sch_netem.c revision 809fa972fd90ff27225294b17a027e908b2d7b7a
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
120661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/* Correlated Loss Generation models */
121661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate {
122661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* state of the Markov chain */
123661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u8 state;
124661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
125661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* 4-states and Gilbert-Elliot models */
126661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a1;	/* p13 for 4-states or p for GE */
127661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a2;	/* p31 for 4-states or r for GE */
128661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a3;	/* p32 for 4-states or h for GE */
129661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a4;	/* p14 for 4-states or 1-k for GE */
130661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u32 a5; /* p23 used only in 4-states */
131661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	} clg;
132661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet/* Time stamp put into socket buffer control block
13650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet * Only valid when skbs are in our internal t(ime)fifo queue.
13750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet */
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct netem_skb_cb {
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	psched_time_t	time_to_send;
140aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	ktime_t		tstamp_save;
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
143aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet/* Because space in skb->cb[] is tight, netem overloads skb->next/prev/tstamp
144aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet * to hold a rb_node structure.
145aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet *
146aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet * If struct sk_buff layout is changed, the following checks will complain.
147aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet */
148aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetstatic struct rb_node *netem_rb_node(struct sk_buff *skb)
149aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet{
150aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, next) != 0);
151aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, prev) !=
152aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		     offsetof(struct sk_buff, next) + sizeof(skb->next));
153aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(offsetof(struct sk_buff, tstamp) !=
154aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		     offsetof(struct sk_buff, prev) + sizeof(skb->prev));
155aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	BUILD_BUG_ON(sizeof(struct rb_node) > sizeof(skb->next) +
156aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet					      sizeof(skb->prev) +
157aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet					      sizeof(skb->tstamp));
158aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	return (struct rb_node *)&skb->next;
159aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet}
160aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
161aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetstatic struct sk_buff *netem_rb_to_skb(struct rb_node *rb)
162aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet{
163aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	return (struct sk_buff *)rb;
164aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet}
165aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
1665f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinnastatic inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
1675f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna{
168aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	/* we assume we can use skb next/prev/tstamp as storage for rb_node */
16916bda13d90c8d5da243e2cfa1677e62ecce26860David S. Miller	qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
170175f9c1bba9b825d22b142d183c9e175488b260cJussi Kivilinna	return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
1715f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna}
1725f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* init_crandom - initialize correlated random number generator
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Use entropy source for initial seed.
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void init_crandom(struct crndstate *state, unsigned long rho)
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->rho = rho;
17963862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	state->last = prandom_u32();
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* get_crandom - correlated random number generator
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Next number depends on last value.
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * rho is scaled to avoid floating point.
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
186b407621c35ed5f9a0734e57472e9539117963768Stephen Hemmingerstatic u32 get_crandom(struct crndstate *state)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u64 value, rho;
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long answer;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	if (state->rho == 0)	/* no correlation */
19263862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		return prandom_u32();
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19463862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	value = prandom_u32();
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rho = (u64)state->rho + 1;
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	state->last = answer;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return answer;
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
201661b79725fea030803a89a16cda506bac8eeca78stephen hemminger/* loss_4state - 4-state model loss generator
202661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * Generates losses according to the 4-state Markov chain adopted in
203661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * the GI (General and Intuitive) loss model.
204661b79725fea030803a89a16cda506bac8eeca78stephen hemminger */
205661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_4state(struct netem_sched_data *q)
206661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
207661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate *clg = &q->clg;
20863862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane	u32 rnd = prandom_u32();
209661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
210661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/*
21125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	 * Makes a comparison between rnd and the transition
212661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * probabilities outgoing from the current state, then decides the
213661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * next state and if the next packet has to be transmitted or lost.
214661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 * The four states correspond to:
215a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   TX_IN_GAP_PERIOD => successfully transmitted packets within a gap period
216a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   LOST_IN_BURST_PERIOD => isolated losses within a gap period
217a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   LOST_IN_GAP_PERIOD => lost packets within a burst period
218a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	 *   TX_IN_GAP_PERIOD => successfully transmitted packets within a burst period
219661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	 */
220661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (clg->state) {
221a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case TX_IN_GAP_PERIOD:
222661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a4) {
223a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_BURST_PERIOD;
224661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
225ab6c27be8178a4682446faa5aa017b948997937fstephen hemminger		} else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
226a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
227661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
228a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		} else if (clg->a1 + clg->a4 < rnd) {
229a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_GAP_PERIOD;
230a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		}
231661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
232661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
233a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case TX_IN_BURST_PERIOD:
234661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a5) {
235a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
236661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
237a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		} else {
238a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_BURST_PERIOD;
239a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		}
240661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
241661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
242a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case LOST_IN_GAP_PERIOD:
243661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		if (rnd < clg->a3)
244a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_BURST_PERIOD;
245661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
246a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = TX_IN_GAP_PERIOD;
247661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		} else if (clg->a2 + clg->a3 < rnd) {
248a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang			clg->state = LOST_IN_GAP_PERIOD;
249661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
250661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
251661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
252a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang	case LOST_IN_BURST_PERIOD:
253a6e2fe17eba47681e82cdb9cfed5a67b57802a78Yang Yingliang		clg->state = TX_IN_GAP_PERIOD;
254661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
255661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
256661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
257661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;
258661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
259661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
260661b79725fea030803a89a16cda506bac8eeca78stephen hemminger/* loss_gilb_ell - Gilbert-Elliot model loss generator
261661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * Generates losses according to the Gilbert-Elliot loss model or
262661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * its special cases  (Gilbert or Simple Gilbert)
263661b79725fea030803a89a16cda506bac8eeca78stephen hemminger *
26425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * Makes a comparison between random number and the transition
265661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * probabilities outgoing from the current state, then decides the
26625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * next state. A second random number is extracted and the comparison
267661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * with the loss probability of the current state decides if the next
268661b79725fea030803a89a16cda506bac8eeca78stephen hemminger * packet will be transmitted or lost.
269661b79725fea030803a89a16cda506bac8eeca78stephen hemminger */
270661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_gilb_ell(struct netem_sched_data *q)
271661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
272661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct clgstate *clg = &q->clg;
273661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
274661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (clg->state) {
275661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case 1:
27663862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a1)
277661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			clg->state = 2;
27863862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a4)
279661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
2807c2781fa92f5b9ca3188817a56a2ced0400355f3stephen hemminger		break;
281661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case 2:
28263862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() < clg->a2)
283661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			clg->state = 1;
28463862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		if (prandom_u32() > clg->a3)
285661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return true;
286661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
287661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
288661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;
289661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
290661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
291661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic bool loss_event(struct netem_sched_data *q)
292661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
293661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (q->loss_model) {
294661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_RANDOM:
295661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* Random packet drop 0 => none, ~0 => all */
296661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return q->loss && q->loss >= get_crandom(&q->loss_cor);
297661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
298661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_4_STATES:
299661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* 4state loss model algorithm (used also for GI model)
300661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* Extracts a value from the markov 4 state loss generator,
301661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* if it is 1 drops a packet and if needed writes the event in
302661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* the kernel logs
303661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		*/
304661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return loss_4state(q);
305661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
306661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_GILB_ELL:
307661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* Gilbert-Elliot loss model algorithm
308661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* Extracts a value from the Gilbert-Elliot loss generator,
309661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* if it is 1 drops a packet and if needed writes the event in
310661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		* the kernel logs
311661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		*/
312661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return loss_gilb_ell(q);
313661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
314661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
315661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return false;	/* not reached */
316661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
317661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
318661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* tabledist - return a pseudo-randomly distributed value with mean mu and
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * std deviation sigma.  Uses table lookup to approximate the desired
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * distribution, and a uniformly-distributed pseudo-random source.
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
323b407621c35ed5f9a0734e57472e9539117963768Stephen Hemmingerstatic psched_tdiff_t tabledist(psched_tdiff_t mu, psched_tdiff_t sigma,
324b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger				struct crndstate *state,
325b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger				const struct disttable *dist)
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
327b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	psched_tdiff_t x;
328b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	long t;
329b407621c35ed5f9a0734e57472e9539117963768Stephen Hemminger	u32 rnd;
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (sigma == 0)
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return mu;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	rnd = get_crandom(state);
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* default uniform distribution */
33710297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki	if (dist == NULL)
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (rnd % (2*sigma)) - sigma + mu;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	t = dist->table[rnd % dist->size];
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	x = (sigma % NETEM_DIST_SCALE) * t;
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (x >= 0)
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x += NETEM_DIST_SCALE/2;
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		x -= NETEM_DIST_SCALE/2;
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return  x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
35090b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeiferstatic psched_time_t packet_len_2_sched_time(unsigned int len, struct netem_sched_data *q)
3517bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer{
35290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	u64 ticks;
353fc33cc72423ed3474cd51bc8bd7c1cdc22a78e1aEric Dumazet
35490b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	len += q->packet_overhead;
35590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
35690b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	if (q->cell_size) {
35790b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
35890b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
35990b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		if (len > cells * q->cell_size)	/* extra cell needed for remainder */
36090b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer			cells++;
36190b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		len = cells * (q->cell_size + q->cell_overhead);
36290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	}
36390b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
36490b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	ticks = (u64)len * NSEC_PER_SEC;
36590b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer
36690b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	do_div(ticks, q->rate);
367fc33cc72423ed3474cd51bc8bd7c1cdc22a78e1aEric Dumazet	return PSCHED_NS2TICKS(ticks);
3687bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer}
3697bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
370ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemmingerstatic void tfifo_reset(struct Qdisc *sch)
371ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger{
372ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
373ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	struct rb_node *p;
374ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
375ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	while ((p = rb_first(&q->t_root))) {
376ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		struct sk_buff *skb = netem_rb_to_skb(p);
377ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
378ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		rb_erase(p, &q->t_root);
379ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		skb->next = NULL;
380ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		skb->prev = NULL;
381ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger		kfree_skb(skb);
382ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	}
383ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger}
384ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger
385960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazetstatic void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
38650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet{
387aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct netem_sched_data *q = qdisc_priv(sch);
38850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	psched_time_t tnext = netem_skb_cb(nskb)->time_to_send;
389aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct rb_node **p = &q->t_root.rb_node, *parent = NULL;
39050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
391aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	while (*p) {
392aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		struct sk_buff *skb;
39350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
394aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		parent = *p;
395aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		skb = netem_rb_to_skb(parent);
396960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		if (tnext >= netem_skb_cb(skb)->time_to_send)
397aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			p = &parent->rb_right;
398aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		else
399aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			p = &parent->rb_left;
40050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
401aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	rb_link_node(netem_rb_node(nskb), parent, p);
402aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	rb_insert_color(netem_rb_node(nskb), &q->t_root);
403aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	sch->q.qlen++;
40450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet}
40550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
4060afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger/*
4070afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * Insert one skb into qdisc.
4080afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * Note: parent depends on return value to account for queue length.
4090afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger * 	NET_XMIT_DROP: queue length didn't change.
4100afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger *      NET_XMIT_SUCCESS: one skb was queued.
4110afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger */
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch)
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
41589e1df74f841fc31e81838d30594c4eff01859f8Guillaume Chazarain	/* We don't fill cb now as skb_unshare() may invalidate it */
41689e1df74f841fc31e81838d30594c4eff01859f8Guillaume Chazarain	struct netem_skb_cb *cb;
4170afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	struct sk_buff *skb2;
4180afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	int count = 1;
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4200afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	/* Random duplication */
4210afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
4220afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		++count;
4230afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger
424661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	/* Drop packet? */
425e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (loss_event(q)) {
426e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		if (q->ecn && INET_ECN_set_ce(skb))
427e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet			sch->qstats.drops++; /* mark packet */
428e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		else
429e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet			--count;
430e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	}
4310afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (count == 0) {
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sch->qstats.drops++;
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		kfree_skb(skb);
434c27f339af90bb874a7a9c680b17abfd32d4a727bJarek Poplawski		return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4375a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	/* If a delay is expected, orphan the skb. (orphaning usually takes
4385a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	 * place at TX completion time, so _before_ the link transit delay)
4395a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	 */
4405a308f40bfe27fcfd1db3970afe18b635f23c182Eric Dumazet	if (q->latency || q->jitter)
441f2f872f9272a79a1048877ea14c15576f46c225eEric Dumazet		skb_orphan_partial(skb);
4424e8a5201506423e0241202de1349422af4260296David S. Miller
4430afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	/*
4440afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * If we need to duplicate packet, then re-insert at top of the
4450afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * qdisc tree, since parent queuer expects that only one
4460afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 * skb will be queued.
4470afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	 */
4480afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger	if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
4497698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller		struct Qdisc *rootq = qdisc_root(sch);
4500afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
4510afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		q->duplicate = 0;
4520afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger
4535f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna		qdisc_enqueue_root(skb2, rootq);
4540afb51e72855971dba83b3c6b70c547c2d1161fdStephen Hemminger		q->duplicate = dupsave;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
457c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	/*
458c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * Randomized packet corruption.
459c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * Make copy if needed since we are modifying
460c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * If packet is going to be hardware checksummed, then
461c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 * do it now in software before we mangle it.
462c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	 */
463c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
464f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches		if (!(skb = skb_unshare(skb, GFP_ATOMIC)) ||
465f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches		    (skb->ip_summed == CHECKSUM_PARTIAL &&
466116a0fc31c6c9b8fc821be5a96e5bf0b43260131Eric Dumazet		     skb_checksum_help(skb)))
467116a0fc31c6c9b8fc821be5a96e5bf0b43260131Eric Dumazet			return qdisc_drop(skb, sch);
468c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
46963862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane		skb->data[prandom_u32() % skb_headlen(skb)] ^=
47063862b5bef7349dd1137e4c70702c67d77565785Aruna-Hewapathirane			1<<(prandom_u32() % 8);
471c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	}
472c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
473960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet	if (unlikely(skb_queue_len(&sch->q) >= sch->limit))
474960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		return qdisc_reshape_fail(skb, sch);
475960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet
476960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet	sch->qstats.backlog += qdisc_pkt_len(skb);
477960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet
4785f86173bdf15981ca49d0434f638b68f70a35644Jussi Kivilinna	cb = netem_skb_cb(skb);
479cc7ec456f82da7f89a5b376e613b3ac4311b3e9aEric Dumazet	if (q->gap == 0 ||		/* not doing reordering */
480a42b4799c683723e8c464de4026af085b2ebd5faVijay Subramanian	    q->counter < q->gap - 1 ||	/* inside last reordering gap */
481f64f9e719261a87818dd192a3a2352e5b20fbd0fJoe Perches	    q->reorder < get_crandom(&q->reorder_cor)) {
4820f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger		psched_time_t now;
48307aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		psched_tdiff_t delay;
48407aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger
48507aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		delay = tabledist(q->latency, q->jitter,
48607aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger				  &q->delay_cor, q->delay_dist);
48707aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger
4883bebcda28077375470dd60545b71bba2f83335fdPatrick McHardy		now = psched_get_time();
4897bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
4907bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer		if (q->rate) {
491aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			struct sk_buff *last;
4927bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
493aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			if (!skb_queue_empty(&sch->q))
494aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				last = skb_peek_tail(&sch->q);
495aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			else
496aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				last = netem_rb_to_skb(rb_last(&q->t_root));
497aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			if (last) {
4987bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				/*
499a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				 * Last packet in queue is reference point (now),
500a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				 * calculate this time bonus and subtract
5017bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				 * from delay.
5027bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer				 */
503aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				delay -= netem_skb_cb(last)->time_to_send - now;
504a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab				delay = max_t(psched_tdiff_t, 0, delay);
505aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet				now = netem_skb_cb(last)->time_to_send;
5067bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer			}
507a13d3104710184ecc43edc35a25ae8092058463fJohannes Naab
5088cfd88d6d70735c47b17aef855b4c81dde83c85cYang Yingliang			delay += packet_len_2_sched_time(qdisc_pkt_len(skb), q);
5097bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer		}
5107bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
5117c59e25f3186f26e85b13a318dbc4482d1d363e9Patrick McHardy		cb->time_to_send = now + delay;
512aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		cb->tstamp_save = skb->tstamp;
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		++q->counter;
514960fb66e520a405dde39ff883f17ff2669c13d85Eric Dumazet		tfifo_enqueue(skb, sch);
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
51610297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki		/*
5170dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 * Do re-ordering by putting one out of N packets at the front
5180dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 * of the queue.
5190dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		 */
5203bebcda28077375470dd60545b71bba2f83335fdPatrick McHardy		cb->time_to_send = psched_get_time();
5210dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger		q->counter = 0;
5228ba25dad0ac78850cd46d91186a27d60f7314752Jarek Poplawski
52350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		__skb_queue_head(&sch->q, skb);
524eb10192447370f19a215a8c2749332afa1199d46Hagen Paul Pfeifer		sch->qstats.requeues++;
525378a2f090f7a478704a372a4869b8a9ac206234eJarek Poplawski	}
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
52710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return NET_XMIT_SUCCESS;
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
530cc7ec456f82da7f89a5b376e613b3ac4311b3e9aEric Dumazetstatic unsigned int netem_drop(struct Qdisc *sch)
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
53350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	unsigned int len;
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
53550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	len = qdisc_queue_drop(sch);
536aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
537aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	if (!len) {
538aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		struct rb_node *p = rb_first(&q->t_root);
539aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
540aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		if (p) {
541aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			struct sk_buff *skb = netem_rb_to_skb(p);
542aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
543aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			rb_erase(p, &q->t_root);
544aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			sch->q.qlen--;
545aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->next = NULL;
546aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->prev = NULL;
547aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			len = qdisc_pkt_len(skb);
548638a52b801e40ed276ceb69b73579ad99365361astephen hemminger			sch->qstats.backlog -= len;
549aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			kfree_skb(skb);
550aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		}
551aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	}
55250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (!len && q->qdisc && q->qdisc->ops->drop)
55350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	    len = q->qdisc->ops->drop(q->qdisc);
55450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (len)
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sch->qstats.drops++;
55650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return len;
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sk_buff *netem_dequeue(struct Qdisc *sch)
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
564aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	struct rb_node *p;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
566fd245a4adb5288eac37250875f237c40a20a1944Eric Dumazet	if (qdisc_is_throttled(sch))
56711274e5a43266d531140530adebead6903380cafStephen Hemminger		return NULL;
56811274e5a43266d531140530adebead6903380cafStephen Hemminger
56950612537e9ab29693122fab20fc1eed235054ffeEric Dumazettfifo_dequeue:
570aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	skb = __skb_dequeue(&sch->q);
571771018e76aaa6474be20a53c20458bcae8b00485Stephen Hemminger	if (skb) {
572aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazetdeliver:
573aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		sch->qstats.backlog -= qdisc_pkt_len(skb);
574aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		qdisc_unthrottled(sch);
575aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		qdisc_bstats_update(sch, skb);
576aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		return skb;
577aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	}
578aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	p = rb_first(&q->t_root);
579aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet	if (p) {
58036b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		psched_time_t time_to_send;
58136b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet
582aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet		skb = netem_rb_to_skb(p);
5830f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger
5840f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger		/* if more time remaining? */
58536b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		time_to_send = netem_skb_cb(skb)->time_to_send;
58636b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		if (time_to_send <= psched_get_time()) {
587aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			rb_erase(p, &q->t_root);
588aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet
589aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			sch->q.qlen--;
590aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->next = NULL;
591aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->prev = NULL;
592aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			skb->tstamp = netem_skb_cb(skb)->tstamp_save;
59303c05f0d4bb0c267edf12d614025a40e33c5a6f9Jarek Poplawski
5948caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski#ifdef CONFIG_NET_CLS_ACT
5958caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			/*
5968caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 * If it's at ingress let's pretend the delay is
5978caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 * from the network (tstamp will be updated).
5988caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			 */
5998caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski			if (G_TC_FROM(skb->tc_verd) & AT_INGRESS)
6008caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski				skb->tstamp.tv64 = 0;
6018caf153974f2274301e583fda732cc8e5b80331fJarek Poplawski#endif
60210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
60350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			if (q->qdisc) {
60450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				int err = qdisc_enqueue(skb, q->qdisc);
60550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet
60650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				if (unlikely(err != NET_XMIT_SUCCESS)) {
60750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet					if (net_xmit_drop_count(err)) {
60850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet						sch->qstats.drops++;
60950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet						qdisc_tree_decrease_qlen(sch, 1);
61050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet					}
61150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				}
61250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				goto tfifo_dequeue;
61350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			}
614aec0a40a6f78843c0ce73f7398230ee5184f896dEric Dumazet			goto deliver;
61507aaa11540828f4482c09e1a936a1f63cdb9fc9dStephen Hemminger		}
61611274e5a43266d531140530adebead6903380cafStephen Hemminger
61750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		if (q->qdisc) {
61850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			skb = q->qdisc->ops->dequeue(q->qdisc);
61950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			if (skb)
62050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet				goto deliver;
62150612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		}
62236b7bfe09b6deb71bf387852465245783c9a6208Eric Dumazet		qdisc_watchdog_schedule(&q->watchdog, time_to_send);
6230f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger	}
6240f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger
62550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc) {
62650612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		skb = q->qdisc->ops->dequeue(q->qdisc);
62750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		if (skb)
62850612537e9ab29693122fab20fc1eed235054ffeEric Dumazet			goto deliver;
62950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
6300f9f32ac65ee4a452a912a8440cebbc4dff73852Stephen Hemminger	return NULL;
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void netem_reset(struct Qdisc *sch)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
63750612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	qdisc_reset_queue(sch);
638ff704050f2fc0f3382b5a70bba56a51a3feca79dstephen hemminger	tfifo_reset(sch);
63950612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc)
64050612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_reset(q->qdisc);
64159cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_cancel(&q->watchdog);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6446373a9a286bdd955a76924cee88a2f8f784988b1stephen hemmingerstatic void dist_free(struct disttable *d)
6456373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger{
6466373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	if (d) {
6476373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger		if (is_vmalloc_addr(d))
6486373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger			vfree(d);
6496373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger		else
6506373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger			kfree(d);
6516373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	}
6526373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger}
6536373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Distribution data is a variable size payload containing
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * signed 16 bit values.
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
6581e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
6616373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	size_t n = nla_len(attr)/sizeof(__s16);
6621e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const __s16 *data = nla_data(attr);
6637698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spinlock_t *root_lock;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct disttable *d;
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
6666373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	size_t s;
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
668df173bda2639ac744ccf596ec1f8f7e66fe4c343stephen hemminger	if (n > NETEM_DIST_MAX)
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6716373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	s = sizeof(struct disttable) + n * sizeof(s16);
672bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
6736373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	if (!d)
6746373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger		d = vmalloc(s);
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!d)
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENOMEM;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	d->size = n;
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	for (i = 0; i < n; i++)
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		d->table[i] = data[i];
68110297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
682102396ae65108b026e4e1868e30fa013f45a169eJarek Poplawski	root_lock = qdisc_root_sleeping_lock(sch);
6837698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller
6847698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spin_lock_bh(root_lock);
685bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	swap(q->delay_dist, d);
6867698b4fcabcd790efc4f226bada1e7b5870653afDavid S. Miller	spin_unlock_bh(root_lock);
687bb52c7acf871537a468433775151339f783d2e8cEric Dumazet
688bb52c7acf871537a468433775151339f783d2e8cEric Dumazet	dist_free(d);
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
692265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemmingerstatic void get_correlation(struct Qdisc *sch, const struct nlattr *attr)
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
6951e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_corr *c = nla_data(attr);
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->delay_cor, c->delay_corr);
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->loss_cor, c->loss_corr);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_crandom(&q->dup_cor, c->dup_corr);
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
702265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemmingerstatic void get_reorder(struct Qdisc *sch, const struct nlattr *attr)
7030dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger{
7040dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	struct netem_sched_data *q = qdisc_priv(sch);
7051e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_reorder *r = nla_data(attr);
7060dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
7070dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	q->reorder = r->probability;
7080dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	init_crandom(&q->reorder_cor, r->correlation);
7090dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger}
7100dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
711265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemmingerstatic void get_corrupt(struct Qdisc *sch, const struct nlattr *attr)
712c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger{
713c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	struct netem_sched_data *q = qdisc_priv(sch);
7141e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardy	const struct tc_netem_corrupt *r = nla_data(attr);
715c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
716c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	q->corrupt = r->probability;
717c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	init_crandom(&q->corrupt_cor, r->correlation);
718c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger}
719c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
7207bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeiferstatic void get_rate(struct Qdisc *sch, const struct nlattr *attr)
7217bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer{
7227bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	struct netem_sched_data *q = qdisc_priv(sch);
7237bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	const struct tc_netem_rate *r = nla_data(attr);
7247bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
7257bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	q->rate = r->rate;
72690b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	q->packet_overhead = r->packet_overhead;
72790b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	q->cell_size = r->cell_size;
728809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa	q->cell_overhead = r->cell_overhead;
72990b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	if (q->cell_size)
73090b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer		q->cell_size_reciprocal = reciprocal_value(q->cell_size);
731809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa	else
732809fa972fd90ff27225294b17a027e908b2d7b7aHannes Frederic Sowa		q->cell_size_reciprocal = (struct reciprocal_value) { 0 };
7337bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer}
7347bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
735661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr)
736661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
737661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
738661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	const struct nlattr *la;
739661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	int rem;
740661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
741661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_for_each_nested(la, attr, rem) {
742661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		u16 type = nla_type(la);
743661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
744833fa7438659d768f0aee862aab4a30cde362bbfYang Yingliang		switch (type) {
745661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		case NETEM_LOSS_GI: {
746661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			const struct tc_netem_gimodel *gi = nla_data(la);
747661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
7482494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger			if (nla_len(la) < sizeof(struct tc_netem_gimodel)) {
749661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				pr_info("netem: incorrect gi model size\n");
750661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				return -EINVAL;
751661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			}
752661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
753661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->loss_model = CLG_4_STATES;
754661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
755661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.state = 1;
756661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a1 = gi->p13;
757661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a2 = gi->p31;
758661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a3 = gi->p32;
759661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a4 = gi->p14;
760661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a5 = gi->p23;
761661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			break;
762661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
763661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
764661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		case NETEM_LOSS_GE: {
765661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			const struct tc_netem_gemodel *ge = nla_data(la);
766661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
7672494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger			if (nla_len(la) < sizeof(struct tc_netem_gemodel)) {
7682494654d4890316e7340fb8b3458daad0474a1b9stephen hemminger				pr_info("netem: incorrect ge model size\n");
769661b79725fea030803a89a16cda506bac8eeca78stephen hemminger				return -EINVAL;
770661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			}
771661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
772661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->loss_model = CLG_GILB_ELL;
773661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.state = 1;
774661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a1 = ge->p;
775661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a2 = ge->r;
776661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a3 = ge->h;
777661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			q->clg.a4 = ge->k1;
778661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			break;
779661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
780661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
781661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		default:
782661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			pr_info("netem: unknown loss type %u\n", type);
783661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			return -EINVAL;
784661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		}
785661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
786661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
787661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return 0;
788661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
789661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
79027a3421e4821734bc19496faa77b380605dc3b23Patrick McHardystatic const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
79127a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_CORR]	= { .len = sizeof(struct tc_netem_corr) },
79227a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_REORDER]	= { .len = sizeof(struct tc_netem_reorder) },
79327a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy	[TCA_NETEM_CORRUPT]	= { .len = sizeof(struct tc_netem_corrupt) },
7947bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	[TCA_NETEM_RATE]	= { .len = sizeof(struct tc_netem_rate) },
795661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	[TCA_NETEM_LOSS]	= { .type = NLA_NESTED },
796e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	[TCA_NETEM_ECN]		= { .type = NLA_U32 },
7976a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	[TCA_NETEM_RATE64]	= { .type = NLA_U64 },
79827a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy};
79927a3421e4821734bc19496faa77b380605dc3b23Patrick McHardy
8002c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Grafstatic int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
8012c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		      const struct nla_policy *policy, int len)
8022c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf{
8032c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	int nested_len = nla_len(nla) - NLA_ALIGN(len);
8042c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf
805661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (nested_len < 0) {
806661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		pr_info("netem: invalid attributes len %d\n", nested_len);
8072c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		return -EINVAL;
808661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
809661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
8102c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	if (nested_len >= nla_attr_size(0))
8112c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf		return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
8122c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf				 nested_len, policy);
813661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
8142c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
8152c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	return 0;
8162c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf}
8172c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf
818c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger/* Parse netlink message to set options */
8191e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int netem_change(struct Qdisc *sch, struct nlattr *opt)
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
822b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	struct nlattr *tb[TCA_NETEM_MAX + 1];
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_qopt *qopt;
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
82510297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
826b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	if (opt == NULL)
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8292c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	qopt = nla_data(opt);
8302c10b32bf57db7ec6d4cca4c4aa3d86bacb01c8aThomas Graf	ret = parse_attr(tb, TCA_NETEM_MAX, opt, netem_policy, sizeof(*qopt));
831b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	if (ret < 0)
832b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy		return ret;
833b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy
83450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	sch->limit = qopt->limit;
83510297b99315e5e08fe623ba56da35db1fee69ba9YOSHIFUJI Hideaki
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->latency = qopt->latency;
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->jitter = qopt->jitter;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->limit = qopt->limit;
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->gap = qopt->gap;
8400dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	q->counter = 0;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->loss = qopt->loss;
8421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	q->duplicate = qopt->duplicate;
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
844bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	/* for compatibility with earlier versions.
845bb2f8cc0ecf025d6d3947e0389434650023f432eStephen Hemminger	 * if gap is set, need to assume 100% probability
8460dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	 */
847a362e0a7890c735a3ef63aab12d71ecfc6e6f4a5Stephen Hemminger	if (q->gap)
848a362e0a7890c735a3ef63aab12d71ecfc6e6f4a5Stephen Hemminger		q->reorder = ~0;
8490dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
850265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_CORR])
851265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger		get_correlation(sch, tb[TCA_NETEM_CORR]);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
853b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	if (tb[TCA_NETEM_DELAY_DIST]) {
854b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy		ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]);
855b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy		if (ret)
856b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy			return ret;
857b03f4672007e533c8dbf0965f995182586216bf1Patrick McHardy	}
858c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
859265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_REORDER])
860265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger		get_reorder(sch, tb[TCA_NETEM_REORDER]);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
862265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger	if (tb[TCA_NETEM_CORRUPT])
863265eb67fb4e16be8e46a51e1e4e2ecd99fb15219Stephen Hemminger		get_corrupt(sch, tb[TCA_NETEM_CORRUPT]);
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8657bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	if (tb[TCA_NETEM_RATE])
8667bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer		get_rate(sch, tb[TCA_NETEM_RATE]);
8677bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
8686a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	if (tb[TCA_NETEM_RATE64])
8696a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		q->rate = max_t(u64, q->rate,
8706a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang				nla_get_u64(tb[TCA_NETEM_RATE64]));
8716a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang
872e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (tb[TCA_NETEM_ECN])
873e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
874e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet
875661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	q->loss_model = CLG_RANDOM;
876661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (tb[TCA_NETEM_LOSS])
877661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]);
878661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
879661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return ret;
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8821e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardystatic int netem_init(struct Qdisc *sch, struct nlattr *opt)
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret;
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!opt)
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EINVAL;
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
89059cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_init(&q->watchdog, sch);
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
892661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	q->loss_model = CLG_RANDOM;
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = netem_change(sch, opt);
89450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (ret)
895250a65f78265940ac33a2dd2002924e6126efe14stephen hemminger		pr_info("netem: change failed\n");
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void netem_destroy(struct Qdisc *sch)
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct netem_sched_data *q = qdisc_priv(sch);
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
90359cb5c6734021acc68590c7c2e0e92ad9a4952c6Patrick McHardy	qdisc_watchdog_cancel(&q->watchdog);
90450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (q->qdisc)
90550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_destroy(q->qdisc);
9066373a9a286bdd955a76924cee88a2f8f784988b1stephen hemminger	dist_free(q->delay_dist);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
909661b79725fea030803a89a16cda506bac8eeca78stephen hemmingerstatic int dump_loss_model(const struct netem_sched_data *q,
910661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			   struct sk_buff *skb)
911661b79725fea030803a89a16cda506bac8eeca78stephen hemminger{
912661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	struct nlattr *nest;
913661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
914661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nest = nla_nest_start(skb, TCA_NETEM_LOSS);
915661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (nest == NULL)
916661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		goto nla_put_failure;
917661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
918661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	switch (q->loss_model) {
919661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_RANDOM:
920661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		/* legacy loss model */
921661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		nla_nest_cancel(skb, nest);
922661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		return 0;	/* no data */
923661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
924661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_4_STATES: {
925661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		struct tc_netem_gimodel gi = {
926661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p13 = q->clg.a1,
927661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p31 = q->clg.a2,
928661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p32 = q->clg.a3,
929661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p14 = q->clg.a4,
930661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p23 = q->clg.a5,
931661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		};
932661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9331b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		if (nla_put(skb, NETEM_LOSS_GI, sizeof(gi), &gi))
9341b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller			goto nla_put_failure;
935661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
936661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
937661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	case CLG_GILB_ELL: {
938661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		struct tc_netem_gemodel ge = {
939661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.p = q->clg.a1,
940661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.r = q->clg.a2,
941661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.h = q->clg.a3,
942661b79725fea030803a89a16cda506bac8eeca78stephen hemminger			.k1 = q->clg.a4,
943661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		};
944661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9451b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		if (nla_put(skb, NETEM_LOSS_GE, sizeof(ge), &ge))
9461b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller			goto nla_put_failure;
947661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		break;
948661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
949661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	}
950661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
951661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_nest_end(skb, nest);
952661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return 0;
953661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
954661b79725fea030803a89a16cda506bac8eeca78stephen hemmingernla_put_failure:
955661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	nla_nest_cancel(skb, nest);
956661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	return -1;
957661b79725fea030803a89a16cda506bac8eeca78stephen hemminger}
958661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	const struct netem_sched_data *q = qdisc_priv(sch);
962861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb);
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_qopt qopt;
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct tc_netem_corr cor;
9650dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	struct tc_netem_reorder reorder;
966c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	struct tc_netem_corrupt corrupt;
9677bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer	struct tc_netem_rate rate;
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.latency = q->latency;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.jitter = q->jitter;
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.limit = q->limit;
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.loss = q->loss;
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.gap = q->gap;
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	qopt.duplicate = q->duplicate;
9751b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
9761b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.delay_corr = q->delay_cor.rho;
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.loss_corr = q->loss_cor.rho;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cor.dup_corr = q->dup_cor.rho;
9811b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_CORR, sizeof(cor), &cor))
9821b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
9830dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
9840dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	reorder.probability = q->reorder;
9850dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger	reorder.correlation = q->reorder_cor.rho;
9861b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder))
9871b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
9880dca51d362b8e4af6b0dbc9e54d1e5165341918aStephen Hemminger
989c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	corrupt.probability = q->corrupt;
990c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger	corrupt.correlation = q->corrupt_cor.rho;
9911b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt))
9921b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
993c865e5d99e25a171e8262fc0f7ba608568633c64Stephen Hemminger
9946a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	if (q->rate >= (1ULL << 32)) {
9956a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		if (nla_put_u64(skb, TCA_NETEM_RATE64, q->rate))
9966a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang			goto nla_put_failure;
9976a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		rate.rate = ~0U;
9986a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	} else {
9996a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang		rate.rate = q->rate;
10006a031f67c83aa175aedd10d4ae64750415ab57b0Yang Yingliang	}
100190b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.packet_overhead = q->packet_overhead;
100290b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.cell_size = q->cell_size;
100390b41a1cd44cc4e507b554ae5a36562a1ba9a4e8Hagen Paul Pfeifer	rate.cell_overhead = q->cell_overhead;
10041b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller	if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate))
10051b34ec43c9b3de44a5420841ab293d1b2035a94cDavid S. Miller		goto nla_put_failure;
10067bc0f28c7a0cd19f40e5a6e4d0a117db9a4e4cd5Hagen Paul Pfeifer
1007e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet	if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn))
1008e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet		goto nla_put_failure;
1009e4ae004b84b315dd4b762e474f97403eac70f76aEric Dumazet
1010661b79725fea030803a89a16cda506bac8eeca78stephen hemminger	if (dump_loss_model(q, skb) != 0)
1011661b79725fea030803a89a16cda506bac8eeca78stephen hemminger		goto nla_put_failure;
1012661b79725fea030803a89a16cda506bac8eeca78stephen hemminger
1013861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	return nla_nest_end(skb, nla);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10151e90474c377e92db7262a8968a45c1dd980ca9e5Patrick McHardynla_put_failure:
1016861d7f745f37506bbd90227e97b95baf2a5fac34stephen hemminger	nlmsg_trim(skb, nla);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -1;
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
102010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic int netem_dump_class(struct Qdisc *sch, unsigned long cl,
102110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			  struct sk_buff *skb, struct tcmsg *tcm)
102210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
102310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
102410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
102550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (cl != 1 || !q->qdisc) 	/* only one class */
102610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		return -ENOENT;
102710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
102810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	tcm->tcm_handle |= TC_H_MIN(1);
102910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	tcm->tcm_info = q->qdisc->handle;
103010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
103110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 0;
103210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
103310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
103410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
103510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		     struct Qdisc **old)
103610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
103710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
103810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
103910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	sch_tree_lock(sch);
104010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	*old = q->qdisc;
104110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	q->qdisc = new;
104250612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	if (*old) {
104350612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_tree_decrease_qlen(*old, (*old)->q.qlen);
104450612537e9ab29693122fab20fc1eed235054ffeEric Dumazet		qdisc_reset(*old);
104550612537e9ab29693122fab20fc1eed235054ffeEric Dumazet	}
104610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	sch_tree_unlock(sch);
104710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
104810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 0;
104910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
105010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
105110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
105210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
105310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	struct netem_sched_data *q = qdisc_priv(sch);
105410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return q->qdisc;
105510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
105610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
105710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic unsigned long netem_get(struct Qdisc *sch, u32 classid)
105810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
105910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	return 1;
106010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
106110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
106210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic void netem_put(struct Qdisc *sch, unsigned long arg)
106310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
106410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
106510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
106610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
106710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger{
106810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	if (!walker->stop) {
106910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		if (walker->count >= walker->skip)
107010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			if (walker->fn(sch, 1, walker) < 0) {
107110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger				walker->stop = 1;
107210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger				return;
107310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger			}
107410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger		walker->count++;
107510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	}
107610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger}
107710f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
107810f6dfcfde884441db89dc66b945d6c948e1d356stephen hemmingerstatic const struct Qdisc_class_ops netem_class_ops = {
107910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.graft		=	netem_graft,
108010f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.leaf		=	netem_leaf,
108110f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.get		=	netem_get,
108210f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.put		=	netem_put,
108310f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.walk		=	netem_walk,
108410f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.dump		=	netem_dump_class,
108510f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger};
108610f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger
108720fea08b5fb639c4c175b5c74a2bb346c5c5bc2eEric Dumazetstatic struct Qdisc_ops netem_qdisc_ops __read_mostly = {
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.id		=	"netem",
108910f6dfcfde884441db89dc66b945d6c948e1d356stephen hemminger	.cl_ops		=	&netem_class_ops,
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.priv_size	=	sizeof(struct netem_sched_data),
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.enqueue	=	netem_enqueue,
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dequeue	=	netem_dequeue,
109377be155cba4e163e8bba9fd27222a8b6189ec4f7Jarek Poplawski	.peek		=	qdisc_peek_dequeued,
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.drop		=	netem_drop,
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.init		=	netem_init,
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.reset		=	netem_reset,
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.destroy	=	netem_destroy,
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.change		=	netem_change,
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.dump		=	netem_dump,
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner		=	THIS_MODULE,
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init netem_module_init(void)
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1106eb229c4cdc3389682cda20adb015ba767950a220Stephen Hemminger	pr_info("netem: version " VERSION "\n");
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return register_qdisc(&netem_qdisc_ops);
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit netem_module_exit(void)
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unregister_qdisc(&netem_qdisc_ops);
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(netem_module_init)
11141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(netem_module_exit)
11151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
1116