Merge tag 'gpio-v4.20-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw...
[linux-2.6-block.git] / net / sched / sch_netem.c
CommitLineData
1da177e4
LT
1/*
2 * net/sched/sch_netem.c Network emulator
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
798b6b19 7 * 2 of the License.
1da177e4
LT
8 *
9 * Many of the algorithms and ideas for this came from
10297b99 10 * NIST Net which is not copyrighted.
1da177e4
LT
11 *
12 * Authors: Stephen Hemminger <shemminger@osdl.org>
13 * Catalin(ux aka Dino) BOIE <catab at umbrella dot ro>
14 */
15
b7f080cf 16#include <linux/mm.h>
1da177e4 17#include <linux/module.h>
5a0e3ad6 18#include <linux/slab.h>
1da177e4
LT
19#include <linux/types.h>
20#include <linux/kernel.h>
21#include <linux/errno.h>
1da177e4 22#include <linux/skbuff.h>
78776d3f 23#include <linux/vmalloc.h>
1da177e4 24#include <linux/rtnetlink.h>
90b41a1c 25#include <linux/reciprocal_div.h>
aec0a40a 26#include <linux/rbtree.h>
1da177e4 27
dc5fc579 28#include <net/netlink.h>
1da177e4 29#include <net/pkt_sched.h>
e4ae004b 30#include <net/inet_ecn.h>
1da177e4 31
250a65f7 32#define VERSION "1.3"
eb229c4c 33
1da177e4
LT
34/* Network Emulation Queuing algorithm.
35 ====================================
36
37 Sources: [1] Mark Carson, Darrin Santay, "NIST Net - A Linux-based
38 Network Emulation Tool
39 [2] Luigi Rizzo, DummyNet for FreeBSD
40
41 ----------------------------------------------------------------
42
43 This started out as a simple way to delay outgoing packets to
44 test TCP but has grown to include most of the functionality
45 of a full blown network emulator like NISTnet. It can delay
46 packets and add random jitter (and correlation). The random
47 distribution can be loaded from a table as well to provide
48 normal, Pareto, or experimental curves. Packet loss,
49 duplication, and reordering can also be emulated.
50
51 This qdisc does not do classification that can be handled in
52 layering other disciplines. It does not need to do bandwidth
53 control either since that can be handled by using token
54 bucket or other rate control.
661b7972 55
56 Correlated Loss Generator models
57
58 Added generation of correlated loss according to the
59 "Gilbert-Elliot" model, a 4-state markov model.
60
61 References:
62 [1] NetemCLG Home http://netgroup.uniroma2.it/NetemCLG
63 [2] S. Salsano, F. Ludovici, A. Ordine, "Definition of a general
64 and intuitive loss model for packet networks and its implementation
65 in the Netem module in the Linux kernel", available in [1]
66
67 Authors: Stefano Salsano <stefano.salsano at uniroma2.it
68 Fabio Ludovici <fabio.ludovici at yahoo.it>
1da177e4
LT
69*/
70
0a9fe5c3
YS
71struct disttable {
72 u32 size;
73 s16 table[0];
74};
75
1da177e4 76struct netem_sched_data {
aec0a40a
ED
77 /* internal t(ime)fifo qdisc uses t_root and sch->limit */
78 struct rb_root t_root;
50612537
ED
79
80 /* optional qdisc for classful handling (NULL at netem init) */
1da177e4 81 struct Qdisc *qdisc;
50612537 82
59cb5c67 83 struct qdisc_watchdog watchdog;
1da177e4 84
112f9cb6
DT
85 s64 latency;
86 s64 jitter;
b407621c 87
1da177e4 88 u32 loss;
e4ae004b 89 u32 ecn;
1da177e4
LT
90 u32 limit;
91 u32 counter;
92 u32 gap;
1da177e4 93 u32 duplicate;
0dca51d3 94 u32 reorder;
c865e5d9 95 u32 corrupt;
6a031f67 96 u64 rate;
90b41a1c
HPP
97 s32 packet_overhead;
98 u32 cell_size;
809fa972 99 struct reciprocal_value cell_size_reciprocal;
90b41a1c 100 s32 cell_overhead;
1da177e4
LT
101
102 struct crndstate {
b407621c
SH
103 u32 last;
104 u32 rho;
c865e5d9 105 } delay_cor, loss_cor, dup_cor, reorder_cor, corrupt_cor;
1da177e4 106
0a9fe5c3 107 struct disttable *delay_dist;
661b7972 108
109 enum {
110 CLG_RANDOM,
111 CLG_4_STATES,
112 CLG_GILB_ELL,
113 } loss_model;
114
a6e2fe17
YY
115 enum {
116 TX_IN_GAP_PERIOD = 1,
117 TX_IN_BURST_PERIOD,
118 LOST_IN_GAP_PERIOD,
119 LOST_IN_BURST_PERIOD,
120 } _4_state_model;
121
c045a734
YY
122 enum {
123 GOOD_STATE = 1,
124 BAD_STATE,
125 } GE_state_model;
126
661b7972 127 /* Correlated Loss Generation models */
128 struct clgstate {
129 /* state of the Markov chain */
130 u8 state;
131
132 /* 4-states and Gilbert-Elliot models */
133 u32 a1; /* p13 for 4-states or p for GE */
134 u32 a2; /* p31 for 4-states or r for GE */
135 u32 a3; /* p32 for 4-states or h for GE */
136 u32 a4; /* p14 for 4-states or 1-k for GE */
137 u32 a5; /* p23 used only in 4-states */
138 } clg;
139
836af83b
DT
140 struct tc_netem_slot slot_config;
141 struct slotstate {
142 u64 slot_next;
143 s32 packets_left;
144 s32 bytes_left;
145 } slot;
146
0a9fe5c3 147 struct disttable *slot_dist;
1da177e4
LT
148};
149
50612537
ED
150/* Time stamp put into socket buffer control block
151 * Only valid when skbs are in our internal t(ime)fifo queue.
56b17425
ED
152 *
153 * As skb->rbnode uses same storage than skb->next, skb->prev and skb->tstamp,
154 * and skb->next & skb->prev are scratch space for a qdisc,
155 * we save skb->tstamp value in skb->cb[] before destroying it.
50612537 156 */
1da177e4 157struct netem_skb_cb {
112f9cb6 158 u64 time_to_send;
1da177e4
LT
159};
160
5f86173b
JK
161static inline struct netem_skb_cb *netem_skb_cb(struct sk_buff *skb)
162{
aec0a40a 163 /* we assume we can use skb next/prev/tstamp as storage for rb_node */
16bda13d 164 qdisc_cb_private_validate(skb, sizeof(struct netem_skb_cb));
175f9c1b 165 return (struct netem_skb_cb *)qdisc_skb_cb(skb)->data;
5f86173b
JK
166}
167
1da177e4
LT
168/* init_crandom - initialize correlated random number generator
169 * Use entropy source for initial seed.
170 */
171static void init_crandom(struct crndstate *state, unsigned long rho)
172{
173 state->rho = rho;
63862b5b 174 state->last = prandom_u32();
1da177e4
LT
175}
176
177/* get_crandom - correlated random number generator
178 * Next number depends on last value.
179 * rho is scaled to avoid floating point.
180 */
b407621c 181static u32 get_crandom(struct crndstate *state)
1da177e4
LT
182{
183 u64 value, rho;
184 unsigned long answer;
185
0a9fe5c3 186 if (!state || state->rho == 0) /* no correlation */
63862b5b 187 return prandom_u32();
1da177e4 188
63862b5b 189 value = prandom_u32();
1da177e4
LT
190 rho = (u64)state->rho + 1;
191 answer = (value * ((1ull<<32) - rho) + state->last * rho) >> 32;
192 state->last = answer;
193 return answer;
194}
195
661b7972 196/* loss_4state - 4-state model loss generator
197 * Generates losses according to the 4-state Markov chain adopted in
198 * the GI (General and Intuitive) loss model.
199 */
200static bool loss_4state(struct netem_sched_data *q)
201{
202 struct clgstate *clg = &q->clg;
63862b5b 203 u32 rnd = prandom_u32();
661b7972 204
205 /*
25985edc 206 * Makes a comparison between rnd and the transition
661b7972 207 * probabilities outgoing from the current state, then decides the
208 * next state and if the next packet has to be transmitted or lost.
209 * The four states correspond to:
a6e2fe17
YY
210 * TX_IN_GAP_PERIOD => successfully transmitted packets within a gap period
211 * LOST_IN_BURST_PERIOD => isolated losses within a gap period
212 * LOST_IN_GAP_PERIOD => lost packets within a burst period
213 * TX_IN_GAP_PERIOD => successfully transmitted packets within a burst period
661b7972 214 */
215 switch (clg->state) {
a6e2fe17 216 case TX_IN_GAP_PERIOD:
661b7972 217 if (rnd < clg->a4) {
a6e2fe17 218 clg->state = LOST_IN_BURST_PERIOD;
661b7972 219 return true;
ab6c27be 220 } else if (clg->a4 < rnd && rnd < clg->a1 + clg->a4) {
a6e2fe17 221 clg->state = LOST_IN_GAP_PERIOD;
661b7972 222 return true;
a6e2fe17
YY
223 } else if (clg->a1 + clg->a4 < rnd) {
224 clg->state = TX_IN_GAP_PERIOD;
225 }
661b7972 226
227 break;
a6e2fe17 228 case TX_IN_BURST_PERIOD:
661b7972 229 if (rnd < clg->a5) {
a6e2fe17 230 clg->state = LOST_IN_GAP_PERIOD;
661b7972 231 return true;
a6e2fe17
YY
232 } else {
233 clg->state = TX_IN_BURST_PERIOD;
234 }
661b7972 235
236 break;
a6e2fe17 237 case LOST_IN_GAP_PERIOD:
661b7972 238 if (rnd < clg->a3)
a6e2fe17 239 clg->state = TX_IN_BURST_PERIOD;
661b7972 240 else if (clg->a3 < rnd && rnd < clg->a2 + clg->a3) {
a6e2fe17 241 clg->state = TX_IN_GAP_PERIOD;
661b7972 242 } else if (clg->a2 + clg->a3 < rnd) {
a6e2fe17 243 clg->state = LOST_IN_GAP_PERIOD;
661b7972 244 return true;
245 }
246 break;
a6e2fe17
YY
247 case LOST_IN_BURST_PERIOD:
248 clg->state = TX_IN_GAP_PERIOD;
661b7972 249 break;
250 }
251
252 return false;
253}
254
255/* loss_gilb_ell - Gilbert-Elliot model loss generator
256 * Generates losses according to the Gilbert-Elliot loss model or
257 * its special cases (Gilbert or Simple Gilbert)
258 *
25985edc 259 * Makes a comparison between random number and the transition
661b7972 260 * probabilities outgoing from the current state, then decides the
25985edc 261 * next state. A second random number is extracted and the comparison
661b7972 262 * with the loss probability of the current state decides if the next
263 * packet will be transmitted or lost.
264 */
265static bool loss_gilb_ell(struct netem_sched_data *q)
266{
267 struct clgstate *clg = &q->clg;
268
269 switch (clg->state) {
c045a734 270 case GOOD_STATE:
63862b5b 271 if (prandom_u32() < clg->a1)
c045a734 272 clg->state = BAD_STATE;
63862b5b 273 if (prandom_u32() < clg->a4)
661b7972 274 return true;
7c2781fa 275 break;
c045a734 276 case BAD_STATE:
63862b5b 277 if (prandom_u32() < clg->a2)
c045a734 278 clg->state = GOOD_STATE;
63862b5b 279 if (prandom_u32() > clg->a3)
661b7972 280 return true;
281 }
282
283 return false;
284}
285
286static bool loss_event(struct netem_sched_data *q)
287{
288 switch (q->loss_model) {
289 case CLG_RANDOM:
290 /* Random packet drop 0 => none, ~0 => all */
291 return q->loss && q->loss >= get_crandom(&q->loss_cor);
292
293 case CLG_4_STATES:
294 /* 4state loss model algorithm (used also for GI model)
295 * Extracts a value from the markov 4 state loss generator,
296 * if it is 1 drops a packet and if needed writes the event in
297 * the kernel logs
298 */
299 return loss_4state(q);
300
301 case CLG_GILB_ELL:
302 /* Gilbert-Elliot loss model algorithm
303 * Extracts a value from the Gilbert-Elliot loss generator,
304 * if it is 1 drops a packet and if needed writes the event in
305 * the kernel logs
306 */
307 return loss_gilb_ell(q);
308 }
309
310 return false; /* not reached */
311}
312
313
1da177e4
LT
314/* tabledist - return a pseudo-randomly distributed value with mean mu and
315 * std deviation sigma. Uses table lookup to approximate the desired
316 * distribution, and a uniformly-distributed pseudo-random source.
317 */
9b0ed891 318static s64 tabledist(s64 mu, s32 sigma,
112f9cb6 319 struct crndstate *state,
9b0ed891 320 const struct disttable *dist)
1da177e4 321{
112f9cb6 322 s64 x;
b407621c
SH
323 long t;
324 u32 rnd;
1da177e4
LT
325
326 if (sigma == 0)
327 return mu;
328
329 rnd = get_crandom(state);
330
331 /* default uniform distribution */
10297b99 332 if (dist == NULL)
043e337f 333 return ((rnd % (2 * sigma)) + mu) - sigma;
1da177e4
LT
334
335 t = dist->table[rnd % dist->size];
336 x = (sigma % NETEM_DIST_SCALE) * t;
337 if (x >= 0)
338 x += NETEM_DIST_SCALE/2;
339 else
340 x -= NETEM_DIST_SCALE/2;
341
342 return x / NETEM_DIST_SCALE + (sigma / NETEM_DIST_SCALE) * t + mu;
343}
344
bce552fd 345static u64 packet_time_ns(u64 len, const struct netem_sched_data *q)
7bc0f28c 346{
90b41a1c
HPP
347 len += q->packet_overhead;
348
349 if (q->cell_size) {
350 u32 cells = reciprocal_divide(len, q->cell_size_reciprocal);
351
352 if (len > cells * q->cell_size) /* extra cell needed for remainder */
353 cells++;
354 len = cells * (q->cell_size + q->cell_overhead);
355 }
bce552fd
SH
356
357 return div64_u64(len * NSEC_PER_SEC, q->rate);
7bc0f28c
HPP
358}
359
ff704050 360static void tfifo_reset(struct Qdisc *sch)
361{
362 struct netem_sched_data *q = qdisc_priv(sch);
3aa605f2 363 struct rb_node *p = rb_first(&q->t_root);
ff704050 364
3aa605f2 365 while (p) {
18a4c0ea 366 struct sk_buff *skb = rb_to_skb(p);
ff704050 367
3aa605f2
ED
368 p = rb_next(p);
369 rb_erase(&skb->rbnode, &q->t_root);
2f08a9a1 370 rtnl_kfree_skbs(skb, skb);
ff704050 371 }
372}
373
960fb66e 374static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
50612537 375{
aec0a40a 376 struct netem_sched_data *q = qdisc_priv(sch);
112f9cb6 377 u64 tnext = netem_skb_cb(nskb)->time_to_send;
aec0a40a 378 struct rb_node **p = &q->t_root.rb_node, *parent = NULL;
50612537 379
aec0a40a
ED
380 while (*p) {
381 struct sk_buff *skb;
50612537 382
aec0a40a 383 parent = *p;
18a4c0ea 384 skb = rb_to_skb(parent);
960fb66e 385 if (tnext >= netem_skb_cb(skb)->time_to_send)
aec0a40a
ED
386 p = &parent->rb_right;
387 else
388 p = &parent->rb_left;
50612537 389 }
56b17425
ED
390 rb_link_node(&nskb->rbnode, parent, p);
391 rb_insert_color(&nskb->rbnode, &q->t_root);
aec0a40a 392 sch->q.qlen++;
50612537
ED
393}
394
6071bd1a
NH
395/* netem can't properly corrupt a megapacket (like we get from GSO), so instead
396 * when we statistically choose to corrupt one, we instead segment it, returning
397 * the first packet to be corrupted, and re-enqueue the remaining frames
398 */
520ac30f
ED
399static struct sk_buff *netem_segment(struct sk_buff *skb, struct Qdisc *sch,
400 struct sk_buff **to_free)
6071bd1a
NH
401{
402 struct sk_buff *segs;
403 netdev_features_t features = netif_skb_features(skb);
404
405 segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
406
407 if (IS_ERR_OR_NULL(segs)) {
520ac30f 408 qdisc_drop(skb, sch, to_free);
6071bd1a
NH
409 return NULL;
410 }
411 consume_skb(skb);
412 return segs;
413}
414
0afb51e7
SH
415/*
416 * Insert one skb into qdisc.
417 * Note: parent depends on return value to account for queue length.
418 * NET_XMIT_DROP: queue length didn't change.
419 * NET_XMIT_SUCCESS: one skb was queued.
420 */
520ac30f
ED
421static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
422 struct sk_buff **to_free)
1da177e4
LT
423{
424 struct netem_sched_data *q = qdisc_priv(sch);
89e1df74
GC
425 /* We don't fill cb now as skb_unshare() may invalidate it */
426 struct netem_skb_cb *cb;
0afb51e7 427 struct sk_buff *skb2;
6071bd1a
NH
428 struct sk_buff *segs = NULL;
429 unsigned int len = 0, last_len, prev_len = qdisc_pkt_len(skb);
430 int nb = 0;
0afb51e7 431 int count = 1;
6071bd1a 432 int rc = NET_XMIT_SUCCESS;
1da177e4 433
0afb51e7
SH
434 /* Random duplication */
435 if (q->duplicate && q->duplicate >= get_crandom(&q->dup_cor))
436 ++count;
437
661b7972 438 /* Drop packet? */
e4ae004b
ED
439 if (loss_event(q)) {
440 if (q->ecn && INET_ECN_set_ce(skb))
25331d6c 441 qdisc_qstats_drop(sch); /* mark packet */
e4ae004b
ED
442 else
443 --count;
444 }
0afb51e7 445 if (count == 0) {
25331d6c 446 qdisc_qstats_drop(sch);
520ac30f 447 __qdisc_drop(skb, to_free);
c27f339a 448 return NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;
1da177e4
LT
449 }
450
5a308f40
ED
451 /* If a delay is expected, orphan the skb. (orphaning usually takes
452 * place at TX completion time, so _before_ the link transit delay)
5a308f40 453 */
5080f39e 454 if (q->latency || q->jitter || q->rate)
f2f872f9 455 skb_orphan_partial(skb);
4e8a5201 456
0afb51e7
SH
457 /*
458 * If we need to duplicate packet, then re-insert at top of the
459 * qdisc tree, since parent queuer expects that only one
460 * skb will be queued.
461 */
462 if (count > 1 && (skb2 = skb_clone(skb, GFP_ATOMIC)) != NULL) {
7698b4fc 463 struct Qdisc *rootq = qdisc_root(sch);
0afb51e7 464 u32 dupsave = q->duplicate; /* prevent duplicating a dup... */
0afb51e7 465
b396cca6 466 q->duplicate = 0;
520ac30f 467 rootq->enqueue(skb2, rootq, to_free);
0afb51e7 468 q->duplicate = dupsave;
1da177e4
LT
469 }
470
c865e5d9
SH
471 /*
472 * Randomized packet corruption.
473 * Make copy if needed since we are modifying
474 * If packet is going to be hardware checksummed, then
475 * do it now in software before we mangle it.
476 */
477 if (q->corrupt && q->corrupt >= get_crandom(&q->corrupt_cor)) {
6071bd1a 478 if (skb_is_gso(skb)) {
520ac30f 479 segs = netem_segment(skb, sch, to_free);
6071bd1a
NH
480 if (!segs)
481 return NET_XMIT_DROP;
482 } else {
483 segs = skb;
484 }
485
486 skb = segs;
487 segs = segs->next;
488
8a6e9c67
ED
489 skb = skb_unshare(skb, GFP_ATOMIC);
490 if (unlikely(!skb)) {
491 qdisc_qstats_drop(sch);
492 goto finish_segs;
493 }
494 if (skb->ip_summed == CHECKSUM_PARTIAL &&
495 skb_checksum_help(skb)) {
496 qdisc_drop(skb, sch, to_free);
6071bd1a
NH
497 goto finish_segs;
498 }
c865e5d9 499
63862b5b
AH
500 skb->data[prandom_u32() % skb_headlen(skb)] ^=
501 1<<(prandom_u32() % 8);
c865e5d9
SH
502 }
503
97d0678f 504 if (unlikely(sch->q.qlen >= sch->limit))
35d889d1 505 return qdisc_drop_all(skb, sch, to_free);
960fb66e 506
25331d6c 507 qdisc_qstats_backlog_inc(sch, skb);
960fb66e 508
5f86173b 509 cb = netem_skb_cb(skb);
cc7ec456 510 if (q->gap == 0 || /* not doing reordering */
a42b4799 511 q->counter < q->gap - 1 || /* inside last reordering gap */
f64f9e71 512 q->reorder < get_crandom(&q->reorder_cor)) {
112f9cb6
DT
513 u64 now;
514 s64 delay;
07aaa115
SH
515
516 delay = tabledist(q->latency, q->jitter,
517 &q->delay_cor, q->delay_dist);
518
112f9cb6 519 now = ktime_get_ns();
7bc0f28c
HPP
520
521 if (q->rate) {
5080f39e
NU
522 struct netem_skb_cb *last = NULL;
523
524 if (sch->q.tail)
525 last = netem_skb_cb(sch->q.tail);
526 if (q->t_root.rb_node) {
527 struct sk_buff *t_skb;
528 struct netem_skb_cb *t_last;
529
18a4c0ea 530 t_skb = skb_rb_last(&q->t_root);
5080f39e
NU
531 t_last = netem_skb_cb(t_skb);
532 if (!last ||
533 t_last->time_to_send > last->time_to_send) {
534 last = t_last;
535 }
536 }
7bc0f28c 537
aec0a40a 538 if (last) {
7bc0f28c 539 /*
a13d3104
JN
540 * Last packet in queue is reference point (now),
541 * calculate this time bonus and subtract
7bc0f28c
HPP
542 * from delay.
543 */
5080f39e 544 delay -= last->time_to_send - now;
112f9cb6 545 delay = max_t(s64, 0, delay);
5080f39e 546 now = last->time_to_send;
7bc0f28c 547 }
a13d3104 548
bce552fd 549 delay += packet_time_ns(qdisc_pkt_len(skb), q);
7bc0f28c
HPP
550 }
551
7c59e25f 552 cb->time_to_send = now + delay;
1da177e4 553 ++q->counter;
960fb66e 554 tfifo_enqueue(skb, sch);
1da177e4 555 } else {
10297b99 556 /*
0dca51d3
SH
557 * Do re-ordering by putting one out of N packets at the front
558 * of the queue.
559 */
112f9cb6 560 cb->time_to_send = ktime_get_ns();
0dca51d3 561 q->counter = 0;
8ba25dad 562
59697730 563 __qdisc_enqueue_head(skb, &sch->q);
eb101924 564 sch->qstats.requeues++;
378a2f09 565 }
1da177e4 566
6071bd1a
NH
567finish_segs:
568 if (segs) {
569 while (segs) {
570 skb2 = segs->next;
a8305bff 571 skb_mark_not_on_list(segs);
6071bd1a
NH
572 qdisc_skb_cb(segs)->pkt_len = segs->len;
573 last_len = segs->len;
520ac30f 574 rc = qdisc_enqueue(segs, sch, to_free);
6071bd1a
NH
575 if (rc != NET_XMIT_SUCCESS) {
576 if (net_xmit_drop_count(rc))
577 qdisc_qstats_drop(sch);
578 } else {
579 nb++;
580 len += last_len;
581 }
582 segs = skb2;
583 }
584 sch->q.qlen += nb;
585 if (nb > 1)
586 qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
587 }
10f6dfcf 588 return NET_XMIT_SUCCESS;
1da177e4
LT
589}
590
836af83b
DT
591/* Delay the next round with a new future slot with a
592 * correct number of bytes and packets.
593 */
594
595static void get_slot_next(struct netem_sched_data *q, u64 now)
596{
0a9fe5c3
YS
597 s64 next_delay;
598
599 if (!q->slot_dist)
600 next_delay = q->slot_config.min_delay +
601 (prandom_u32() *
602 (q->slot_config.max_delay -
603 q->slot_config.min_delay) >> 32);
604 else
605 next_delay = tabledist(q->slot_config.dist_delay,
606 (s32)(q->slot_config.dist_jitter),
607 NULL, q->slot_dist);
608
609 q->slot.slot_next = now + next_delay;
836af83b
DT
610 q->slot.packets_left = q->slot_config.max_packets;
611 q->slot.bytes_left = q->slot_config.max_bytes;
612}
613
1da177e4
LT
614static struct sk_buff *netem_dequeue(struct Qdisc *sch)
615{
616 struct netem_sched_data *q = qdisc_priv(sch);
617 struct sk_buff *skb;
aec0a40a 618 struct rb_node *p;
1da177e4 619
50612537 620tfifo_dequeue:
ed760cb8 621 skb = __qdisc_dequeue_head(&sch->q);
771018e7 622 if (skb) {
25331d6c 623 qdisc_qstats_backlog_dec(sch, skb);
0ad2a836 624deliver:
aec0a40a
ED
625 qdisc_bstats_update(sch, skb);
626 return skb;
627 }
628 p = rb_first(&q->t_root);
629 if (p) {
112f9cb6 630 u64 time_to_send;
836af83b 631 u64 now = ktime_get_ns();
36b7bfe0 632
18a4c0ea 633 skb = rb_to_skb(p);
0f9f32ac
SH
634
635 /* if more time remaining? */
36b7bfe0 636 time_to_send = netem_skb_cb(skb)->time_to_send;
836af83b
DT
637 if (q->slot.slot_next && q->slot.slot_next < time_to_send)
638 get_slot_next(q, now);
aec0a40a 639
836af83b
DT
640 if (time_to_send <= now && q->slot.slot_next <= now) {
641 rb_erase(p, &q->t_root);
aec0a40a 642 sch->q.qlen--;
0ad2a836 643 qdisc_qstats_backlog_dec(sch, skb);
aec0a40a
ED
644 skb->next = NULL;
645 skb->prev = NULL;
bffa72cf
ED
646 /* skb->dev shares skb->rbnode area,
647 * we need to restore its value.
648 */
649 skb->dev = qdisc_dev(sch);
03c05f0d 650
836af83b
DT
651 if (q->slot.slot_next) {
652 q->slot.packets_left--;
653 q->slot.bytes_left -= qdisc_pkt_len(skb);
654 if (q->slot.packets_left <= 0 ||
655 q->slot.bytes_left <= 0)
656 get_slot_next(q, now);
657 }
658
50612537 659 if (q->qdisc) {
21de12ee 660 unsigned int pkt_len = qdisc_pkt_len(skb);
520ac30f
ED
661 struct sk_buff *to_free = NULL;
662 int err;
50612537 663
520ac30f
ED
664 err = qdisc_enqueue(skb, q->qdisc, &to_free);
665 kfree_skb_list(to_free);
21de12ee
ED
666 if (err != NET_XMIT_SUCCESS &&
667 net_xmit_drop_count(err)) {
668 qdisc_qstats_drop(sch);
669 qdisc_tree_reduce_backlog(sch, 1,
670 pkt_len);
50612537
ED
671 }
672 goto tfifo_dequeue;
673 }
aec0a40a 674 goto deliver;
07aaa115 675 }
11274e5a 676
50612537
ED
677 if (q->qdisc) {
678 skb = q->qdisc->ops->dequeue(q->qdisc);
679 if (skb)
680 goto deliver;
681 }
836af83b
DT
682
683 qdisc_watchdog_schedule_ns(&q->watchdog,
684 max(time_to_send,
685 q->slot.slot_next));
0f9f32ac
SH
686 }
687
50612537
ED
688 if (q->qdisc) {
689 skb = q->qdisc->ops->dequeue(q->qdisc);
690 if (skb)
691 goto deliver;
692 }
0f9f32ac 693 return NULL;
1da177e4
LT
694}
695
1da177e4
LT
696static void netem_reset(struct Qdisc *sch)
697{
698 struct netem_sched_data *q = qdisc_priv(sch);
699
50612537 700 qdisc_reset_queue(sch);
ff704050 701 tfifo_reset(sch);
50612537
ED
702 if (q->qdisc)
703 qdisc_reset(q->qdisc);
59cb5c67 704 qdisc_watchdog_cancel(&q->watchdog);
1da177e4
LT
705}
706
6373a9a2 707static void dist_free(struct disttable *d)
708{
4cb28970 709 kvfree(d);
6373a9a2 710}
711
1da177e4
LT
712/*
713 * Distribution data is a variable size payload containing
714 * signed 16 bit values.
715 */
836af83b 716
0a9fe5c3
YS
717static int get_dist_table(struct Qdisc *sch, struct disttable **tbl,
718 const struct nlattr *attr)
1da177e4 719{
6373a9a2 720 size_t n = nla_len(attr)/sizeof(__s16);
1e90474c 721 const __s16 *data = nla_data(attr);
7698b4fc 722 spinlock_t *root_lock;
1da177e4
LT
723 struct disttable *d;
724 int i;
725
df173bda 726 if (n > NETEM_DIST_MAX)
1da177e4
LT
727 return -EINVAL;
728
752ade68 729 d = kvmalloc(sizeof(struct disttable) + n * sizeof(s16), GFP_KERNEL);
1da177e4
LT
730 if (!d)
731 return -ENOMEM;
732
733 d->size = n;
734 for (i = 0; i < n; i++)
735 d->table[i] = data[i];
10297b99 736
102396ae 737 root_lock = qdisc_root_sleeping_lock(sch);
7698b4fc
DM
738
739 spin_lock_bh(root_lock);
0a9fe5c3 740 swap(*tbl, d);
7698b4fc 741 spin_unlock_bh(root_lock);
bb52c7ac
ED
742
743 dist_free(d);
1da177e4
LT
744 return 0;
745}
746
836af83b
DT
747static void get_slot(struct netem_sched_data *q, const struct nlattr *attr)
748{
749 const struct tc_netem_slot *c = nla_data(attr);
750
751 q->slot_config = *c;
752 if (q->slot_config.max_packets == 0)
753 q->slot_config.max_packets = INT_MAX;
754 if (q->slot_config.max_bytes == 0)
755 q->slot_config.max_bytes = INT_MAX;
756 q->slot.packets_left = q->slot_config.max_packets;
757 q->slot.bytes_left = q->slot_config.max_bytes;
0a9fe5c3
YS
758 if (q->slot_config.min_delay | q->slot_config.max_delay |
759 q->slot_config.dist_jitter)
836af83b
DT
760 q->slot.slot_next = ktime_get_ns();
761 else
762 q->slot.slot_next = 0;
763}
764
49545a77 765static void get_correlation(struct netem_sched_data *q, const struct nlattr *attr)
1da177e4 766{
1e90474c 767 const struct tc_netem_corr *c = nla_data(attr);
1da177e4 768
1da177e4
LT
769 init_crandom(&q->delay_cor, c->delay_corr);
770 init_crandom(&q->loss_cor, c->loss_corr);
771 init_crandom(&q->dup_cor, c->dup_corr);
1da177e4
LT
772}
773
49545a77 774static void get_reorder(struct netem_sched_data *q, const struct nlattr *attr)
0dca51d3 775{
1e90474c 776 const struct tc_netem_reorder *r = nla_data(attr);
0dca51d3 777
0dca51d3
SH
778 q->reorder = r->probability;
779 init_crandom(&q->reorder_cor, r->correlation);
0dca51d3
SH
780}
781
49545a77 782static void get_corrupt(struct netem_sched_data *q, const struct nlattr *attr)
c865e5d9 783{
1e90474c 784 const struct tc_netem_corrupt *r = nla_data(attr);
c865e5d9 785
c865e5d9
SH
786 q->corrupt = r->probability;
787 init_crandom(&q->corrupt_cor, r->correlation);
c865e5d9
SH
788}
789
49545a77 790static void get_rate(struct netem_sched_data *q, const struct nlattr *attr)
7bc0f28c 791{
7bc0f28c
HPP
792 const struct tc_netem_rate *r = nla_data(attr);
793
794 q->rate = r->rate;
90b41a1c
HPP
795 q->packet_overhead = r->packet_overhead;
796 q->cell_size = r->cell_size;
809fa972 797 q->cell_overhead = r->cell_overhead;
90b41a1c
HPP
798 if (q->cell_size)
799 q->cell_size_reciprocal = reciprocal_value(q->cell_size);
809fa972
HFS
800 else
801 q->cell_size_reciprocal = (struct reciprocal_value) { 0 };
7bc0f28c
HPP
802}
803
49545a77 804static int get_loss_clg(struct netem_sched_data *q, const struct nlattr *attr)
661b7972 805{
661b7972 806 const struct nlattr *la;
807 int rem;
808
809 nla_for_each_nested(la, attr, rem) {
810 u16 type = nla_type(la);
811
833fa743 812 switch (type) {
661b7972 813 case NETEM_LOSS_GI: {
814 const struct tc_netem_gimodel *gi = nla_data(la);
815
2494654d 816 if (nla_len(la) < sizeof(struct tc_netem_gimodel)) {
661b7972 817 pr_info("netem: incorrect gi model size\n");
818 return -EINVAL;
819 }
820
821 q->loss_model = CLG_4_STATES;
822
3fbac2a8 823 q->clg.state = TX_IN_GAP_PERIOD;
661b7972 824 q->clg.a1 = gi->p13;
825 q->clg.a2 = gi->p31;
826 q->clg.a3 = gi->p32;
827 q->clg.a4 = gi->p14;
828 q->clg.a5 = gi->p23;
829 break;
830 }
831
832 case NETEM_LOSS_GE: {
833 const struct tc_netem_gemodel *ge = nla_data(la);
834
2494654d 835 if (nla_len(la) < sizeof(struct tc_netem_gemodel)) {
836 pr_info("netem: incorrect ge model size\n");
661b7972 837 return -EINVAL;
838 }
839
840 q->loss_model = CLG_GILB_ELL;
3fbac2a8 841 q->clg.state = GOOD_STATE;
661b7972 842 q->clg.a1 = ge->p;
843 q->clg.a2 = ge->r;
844 q->clg.a3 = ge->h;
845 q->clg.a4 = ge->k1;
846 break;
847 }
848
849 default:
850 pr_info("netem: unknown loss type %u\n", type);
851 return -EINVAL;
852 }
853 }
854
855 return 0;
856}
857
27a3421e
PM
858static const struct nla_policy netem_policy[TCA_NETEM_MAX + 1] = {
859 [TCA_NETEM_CORR] = { .len = sizeof(struct tc_netem_corr) },
860 [TCA_NETEM_REORDER] = { .len = sizeof(struct tc_netem_reorder) },
861 [TCA_NETEM_CORRUPT] = { .len = sizeof(struct tc_netem_corrupt) },
7bc0f28c 862 [TCA_NETEM_RATE] = { .len = sizeof(struct tc_netem_rate) },
661b7972 863 [TCA_NETEM_LOSS] = { .type = NLA_NESTED },
e4ae004b 864 [TCA_NETEM_ECN] = { .type = NLA_U32 },
6a031f67 865 [TCA_NETEM_RATE64] = { .type = NLA_U64 },
99803171
DT
866 [TCA_NETEM_LATENCY64] = { .type = NLA_S64 },
867 [TCA_NETEM_JITTER64] = { .type = NLA_S64 },
836af83b 868 [TCA_NETEM_SLOT] = { .len = sizeof(struct tc_netem_slot) },
27a3421e
PM
869};
870
2c10b32b
TG
871static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,
872 const struct nla_policy *policy, int len)
873{
874 int nested_len = nla_len(nla) - NLA_ALIGN(len);
875
661b7972 876 if (nested_len < 0) {
877 pr_info("netem: invalid attributes len %d\n", nested_len);
2c10b32b 878 return -EINVAL;
661b7972 879 }
880
2c10b32b
TG
881 if (nested_len >= nla_attr_size(0))
882 return nla_parse(tb, maxtype, nla_data(nla) + NLA_ALIGN(len),
fceb6435 883 nested_len, policy, NULL);
661b7972 884
2c10b32b
TG
885 memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1));
886 return 0;
887}
888
c865e5d9 889/* Parse netlink message to set options */
2030721c
AA
890static int netem_change(struct Qdisc *sch, struct nlattr *opt,
891 struct netlink_ext_ack *extack)
1da177e4
LT
892{
893 struct netem_sched_data *q = qdisc_priv(sch);
b03f4672 894 struct nlattr *tb[TCA_NETEM_MAX + 1];
1da177e4 895 struct tc_netem_qopt *qopt;
54a4b05c
YY
896 struct clgstate old_clg;
897 int old_loss_model = CLG_RANDOM;
1da177e4 898 int ret;
10297b99 899
b03f4672 900 if (opt == NULL)
1da177e4
LT
901 return -EINVAL;
902
2c10b32b
TG
903 qopt = nla_data(opt);
904 ret = parse_attr(tb, TCA_NETEM_MAX, opt, netem_policy, sizeof(*qopt));
b03f4672
PM
905 if (ret < 0)
906 return ret;
907
54a4b05c
YY
908 /* backup q->clg and q->loss_model */
909 old_clg = q->clg;
910 old_loss_model = q->loss_model;
911
912 if (tb[TCA_NETEM_LOSS]) {
49545a77 913 ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]);
54a4b05c
YY
914 if (ret) {
915 q->loss_model = old_loss_model;
916 return ret;
917 }
918 } else {
919 q->loss_model = CLG_RANDOM;
920 }
921
922 if (tb[TCA_NETEM_DELAY_DIST]) {
0a9fe5c3
YS
923 ret = get_dist_table(sch, &q->delay_dist,
924 tb[TCA_NETEM_DELAY_DIST]);
925 if (ret)
926 goto get_table_failure;
927 }
928
929 if (tb[TCA_NETEM_SLOT_DIST]) {
930 ret = get_dist_table(sch, &q->slot_dist,
931 tb[TCA_NETEM_SLOT_DIST]);
932 if (ret)
933 goto get_table_failure;
54a4b05c
YY
934 }
935
50612537 936 sch->limit = qopt->limit;
10297b99 937
112f9cb6
DT
938 q->latency = PSCHED_TICKS2NS(qopt->latency);
939 q->jitter = PSCHED_TICKS2NS(qopt->jitter);
1da177e4
LT
940 q->limit = qopt->limit;
941 q->gap = qopt->gap;
0dca51d3 942 q->counter = 0;
1da177e4
LT
943 q->loss = qopt->loss;
944 q->duplicate = qopt->duplicate;
945
bb2f8cc0
SH
946 /* for compatibility with earlier versions.
947 * if gap is set, need to assume 100% probability
0dca51d3 948 */
a362e0a7
SH
949 if (q->gap)
950 q->reorder = ~0;
0dca51d3 951
265eb67f 952 if (tb[TCA_NETEM_CORR])
49545a77 953 get_correlation(q, tb[TCA_NETEM_CORR]);
1da177e4 954
265eb67f 955 if (tb[TCA_NETEM_REORDER])
49545a77 956 get_reorder(q, tb[TCA_NETEM_REORDER]);
1da177e4 957
265eb67f 958 if (tb[TCA_NETEM_CORRUPT])
49545a77 959 get_corrupt(q, tb[TCA_NETEM_CORRUPT]);
1da177e4 960
7bc0f28c 961 if (tb[TCA_NETEM_RATE])
49545a77 962 get_rate(q, tb[TCA_NETEM_RATE]);
7bc0f28c 963
6a031f67
YY
964 if (tb[TCA_NETEM_RATE64])
965 q->rate = max_t(u64, q->rate,
966 nla_get_u64(tb[TCA_NETEM_RATE64]));
967
99803171
DT
968 if (tb[TCA_NETEM_LATENCY64])
969 q->latency = nla_get_s64(tb[TCA_NETEM_LATENCY64]);
970
971 if (tb[TCA_NETEM_JITTER64])
972 q->jitter = nla_get_s64(tb[TCA_NETEM_JITTER64]);
973
e4ae004b
ED
974 if (tb[TCA_NETEM_ECN])
975 q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]);
976
836af83b
DT
977 if (tb[TCA_NETEM_SLOT])
978 get_slot(q, tb[TCA_NETEM_SLOT]);
979
661b7972 980 return ret;
0a9fe5c3
YS
981
982get_table_failure:
983 /* recover clg and loss_model, in case of
984 * q->clg and q->loss_model were modified
985 * in get_loss_clg()
986 */
987 q->clg = old_clg;
988 q->loss_model = old_loss_model;
989 return ret;
1da177e4
LT
990}
991
e63d7dfd
AA
992static int netem_init(struct Qdisc *sch, struct nlattr *opt,
993 struct netlink_ext_ack *extack)
1da177e4
LT
994{
995 struct netem_sched_data *q = qdisc_priv(sch);
996 int ret;
997
634576a1
NA
998 qdisc_watchdog_init(&q->watchdog, sch);
999
1da177e4
LT
1000 if (!opt)
1001 return -EINVAL;
1002
661b7972 1003 q->loss_model = CLG_RANDOM;
2030721c 1004 ret = netem_change(sch, opt, extack);
50612537 1005 if (ret)
250a65f7 1006 pr_info("netem: change failed\n");
1da177e4
LT
1007 return ret;
1008}
1009
1010static void netem_destroy(struct Qdisc *sch)
1011{
1012 struct netem_sched_data *q = qdisc_priv(sch);
1013
59cb5c67 1014 qdisc_watchdog_cancel(&q->watchdog);
50612537 1015 if (q->qdisc)
86bd446b 1016 qdisc_put(q->qdisc);
6373a9a2 1017 dist_free(q->delay_dist);
0a9fe5c3 1018 dist_free(q->slot_dist);
1da177e4
LT
1019}
1020
661b7972 1021static int dump_loss_model(const struct netem_sched_data *q,
1022 struct sk_buff *skb)
1023{
1024 struct nlattr *nest;
1025
1026 nest = nla_nest_start(skb, TCA_NETEM_LOSS);
1027 if (nest == NULL)
1028 goto nla_put_failure;
1029
1030 switch (q->loss_model) {
1031 case CLG_RANDOM:
1032 /* legacy loss model */
1033 nla_nest_cancel(skb, nest);
1034 return 0; /* no data */
1035
1036 case CLG_4_STATES: {
1037 struct tc_netem_gimodel gi = {
1038 .p13 = q->clg.a1,
1039 .p31 = q->clg.a2,
1040 .p32 = q->clg.a3,
1041 .p14 = q->clg.a4,
1042 .p23 = q->clg.a5,
1043 };
1044
1b34ec43
DM
1045 if (nla_put(skb, NETEM_LOSS_GI, sizeof(gi), &gi))
1046 goto nla_put_failure;
661b7972 1047 break;
1048 }
1049 case CLG_GILB_ELL: {
1050 struct tc_netem_gemodel ge = {
1051 .p = q->clg.a1,
1052 .r = q->clg.a2,
1053 .h = q->clg.a3,
1054 .k1 = q->clg.a4,
1055 };
1056
1b34ec43
DM
1057 if (nla_put(skb, NETEM_LOSS_GE, sizeof(ge), &ge))
1058 goto nla_put_failure;
661b7972 1059 break;
1060 }
1061 }
1062
1063 nla_nest_end(skb, nest);
1064 return 0;
1065
1066nla_put_failure:
1067 nla_nest_cancel(skb, nest);
1068 return -1;
1069}
1070
1da177e4
LT
1071static int netem_dump(struct Qdisc *sch, struct sk_buff *skb)
1072{
1073 const struct netem_sched_data *q = qdisc_priv(sch);
861d7f74 1074 struct nlattr *nla = (struct nlattr *) skb_tail_pointer(skb);
1da177e4
LT
1075 struct tc_netem_qopt qopt;
1076 struct tc_netem_corr cor;
0dca51d3 1077 struct tc_netem_reorder reorder;
c865e5d9 1078 struct tc_netem_corrupt corrupt;
7bc0f28c 1079 struct tc_netem_rate rate;
836af83b 1080 struct tc_netem_slot slot;
1da177e4 1081
112f9cb6
DT
1082 qopt.latency = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->latency),
1083 UINT_MAX);
1084 qopt.jitter = min_t(psched_tdiff_t, PSCHED_NS2TICKS(q->jitter),
1085 UINT_MAX);
1da177e4
LT
1086 qopt.limit = q->limit;
1087 qopt.loss = q->loss;
1088 qopt.gap = q->gap;
1089 qopt.duplicate = q->duplicate;
1b34ec43
DM
1090 if (nla_put(skb, TCA_OPTIONS, sizeof(qopt), &qopt))
1091 goto nla_put_failure;
1da177e4 1092
99803171
DT
1093 if (nla_put(skb, TCA_NETEM_LATENCY64, sizeof(q->latency), &q->latency))
1094 goto nla_put_failure;
1095
1096 if (nla_put(skb, TCA_NETEM_JITTER64, sizeof(q->jitter), &q->jitter))
1097 goto nla_put_failure;
1098
1da177e4
LT
1099 cor.delay_corr = q->delay_cor.rho;
1100 cor.loss_corr = q->loss_cor.rho;
1101 cor.dup_corr = q->dup_cor.rho;
1b34ec43
DM
1102 if (nla_put(skb, TCA_NETEM_CORR, sizeof(cor), &cor))
1103 goto nla_put_failure;
0dca51d3
SH
1104
1105 reorder.probability = q->reorder;
1106 reorder.correlation = q->reorder_cor.rho;
1b34ec43
DM
1107 if (nla_put(skb, TCA_NETEM_REORDER, sizeof(reorder), &reorder))
1108 goto nla_put_failure;
0dca51d3 1109
c865e5d9
SH
1110 corrupt.probability = q->corrupt;
1111 corrupt.correlation = q->corrupt_cor.rho;
1b34ec43
DM
1112 if (nla_put(skb, TCA_NETEM_CORRUPT, sizeof(corrupt), &corrupt))
1113 goto nla_put_failure;
c865e5d9 1114
6a031f67 1115 if (q->rate >= (1ULL << 32)) {
2a51c1e8
ND
1116 if (nla_put_u64_64bit(skb, TCA_NETEM_RATE64, q->rate,
1117 TCA_NETEM_PAD))
6a031f67
YY
1118 goto nla_put_failure;
1119 rate.rate = ~0U;
1120 } else {
1121 rate.rate = q->rate;
1122 }
90b41a1c
HPP
1123 rate.packet_overhead = q->packet_overhead;
1124 rate.cell_size = q->cell_size;
1125 rate.cell_overhead = q->cell_overhead;
1b34ec43
DM
1126 if (nla_put(skb, TCA_NETEM_RATE, sizeof(rate), &rate))
1127 goto nla_put_failure;
7bc0f28c 1128
e4ae004b
ED
1129 if (q->ecn && nla_put_u32(skb, TCA_NETEM_ECN, q->ecn))
1130 goto nla_put_failure;
1131
661b7972 1132 if (dump_loss_model(q, skb) != 0)
1133 goto nla_put_failure;
1134
0a9fe5c3
YS
1135 if (q->slot_config.min_delay | q->slot_config.max_delay |
1136 q->slot_config.dist_jitter) {
836af83b
DT
1137 slot = q->slot_config;
1138 if (slot.max_packets == INT_MAX)
1139 slot.max_packets = 0;
1140 if (slot.max_bytes == INT_MAX)
1141 slot.max_bytes = 0;
1142 if (nla_put(skb, TCA_NETEM_SLOT, sizeof(slot), &slot))
1143 goto nla_put_failure;
1144 }
1145
861d7f74 1146 return nla_nest_end(skb, nla);
1da177e4 1147
1e90474c 1148nla_put_failure:
861d7f74 1149 nlmsg_trim(skb, nla);
1da177e4
LT
1150 return -1;
1151}
1152
10f6dfcf 1153static int netem_dump_class(struct Qdisc *sch, unsigned long cl,
1154 struct sk_buff *skb, struct tcmsg *tcm)
1155{
1156 struct netem_sched_data *q = qdisc_priv(sch);
1157
50612537 1158 if (cl != 1 || !q->qdisc) /* only one class */
10f6dfcf 1159 return -ENOENT;
1160
1161 tcm->tcm_handle |= TC_H_MIN(1);
1162 tcm->tcm_info = q->qdisc->handle;
1163
1164 return 0;
1165}
1166
1167static int netem_graft(struct Qdisc *sch, unsigned long arg, struct Qdisc *new,
653d6fd6 1168 struct Qdisc **old, struct netlink_ext_ack *extack)
10f6dfcf 1169{
1170 struct netem_sched_data *q = qdisc_priv(sch);
1171
86a7996c 1172 *old = qdisc_replace(sch, new, &q->qdisc);
10f6dfcf 1173 return 0;
1174}
1175
1176static struct Qdisc *netem_leaf(struct Qdisc *sch, unsigned long arg)
1177{
1178 struct netem_sched_data *q = qdisc_priv(sch);
1179 return q->qdisc;
1180}
1181
143976ce 1182static unsigned long netem_find(struct Qdisc *sch, u32 classid)
10f6dfcf 1183{
1184 return 1;
1185}
1186
10f6dfcf 1187static void netem_walk(struct Qdisc *sch, struct qdisc_walker *walker)
1188{
1189 if (!walker->stop) {
1190 if (walker->count >= walker->skip)
1191 if (walker->fn(sch, 1, walker) < 0) {
1192 walker->stop = 1;
1193 return;
1194 }
1195 walker->count++;
1196 }
1197}
1198
1199static const struct Qdisc_class_ops netem_class_ops = {
1200 .graft = netem_graft,
1201 .leaf = netem_leaf,
143976ce 1202 .find = netem_find,
10f6dfcf 1203 .walk = netem_walk,
1204 .dump = netem_dump_class,
1205};
1206
20fea08b 1207static struct Qdisc_ops netem_qdisc_ops __read_mostly = {
1da177e4 1208 .id = "netem",
10f6dfcf 1209 .cl_ops = &netem_class_ops,
1da177e4
LT
1210 .priv_size = sizeof(struct netem_sched_data),
1211 .enqueue = netem_enqueue,
1212 .dequeue = netem_dequeue,
77be155c 1213 .peek = qdisc_peek_dequeued,
1da177e4
LT
1214 .init = netem_init,
1215 .reset = netem_reset,
1216 .destroy = netem_destroy,
1217 .change = netem_change,
1218 .dump = netem_dump,
1219 .owner = THIS_MODULE,
1220};
1221
1222
1223static int __init netem_module_init(void)
1224{
eb229c4c 1225 pr_info("netem: version " VERSION "\n");
1da177e4
LT
1226 return register_qdisc(&netem_qdisc_ops);
1227}
1228static void __exit netem_module_exit(void)
1229{
1230 unregister_qdisc(&netem_qdisc_ops);
1231}
1232module_init(netem_module_init)
1233module_exit(netem_module_exit)
1234MODULE_LICENSE("GPL");