11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * net/sched/sch_netem.c	Network emulator
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 		This program is free software; you can redistribute it and/or
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 		modify it under the terms of the GNU General Public License
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 		as published by the Free Software Foundation; either version
7798b6b19d7a4b6e1ea5340ec8b3b92811e05b81bStephen Hemminger * 		2 of the License.
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  		Many of the algorithms and ideas for this came from
1010297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki *		NIST Net which is not copyrighted.
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Authors:	Stephen Hemminger <shemminger@osdl.org>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *		Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16b7f080cfe223b3b7424872639d153695615a9255Alexey Dobriyan#include <linux/mm.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
185a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/skbuff.h>
2378776d3f2b2b6d59e32cdaf3f30228a0d9d0b720David S. Miller#include <linux/vmalloc.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/rtnetlink.h>
2590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer#include <linux/reciprocal_div.h>
26aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet#include <linux/rbtree.h>
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28dc5fc579b90ed0a9a4e55b0218cdbaf0a8cf2e67Arnaldo Carvalho de Melo#include <net/netlink.h>
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/pkt_sched.h>
30e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet#include <net/inet_ecn.h>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
32250a65f78265940ac33a2dd2002924e6126efe14stephen hemminger#define VERSION "1.3"
33eb229c4cdc3389682cda20adb015ba767950a220Stephen Hemminger
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	Network Emulation Queuing algorithm.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	====================================
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 Network Emulation Tool
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 [2] Luigi Rizzo, DummyNet for FreeBSD
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 ----------------------------------------------------------------
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 This started out as a simple way to delay outgoing packets to
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 test TCP but has grown to include most of the functionality
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 of a full blown network emulator like NISTnet. It can delay
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 packets and add random jitter (and correlation). The random
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 distribution can be loaded from a table as well to provide
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 normal, Pareto, or experimental curves. Packet loss,
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 duplication, and reordering can also be emulated.
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 This qdisc does not do classification that can be handled in
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 layering other disciplines.  It does not need to do bandwidth
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 control either since that can be handled by using token
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 bucket or other rate control.
55661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
56661b79725fea030803a89a16cda506bac8eeca78stephen hemminger     Correlated Loss Generator models
57661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
58661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	Added generation of correlated loss according to the
59661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	"Gilbert-Elliot" model, a 4-state markov model.
60661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
61661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	References:
62661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	[1] NetemCLG Home http://netgroup.uniroma2.it/NetemCLG
63661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	[2] S. Salsano, F. Ludovici, A. Ordine, "Definition of a general
64661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	and intuitive loss model for packet networks and its implementation
65661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	in the Netem module in the Linux kernel", available in [1]
66661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
67661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	Authors: Stefano Salsano <stefano.salsano at uniroma2.it
68661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		 Fabio Ludovici <fabio.ludovici at yahoo.it>
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*/
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct netem_sched_data {
72aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	/* internal t(ime)fifo qdisc uses t_root and sch->limit */
73aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct rb_root t_root;
7450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
7550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	/* optional qdisc for classful handling (NULL at netem init) */
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct Qdisc	*qdisc;
7750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
7859cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	struct qdisc_watchdog watchdog;
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
80b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	psched_tdiff_t latency;
81b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	psched_tdiff_t jitter;
82b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 loss;
84e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	u32 ecn;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 limit;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 counter;
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 gap;
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u32 duplicate;
890dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	u32 reorder;
90c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	u32 corrupt;
916a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	u64 rate;
9290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	s32 packet_overhead;
9390b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	u32 cell_size;
94809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa	struct reciprocal_value cell_size_reciprocal;
9590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	s32 cell_overhead;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct crndstate {
98b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger		u32 last;
99b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger		u32 rho;
100c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	} delay_cor, loss_cor, dup_cor, reorder_cor, corrupt_cor;
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct disttable {
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u32  size;
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		s16 table[0];
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} *delay_dist;
106661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
107661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	enum  {
108661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		CLG_RANDOM,
109661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		CLG_4_STATES,
110661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		CLG_GILB_ELL,
111661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	} loss_model;
112661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
113a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	enum {
114a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		TX_IN_GAP_PERIOD = 1,
115a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		TX_IN_BURST_PERIOD,
116a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		LOST_IN_GAP_PERIOD,
117a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		LOST_IN_BURST_PERIOD,
118a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	} _4_state_model;
119a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang
120c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang	enum {
121c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang		GOOD_STATE = 1,
122c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang		BAD_STATE,
123c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang	} GE_state_model;
124c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang
125661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/* Correlated Loss Generation models */
126661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate {
127661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* state of the Markov chain */
128661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u8 state;
129661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
130661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* 4-states and Gilbert-Elliot models */
131661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a1;	/* p13 for 4-states or p for GE */
132661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a2;	/* p31 for 4-states or r for GE */
133661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a3;	/* p32 for 4-states or h for GE */
134661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a4;	/* p14 for 4-states or 1-k for GE */
135661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a5; /* p23 used only in 4-states */
136661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	} clg;
137661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet/* Time stamp put into socket buffer control block
14150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet * Only valid when skbs are in our internal t(ime)fifo queue.
14250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet */
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct netem_skb_cb {
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	psched_time_t	time_to_send;
145aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	ktime_t		tstamp_save;
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
148aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet/* Because space in skb->cb[] is tight, netem overloads skb->next/prev/tstamp
149aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet * to hold a rb_node structure.
150aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet *
151aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet * If struct sk_buff layout is changed, the following checks will complain.
152aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet */
153aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetstatic struct rb_node *netem_rb_node(struct sk_buff *skb)
154aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet{
155aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, next) != 0);
156aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, prev) !=
157aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		     offsetof(struct sk_buff, next) + sizeof(skb->next));
158aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, tstamp) !=
159aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		     offsetof(struct sk_buff, prev) + sizeof(skb->prev));
160aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(sizeof(struct rb_node) > sizeof(skb->next) +
161aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet					      sizeof(skb->prev) +
162aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet					      sizeof(skb->tstamp));
163aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	return (struct rb_node *)&skb->next;
164aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet}
165aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
166aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetstatic struct sk_buff *netem_rb_to_skb(struct rb_node *rb)
167aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet{
168aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	return (struct sk_buff *)rb;
169aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet}
170aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
1715f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinnastatic inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
1725f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna{
173aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	/* we assume we can use skb next/prev/tstamp as storage for rb_node */
17416bda13d90c8d5da243e2cfa1677e62ecce26860David S. Miller	qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
175175f9c1bba9b825d22b142d183c9e175488b260cJussi Kivilinna	return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
1765f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna}
1775f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* init_crandom - initialize correlated random number generator
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use entropy source for initial seed.
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void init_crandom(struct crndstate *state, unsigned long rho)
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->rho = rho;
18463862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	state->last = prandom_u32();
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* get_crandom - correlated random number generator
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Next number depends on last value.
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rho is scaled to avoid floating point.
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
191b407621c35ed5f9a0734e57472e9539117963768Stephen Hemmingerstatic u32 get_crandom(struct crndstate *state)
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 value, rho;
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long answer;
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
196bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	if (state->rho == 0)	/* no correlation */
19763862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		return prandom_u32();
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19963862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	value = prandom_u32();
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rho = (u64)state->rho + 1;
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->last = answer;
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return answer;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
206661b79725fea030803a89a16cda506bac8eeca78stephen hemminger/* loss_4state - 4-state model loss generator
207661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * Generates losses according to the 4-state Markov chain adopted in
208661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * the GI (General and Intuitive) loss model.
209661b79725fea030803a89a16cda506bac8eeca78stephen hemminger */
210661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_4state(struct netem_sched_data *q)
211661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
212661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate *clg = &q->clg;
21363862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	u32 rnd = prandom_u32();
214661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
215661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/*
21625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * Makes a comparison between rnd and the transition
217661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * probabilities outgoing from the current state, then decides the
218661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * next state and if the next packet has to be transmitted or lost.
219661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * The four states correspond to:
220a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   TX_IN_GAP_PERIOD => successfully transmitted packets within a gap period
221a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   LOST_IN_BURST_PERIOD => isolated losses within a gap period
222a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   LOST_IN_GAP_PERIOD => lost packets within a burst period
223a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   TX_IN_GAP_PERIOD => successfully transmitted packets within a burst period
224661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 */
225661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (clg->state) {
226a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case TX_IN_GAP_PERIOD:
227661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a4) {
228a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_BURST_PERIOD;
229661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
230ab6c27be8178a4682446faa5aa017b948997937fstephen hemminger		} else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
231a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
232661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
233a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		} else if (clg->a1 + clg->a4 < rnd) {
234a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_GAP_PERIOD;
235a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		}
236661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
237661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
238a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case TX_IN_BURST_PERIOD:
239661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a5) {
240a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
241661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
242a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		} else {
243a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_BURST_PERIOD;
244a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		}
245661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
246661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
247a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case LOST_IN_GAP_PERIOD:
248661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a3)
249a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_BURST_PERIOD;
250661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
251a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_GAP_PERIOD;
252661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		} else if (clg->a2 + clg->a3 < rnd) {
253a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
254661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
255661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
256661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
257a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case LOST_IN_BURST_PERIOD:
258a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		clg->state = TX_IN_GAP_PERIOD;
259661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
260661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
261661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
262661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;
263661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
264661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
265661b79725fea030803a89a16cda506bac8eeca78stephen hemminger/* loss_gilb_ell - Gilbert-Elliot model loss generator
266661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * Generates losses according to the Gilbert-Elliot loss model or
267661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * its special cases  (Gilbert or Simple Gilbert)
268661b79725fea030803a89a16cda506bac8eeca78stephen hemminger *
26925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * Makes a comparison between random number and the transition
270661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * probabilities outgoing from the current state, then decides the
27125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * next state. A second random number is extracted and the comparison
272661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * with the loss probability of the current state decides if the next
273661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * packet will be transmitted or lost.
274661b79725fea030803a89a16cda506bac8eeca78stephen hemminger */
275661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_gilb_ell(struct netem_sched_data *q)
276661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
277661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate *clg = &q->clg;
278661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
279661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (clg->state) {
280c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang	case GOOD_STATE:
28163862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a1)
282c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang			clg->state = BAD_STATE;
28363862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a4)
284661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
2857c2781fa92f5b9ca3188817a56a2ced0400355f3stephen hemminger		break;
286c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang	case BAD_STATE:
28763862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a2)
288c045a734da4cb6d4665962f252de3d8871136ae9Yang Yingliang			clg->state = GOOD_STATE;
28963862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() > clg->a3)
290661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
291661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
292661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
293661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;
294661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
295661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
296661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_event(struct netem_sched_data *q)
297661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
298661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (q->loss_model) {
299661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_RANDOM:
300661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* Random packet drop 0 => none, ~0 => all */
301661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return q->loss && q->loss >= get_crandom(&q->loss_cor);
302661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
303661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_4_STATES:
304661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* 4state loss model algorithm (used also for GI model)
305661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* Extracts a value from the markov 4 state loss generator,
306661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* if it is 1 drops a packet and if needed writes the event in
307661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* the kernel logs
308661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		*/
309661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return loss_4state(q);
310661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
311661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_GILB_ELL:
312661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* Gilbert-Elliot loss model algorithm
313661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* Extracts a value from the Gilbert-Elliot loss generator,
314661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* if it is 1 drops a packet and if needed writes the event in
315661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* the kernel logs
316661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		*/
317661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return loss_gilb_ell(q);
318661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
319661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
320661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;	/* not reached */
321661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
322661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
323661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tabledist - return a pseudo-randomly distributed value with mean mu and
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * std deviation sigma.  Uses table lookup to approximate the desired
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * distribution, and a uniformly-distributed pseudo-random source.
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
328b407621c35ed5f9a0734e57472e9539117963768Stephen Hemmingerstatic psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
329b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger				struct crndstate *state,
330b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger				const struct disttable *dist)
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
332b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	psched_tdiff_t x;
333b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	long t;
334b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	u32 rnd;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sigma == 0)
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return mu;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rnd = get_crandom(state);
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* default uniform distribution */
34210297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki	if (dist == NULL)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (rnd % (2*sigma)) - sigma + mu;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	t = dist->table[rnd % dist->size];
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x = (sigma % NETEM_DIST_SCALE) * t;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x >= 0)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x += NETEM_DIST_SCALE/2;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x -= NETEM_DIST_SCALE/2;
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeiferstatic psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
3567bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer{
35790b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	u64 ticks;
358fc33cc72423ed3474cd51bc8bd7c1cdc22a78e1aEric Dumazet
35990b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	len += q->packet_overhead;
36090b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
36190b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	if (q->cell_size) {
36290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
36390b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
36490b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
36590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer			cells++;
36690b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		len = cells * (q->cell_size + q->cell_overhead);
36790b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	}
36890b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
36990b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	ticks = (u64)len * NSEC_PER_SEC;
37090b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
37190b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	do_div(ticks, q->rate);
372fc33cc72423ed3474cd51bc8bd7c1cdc22a78e1aEric Dumazet	return PSCHED_NS2TICKS(ticks);
3737bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer}
3747bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
375ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemmingerstatic void tfifo_reset(struct Qdisc *sch)
376ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger{
377ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
378ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	struct rb_node *p;
379ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
380ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	while ((p = rb_first(&q->t_root))) {
381ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		struct sk_buff *skb = netem_rb_to_skb(p);
382ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
383ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		rb_erase(p, &q->t_root);
384ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		skb->next = NULL;
385ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		skb->prev = NULL;
386ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		kfree_skb(skb);
387ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	}
388ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger}
389ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
390960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazetstatic void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
39150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet{
392aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct netem_sched_data *q = qdisc_priv(sch);
39350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	psched_time_t tnext = netem_skb_cb(nskb)->time_to_send;
394aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct rb_node **p = &q->t_root.rb_node, *parent = NULL;
39550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
396aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	while (*p) {
397aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		struct sk_buff *skb;
39850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
399aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		parent = *p;
400aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		skb = netem_rb_to_skb(parent);
401960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		if (tnext >= netem_skb_cb(skb)->time_to_send)
402aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			p = &parent->rb_right;
403aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		else
404aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			p = &parent->rb_left;
40550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
406aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	rb_link_node(netem_rb_node(nskb), parent, p);
407aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	rb_insert_color(netem_rb_node(nskb), &q->t_root);
408aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	sch->q.qlen++;
40950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet}
41050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
4110afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger/*
4120afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * Insert one skb into qdisc.
4130afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * Note: parent depends on return value to account for queue length.
4140afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * 	NET_XMIT_DROP: queue length didn't change.
4150afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger *      NET_XMIT_SUCCESS: one skb was queued.
4160afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
42089e1df74f841fc31e81838d30594c4eff01859f8Guillaume Chazarain	/* We don't fill cb now as skb_unshare() may invalidate it */
42189e1df74f841fc31e81838d30594c4eff01859f8Guillaume Chazarain	struct netem_skb_cb *cb;
4220afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	struct sk_buff *skb2;
4230afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	int count = 1;
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4250afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	/* Random duplication */
4260afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
4270afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		++count;
4280afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger
429661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/* Drop packet? */
430e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (loss_event(q)) {
431e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		if (q->ecn && INET_ECN_set_ce(skb))
43225331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend			qdisc_qstats_drop(sch); /* mark packet */
433e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		else
434e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet			--count;
435e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	}
4360afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (count == 0) {
43725331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend		qdisc_qstats_drop(sch);
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree_skb(skb);
439c27f339af90bb874a7a9c680b17abfd32d4a727bJarek Poplawski		return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4425a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	/* If a delay is expected, orphan the skb. (orphaning usually takes
4435a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	 * place at TX completion time, so _before_ the link transit delay)
4445a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	 */
4455a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	if (q->latency || q->jitter)
446f2f872f9272a79a1048877ea14c15576f46c225eEric Dumazet		skb_orphan_partial(skb);
4474e8a5201506423e0241202de1349422af4260296David S. Miller
4480afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	/*
4490afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * If we need to duplicate packet, then re-insert at top of the
4500afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * qdisc tree, since parent queuer expects that only one
4510afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * skb will be queued.
4520afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 */
4530afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
4547698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller		struct Qdisc *rootq = qdisc_root(sch);
4550afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
4560afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		q->duplicate = 0;
4570afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger
4585f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna		qdisc_enqueue_root(skb2, rootq);
4590afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		q->duplicate = dupsave;
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
462c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	/*
463c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * Randomized packet corruption.
464c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * Make copy if needed since we are modifying
465c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * If packet is going to be hardware checksummed, then
466c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * do it now in software before we mangle it.
467c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 */
468c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
469f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches		if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
470f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches		    (skb->ip_summed == CHECKSUM_PARTIAL &&
471116a0fc31c6c9b8fc821be5a96e5bf0b43260131Eric Dumazet		     skb_checksum_help(skb)))
472116a0fc31c6c9b8fc821be5a96e5bf0b43260131Eric Dumazet			return qdisc_drop(skb, sch);
473c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
47463862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		skb->data[prandom_u32() % skb_headlen(skb)] ^=
47563862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane			1<<(prandom_u32() % 8);
476c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	}
477c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
478960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet	if (unlikely(skb_queue_len(&sch->q) >= sch->limit))
479960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		return qdisc_reshape_fail(skb, sch);
480960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet
48125331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend	qdisc_qstats_backlog_inc(sch, skb);
482960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet
4835f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna	cb = netem_skb_cb(skb);
484cc7ec456f82da7f89a5b376e613b3ac4311b3e9aEric Dumazet	if (q->gap == 0 ||		/* not doing reordering */
485a42b4799c683723e8c464de4026af085b2ebd5faVijay Subramanian	    q->counter < q->gap - 1 ||	/* inside last reordering gap */
486f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    q->reorder < get_crandom(&q->reorder_cor)) {
4870f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger		psched_time_t now;
48807aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		psched_tdiff_t delay;
48907aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger
49007aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		delay = tabledist(q->latency, q->jitter,
49107aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger				  &q->delay_cor, q->delay_dist);
49207aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger
4933bebcda28077375470dd60545b71bba2f83335fdPatrick McHardy		now = psched_get_time();
4947bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
4957bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer		if (q->rate) {
496aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			struct sk_buff *last;
4977bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
498aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			if (!skb_queue_empty(&sch->q))
499aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				last = skb_peek_tail(&sch->q);
500aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			else
501aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				last = netem_rb_to_skb(rb_last(&q->t_root));
502aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			if (last) {
5037bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				/*
504a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				 * Last packet in queue is reference point (now),
505a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				 * calculate this time bonus and subtract
5067bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				 * from delay.
5077bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				 */
508aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				delay -= netem_skb_cb(last)->time_to_send - now;
509a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				delay = max_t(psched_tdiff_t, 0, delay);
510aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				now = netem_skb_cb(last)->time_to_send;
5117bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer			}
512a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab
5138cfd88d6d70735c47b17aef855b4c81dde83c85cYang Yingliang			delay += packet_len_2_sched_time(qdisc_pkt_len(skb), q);
5147bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer		}
5157bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
5167c59e25f3186f26e85b13a318dbc4482d1d363e9Patrick McHardy		cb->time_to_send = now + delay;
517aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		cb->tstamp_save = skb->tstamp;
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++q->counter;
519960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		tfifo_enqueue(skb, sch);
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
52110297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki		/*
5220dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 * Do re-ordering by putting one out of N packets at the front
5230dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 * of the queue.
5240dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 */
5253bebcda28077375470dd60545b71bba2f83335fdPatrick McHardy		cb->time_to_send = psched_get_time();
5260dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		q->counter = 0;
5278ba25dad0ac78850cd46d91186a27d60f7314752Jarek Poplawski
52850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		__skb_queue_head(&sch->q, skb);
529eb10192447370f19a215a8c2749332afa1199d46Hagen Paul Pfeifer		sch->qstats.requeues++;
530378a2f090f7a478704a372a4869b8a9ac206234eJarek Poplawski	}
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return NET_XMIT_SUCCESS;
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
535cc7ec456f82da7f89a5b376e613b3ac4311b3e9aEric Dumazetstatic unsigned int netem_drop(struct Qdisc *sch)
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
53850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	unsigned int len;
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
54050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	len = qdisc_queue_drop(sch);
541aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
542aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	if (!len) {
543aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		struct rb_node *p = rb_first(&q->t_root);
544aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
545aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		if (p) {
546aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			struct sk_buff *skb = netem_rb_to_skb(p);
547aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
548aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			rb_erase(p, &q->t_root);
549aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			sch->q.qlen--;
550aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->next = NULL;
551aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->prev = NULL;
55225331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend			qdisc_qstats_backlog_dec(sch, skb);
553aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			kfree_skb(skb);
554aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		}
555aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	}
55650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (!len && q->qdisc && q->qdisc->ops->drop)
55750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	    len = q->qdisc->ops->drop(q->qdisc);
55850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (len)
55925331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend		qdisc_qstats_drop(sch);
56050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return len;
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sk_buff *netem_dequeue(struct Qdisc *sch)
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
568aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct rb_node *p;
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
570fd245a4adb5288eac37250875f237c40a20a1944Eric Dumazet	if (qdisc_is_throttled(sch))
57111274e5a43266d531140530adebead6903380cafStephen Hemminger		return NULL;
57211274e5a43266d531140530adebead6903380cafStephen Hemminger
57350612537e9ab29693122fab20fc1eed235054ffeEric Dumazettfifo_dequeue:
574aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	skb = __skb_dequeue(&sch->q);
575771018e76aaa6474be20a53c20458bcae8b00485Stephen Hemminger	if (skb) {
576aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetdeliver:
57725331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend		qdisc_qstats_backlog_dec(sch, skb);
578aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		qdisc_unthrottled(sch);
579aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		qdisc_bstats_update(sch, skb);
580aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		return skb;
581aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	}
582aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	p = rb_first(&q->t_root);
583aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	if (p) {
58436b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		psched_time_t time_to_send;
58536b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet
586aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		skb = netem_rb_to_skb(p);
5870f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger
5880f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger		/* if more time remaining? */
58936b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		time_to_send = netem_skb_cb(skb)->time_to_send;
59036b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		if (time_to_send <= psched_get_time()) {
591aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			rb_erase(p, &q->t_root);
592aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
593aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			sch->q.qlen--;
594aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->next = NULL;
595aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->prev = NULL;
596aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->tstamp = netem_skb_cb(skb)->tstamp_save;
59703c05f0d4bb0c267edf12d614025a40e33c5a6f9Jarek Poplawski
5988caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski#ifdef CONFIG_NET_CLS_ACT
5998caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			/*
6008caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 * If it's at ingress let's pretend the delay is
6018caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 * from the network (tstamp will be updated).
6028caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 */
6038caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			if (G_TC_FROM(skb->tc_verd) & AT_INGRESS)
6048caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski				skb->tstamp.tv64 = 0;
6058caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski#endif
60610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
60750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			if (q->qdisc) {
60850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				int err = qdisc_enqueue(skb, q->qdisc);
60950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
61050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				if (unlikely(err != NET_XMIT_SUCCESS)) {
61150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet					if (net_xmit_drop_count(err)) {
61225331d6ce42bcf4b34b6705fce4da15c3fabe62fJohn Fastabend						qdisc_qstats_drop(sch);
61350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet						qdisc_tree_decrease_qlen(sch, 1);
61450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet					}
61550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				}
61650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				goto tfifo_dequeue;
61750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			}
618aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			goto deliver;
61907aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		}
62011274e5a43266d531140530adebead6903380cafStephen Hemminger
62150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		if (q->qdisc) {
62250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			skb = q->qdisc->ops->dequeue(q->qdisc);
62350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			if (skb)
62450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				goto deliver;
62550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		}
62636b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		qdisc_watchdog_schedule(&q->watchdog, time_to_send);
6270f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger	}
6280f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger
62950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc) {
63050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		skb = q->qdisc->ops->dequeue(q->qdisc);
63150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		if (skb)
63250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			goto deliver;
63350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
6340f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger	return NULL;
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void netem_reset(struct Qdisc *sch)
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
64150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	qdisc_reset_queue(sch);
642ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	tfifo_reset(sch);
64350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc)
64450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_reset(q->qdisc);
64559cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_cancel(&q->watchdog);
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6486373a9a286bdd955a76924cee88a2f8f784988b1stephen hemmingerstatic void dist_free(struct disttable *d)
6496373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger{
6504cb28970a23ff209199b0a4358d68efe82c8f493WANG Cong	kvfree(d);
6516373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger}
6526373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Distribution data is a variable size payload containing
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signed 16 bit values.
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6571e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
6606373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	size_t n = nla_len(attr)/sizeof(__s16);
6611e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const __s16 *data = nla_data(attr);
6627698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spinlock_t *root_lock;
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct disttable *d;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6656373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	size_t s;
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
667df173bda2639ac744ccf596ec1f8f7e66fe4c343stephen hemminger	if (n > NETEM_DIST_MAX)
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6706373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	s = sizeof(struct disttable) + n * sizeof(s16);
671bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
6726373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	if (!d)
6736373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger		d = vmalloc(s);
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!d)
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	d->size = n;
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < n; i++)
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d->table[i] = data[i];
68010297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
681102396ae65108b026e4e1868e30fa013f45a169eJarek Poplawski	root_lock = qdisc_root_sleeping_lock(sch);
6827698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller
6837698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spin_lock_bh(root_lock);
684bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	swap(q->delay_dist, d);
6857698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spin_unlock_bh(root_lock);
686bb52c7acf871537a468433775151339f783d2e8cEric Dumazet
687bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	dist_free(d);
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
69149545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliangstatic void get_correlation(struct netem_sched_data *q, const struct nlattr *attr)
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6931e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_corr *c = nla_data(attr);
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->delay_cor, c->delay_corr);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->loss_cor, c->loss_corr);
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->dup_cor, c->dup_corr);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
70049545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliangstatic void get_reorder(struct netem_sched_data *q, const struct nlattr *attr)
7010dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger{
7021e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_reorder *r = nla_data(attr);
7030dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
7040dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	q->reorder = r->probability;
7050dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	init_crandom(&q->reorder_cor, r->correlation);
7060dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger}
7070dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
70849545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliangstatic void get_corrupt(struct netem_sched_data *q, const struct nlattr *attr)
709c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger{
7101e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_corrupt *r = nla_data(attr);
711c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
712c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	q->corrupt = r->probability;
713c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	init_crandom(&q->corrupt_cor, r->correlation);
714c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger}
715c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
71649545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliangstatic void get_rate(struct netem_sched_data *q, const struct nlattr *attr)
7177bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer{
7187bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	const struct tc_netem_rate *r = nla_data(attr);
7197bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
7207bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	q->rate = r->rate;
72190b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	q->packet_overhead = r->packet_overhead;
72290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	q->cell_size = r->cell_size;
723809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa	q->cell_overhead = r->cell_overhead;
72490b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	if (q->cell_size)
72590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
726809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa	else
727809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa		q->cell_size_reciprocal = (struct reciprocal_value) { 0 };
7287bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer}
7297bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
73049545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliangstatic int get_loss_clg(struct netem_sched_data *q, const struct nlattr *attr)
731661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
732661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	const struct nlattr *la;
733661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	int rem;
734661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
735661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_for_each_nested(la, attr, rem) {
736661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u16 type = nla_type(la);
737661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
738833fa7438659d768f0aee862aab4a30cde362bbfYang Yingliang		switch (type) {
739661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		case NETEM_LOSS_GI: {
740661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			const struct tc_netem_gimodel *gi = nla_data(la);
741661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
7422494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger			if (nla_len(la) < sizeof(struct tc_netem_gimodel)) {
743661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				pr_info("netem: incorrect gi model size\n");
744661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				return -EINVAL;
745661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			}
746661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
747661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->loss_model = CLG_4_STATES;
748661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
7493fbac2a87e73e1dfdfa83e18e9601628eec0d676Yang Yingliang			q->clg.state = TX_IN_GAP_PERIOD;
750661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a1 = gi->p13;
751661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a2 = gi->p31;
752661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a3 = gi->p32;
753661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a4 = gi->p14;
754661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a5 = gi->p23;
755661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			break;
756661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
757661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
758661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		case NETEM_LOSS_GE: {
759661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			const struct tc_netem_gemodel *ge = nla_data(la);
760661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
7612494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger			if (nla_len(la) < sizeof(struct tc_netem_gemodel)) {
7622494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger				pr_info("netem: incorrect ge model size\n");
763661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				return -EINVAL;
764661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			}
765661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
766661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->loss_model = CLG_GILB_ELL;
7673fbac2a87e73e1dfdfa83e18e9601628eec0d676Yang Yingliang			q->clg.state = GOOD_STATE;
768661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a1 = ge->p;
769661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a2 = ge->r;
770661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a3 = ge->h;
771661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a4 = ge->k1;
772661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			break;
773661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
774661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
775661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		default:
776661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			pr_info("netem: unknown loss type %u\n", type);
777661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return -EINVAL;
778661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
779661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
780661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
781661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return 0;
782661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
783661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
78427a3421e4821734bc19496faa77b380605dc3b23Patrick McHardystatic const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
78527a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_CORR]	= { .len = sizeof(struct tc_netem_corr) },
78627a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_REORDER]	= { .len = sizeof(struct tc_netem_reorder) },
78727a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_CORRUPT]	= { .len = sizeof(struct tc_netem_corrupt) },
7887bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	[TCA_NETEM_RATE]	= { .len = sizeof(struct tc_netem_rate) },
789661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	[TCA_NETEM_LOSS]	= { .type = NLA_NESTED },
790e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	[TCA_NETEM_ECN]		= { .type = NLA_U32 },
7916a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	[TCA_NETEM_RATE64]	= { .type = NLA_U64 },
79227a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy};
79327a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy
7942c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Grafstatic int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
7952c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		      const struct nla_policy *policy, int len)
7962c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf{
7972c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	int nested_len = nla_len(nla) - NLA_ALIGN(len);
7982c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf
799661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (nested_len < 0) {
800661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		pr_info("netem: invalid attributes len %d\n", nested_len);
8012c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		return -EINVAL;
802661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
803661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
8042c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	if (nested_len >= nla_attr_size(0))
8052c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
8062c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf				 nested_len, policy);
807661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
8082c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
8092c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	return 0;
8102c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf}
8112c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf
812c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger/* Parse netlink message to set options */
8131e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int netem_change(struct Qdisc *sch, struct nlattr *opt)
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
816b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	struct nlattr *tb[TCA_NETEM_MAX + 1];
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_qopt *qopt;
81854a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	struct clgstate old_clg;
81954a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	int old_loss_model = CLG_RANDOM;
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
82110297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
822b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	if (opt == NULL)
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8252c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	qopt = nla_data(opt);
8262c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	ret = parse_attr(tb, TCA_NETEM_MAX, opt, netem_policy, sizeof(*qopt));
827b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	if (ret < 0)
828b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy		return ret;
829b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy
83054a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	/* backup q->clg and q->loss_model */
83154a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	old_clg = q->clg;
83254a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	old_loss_model = q->loss_model;
83354a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang
83454a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	if (tb[TCA_NETEM_LOSS]) {
83549545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliang		ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
83654a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		if (ret) {
83754a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			q->loss_model = old_loss_model;
83854a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			return ret;
83954a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		}
84054a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	} else {
84154a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		q->loss_model = CLG_RANDOM;
84254a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	}
84354a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang
84454a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	if (tb[TCA_NETEM_DELAY_DIST]) {
84554a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
84654a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		if (ret) {
84754a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			/* recover clg and loss_model, in case of
84854a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			 * q->clg and q->loss_model were modified
84954a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			 * in get_loss_clg()
85054a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			 */
85154a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			q->clg = old_clg;
85254a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			q->loss_model = old_loss_model;
85354a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang			return ret;
85454a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang		}
85554a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang	}
85654a4b05cd281a352d803417a98a72878fb0802cfYang Yingliang
85750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	sch->limit = qopt->limit;
85810297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->latency = qopt->latency;
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->jitter = qopt->jitter;
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->limit = qopt->limit;
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->gap = qopt->gap;
8630dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	q->counter = 0;
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->loss = qopt->loss;
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->duplicate = qopt->duplicate;
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
867bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	/* for compatibility with earlier versions.
868bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	 * if gap is set, need to assume 100% probability
8690dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	 */
870a362e0a7890c735a3ef63aab12d71ecfc6e6f4a5Stephen Hemminger	if (q->gap)
871a362e0a7890c735a3ef63aab12d71ecfc6e6f4a5Stephen Hemminger		q->reorder = ~0;
8720dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
873265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_CORR])
87449545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliang		get_correlation(q, tb[TCA_NETEM_CORR]);
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
876265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_REORDER])
87749545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliang		get_reorder(q, tb[TCA_NETEM_REORDER]);
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
879265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_CORRUPT])
88049545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliang		get_corrupt(q, tb[TCA_NETEM_CORRUPT]);
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8827bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	if (tb[TCA_NETEM_RATE])
88349545a7775e746e4e32d1524801221ffdfe1cc0aYang Yingliang		get_rate(q, tb[TCA_NETEM_RATE]);
8847bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
8856a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	if (tb[TCA_NETEM_RATE64])
8866a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		q->rate = max_t(u64, q->rate,
8876a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang				nla_get_u64(tb[TCA_NETEM_RATE64]));
8886a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang
889e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (tb[TCA_NETEM_ECN])
890e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
891e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet
892661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return ret;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8951e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int netem_init(struct Qdisc *sch, struct nlattr *opt)
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!opt)
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90359cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_init(&q->watchdog, sch);
9041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
905661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	q->loss_model = CLG_RANDOM;
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = netem_change(sch, opt);
90750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (ret)
908250a65f78265940ac33a2dd2002924e6126efe14stephen hemminger		pr_info("netem: change failed\n");
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void netem_destroy(struct Qdisc *sch)
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
91659cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_cancel(&q->watchdog);
91750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc)
91850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_destroy(q->qdisc);
9196373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	dist_free(q->delay_dist);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
922661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic int dump_loss_model(const struct netem_sched_data *q,
923661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			   struct sk_buff *skb)
924661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
925661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct nlattr *nest;
926661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
927661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nest = nla_nest_start(skb, TCA_NETEM_LOSS);
928661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (nest == NULL)
929661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		goto nla_put_failure;
930661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
931661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (q->loss_model) {
932661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_RANDOM:
933661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* legacy loss model */
934661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		nla_nest_cancel(skb, nest);
935661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return 0;	/* no data */
936661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
937661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_4_STATES: {
938661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		struct tc_netem_gimodel gi = {
939661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p13 = q->clg.a1,
940661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p31 = q->clg.a2,
941661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p32 = q->clg.a3,
942661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p14 = q->clg.a4,
943661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p23 = q->clg.a5,
944661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		};
945661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9461b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		if (nla_put(skb, NETEM_LOSS_GI, sizeof(gi), &gi))
9471b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller			goto nla_put_failure;
948661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
949661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
950661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_GILB_ELL: {
951661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		struct tc_netem_gemodel ge = {
952661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p = q->clg.a1,
953661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.r = q->clg.a2,
954661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.h = q->clg.a3,
955661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.k1 = q->clg.a4,
956661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		};
957661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9581b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		if (nla_put(skb, NETEM_LOSS_GE, sizeof(ge), &ge))
9591b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller			goto nla_put_failure;
960661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
961661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
962661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
963661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
964661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_nest_end(skb, nest);
965661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return 0;
966661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
967661b79725fea030803a89a16cda506bac8eeca78stephen hemmingernla_put_failure:
968661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_nest_cancel(skb, nest);
969661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return -1;
970661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
971661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct netem_sched_data *q = qdisc_priv(sch);
975861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_qopt qopt;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_corr cor;
9780dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	struct tc_netem_reorder reorder;
979c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	struct tc_netem_corrupt corrupt;
9807bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	struct tc_netem_rate rate;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.latency = q->latency;
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.jitter = q->jitter;
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.limit = q->limit;
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.loss = q->loss;
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.gap = q->gap;
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.duplicate = q->duplicate;
9881b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
9891b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.delay_corr = q->delay_cor.rho;
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.loss_corr = q->loss_cor.rho;
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.dup_corr = q->dup_cor.rho;
9941b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_CORR, sizeof(cor), &cor))
9951b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
9960dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
9970dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	reorder.probability = q->reorder;
9980dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	reorder.correlation = q->reorder_cor.rho;
9991b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder))
10001b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
10010dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
1002c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	corrupt.probability = q->corrupt;
1003c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	corrupt.correlation = q->corrupt_cor.rho;
10041b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt))
10051b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
1006c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
10076a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	if (q->rate >= (1ULL << 32)) {
10086a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		if (nla_put_u64(skb, TCA_NETEM_RATE64, q->rate))
10096a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang			goto nla_put_failure;
10106a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		rate.rate = ~0U;
10116a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	} else {
10126a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		rate.rate = q->rate;
10136a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	}
101490b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.packet_overhead = q->packet_overhead;
101590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.cell_size = q->cell_size;
101690b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.cell_overhead = q->cell_overhead;
10171b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate))
10181b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
10197bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
1020e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn))
1021e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		goto nla_put_failure;
1022e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet
1023661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (dump_loss_model(q, skb) != 0)
1024661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		goto nla_put_failure;
1025661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
1026861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	return nla_nest_end(skb, nla);
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10281e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardynla_put_failure:
1029861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	nlmsg_trim(skb, nla);
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
103310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic int netem_dump_class(struct Qdisc *sch, unsigned long cl,
103410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			  struct sk_buff *skb, struct tcmsg *tcm)
103510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
103610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
103710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
103850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (cl != 1 || !q->qdisc) 	/* only one class */
103910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		return -ENOENT;
104010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
104110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	tcm->tcm_handle |= TC_H_MIN(1);
104210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	tcm->tcm_info = q->qdisc->handle;
104310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
104410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 0;
104510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
104610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
104710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
104810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		     struct Qdisc **old)
104910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
105010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
105110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
105210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	sch_tree_lock(sch);
105310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	*old = q->qdisc;
105410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	q->qdisc = new;
105550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (*old) {
105650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
105750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_reset(*old);
105850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
105910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	sch_tree_unlock(sch);
106010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
106110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 0;
106210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
106310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
106410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
106510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
106610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
106710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return q->qdisc;
106810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
106910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
107010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic unsigned long netem_get(struct Qdisc *sch, u32 classid)
107110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
107210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 1;
107310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
107410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
107510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic void netem_put(struct Qdisc *sch, unsigned long arg)
107610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
107710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
107810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
107910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
108010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
108110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	if (!walker->stop) {
108210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		if (walker->count >= walker->skip)
108310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			if (walker->fn(sch, 1, walker) < 0) {
108410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger				walker->stop = 1;
108510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger				return;
108610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			}
108710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		walker->count++;
108810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	}
108910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
109010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
109110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic const struct Qdisc_class_ops netem_class_ops = {
109210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.graft		=	netem_graft,
109310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.leaf		=	netem_leaf,
109410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.get		=	netem_get,
109510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.put		=	netem_put,
109610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.walk		=	netem_walk,
109710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.dump		=	netem_dump_class,
109810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger};
109910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
110020fea08b5fb639c4c175b5c74a2bb346c5c5bc2eEric Dumazetstatic struct Qdisc_ops netem_qdisc_ops __read_mostly = {
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id		=	"netem",
110210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.cl_ops		=	&netem_class_ops,
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.priv_size	=	sizeof(struct netem_sched_data),
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.enqueue	=	netem_enqueue,
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dequeue	=	netem_dequeue,
110677be155cba4e163e8bba9fd27222a8b6189ec4f7Jarek Poplawski	.peek		=	qdisc_peek_dequeued,
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drop		=	netem_drop,
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		=	netem_init,
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.reset		=	netem_reset,
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.destroy	=	netem_destroy,
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.change		=	netem_change,
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dump		=	netem_dump,
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		=	THIS_MODULE,
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init netem_module_init(void)
11181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1119eb229c4cdc3389682cda20adb015ba767950a220Stephen Hemminger	pr_info("netem: version " VERSION "\n");
11201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return register_qdisc(&netem_qdisc_ops);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit netem_module_exit(void)
11231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_qdisc(&netem_qdisc_ops);
11251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(netem_module_init)
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(netem_module_exit)
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1129