kernel: remove esfq qdisc
[librecmc/librecmc.git] / package / network / utils / iproute2 / patches / 950-add-cake-to-tc.patch
1 --- a/include/linux/pkt_sched.h
2 +++ b/include/linux/pkt_sched.h
3 @@ -850,4 +850,56 @@ struct tc_pie_xstats {
4         __u32 maxq;             /* maximum queue size */
5         __u32 ecn_mark;         /* packets marked with ecn*/
6  };
7 +
8 +/* CAKE */
9 +enum {
10 +       TCA_CAKE_UNSPEC,
11 +       TCA_CAKE_BASE_RATE,
12 +       TCA_CAKE_DIFFSERV_MODE,
13 +       TCA_CAKE_ATM,
14 +       TCA_CAKE_FLOW_MODE,
15 +       TCA_CAKE_OVERHEAD,
16 +       TCA_CAKE_RTT,
17 +       TCA_CAKE_TARGET,
18 +       TCA_CAKE_AUTORATE,
19 +       TCA_CAKE_MEMORY,
20 +       __TCA_CAKE_MAX
21 +};
22 +#define TCA_CAKE_MAX   (__TCA_CAKE_MAX - 1)
23 +
24 +struct tc_cake_traffic_stats {
25 +       __u32 packets;
26 +       __u32 link_ms;
27 +       __u64 bytes;
28 +};
29 +
30 +#define TC_CAKE_MAX_TINS (8)
31 +struct tc_cake_xstats {
32 +       __u16 version;  /* == 4, increments when struct extended */
33 +       __u8  max_tins; /* == TC_CAKE_MAX_TINS */
34 +       __u8  tin_cnt;  /* <= TC_CAKE_MAX_TINS */
35 +
36 +       __u32 threshold_rate   [TC_CAKE_MAX_TINS];
37 +       __u32 target_us        [TC_CAKE_MAX_TINS];
38 +       struct tc_cake_traffic_stats sent      [TC_CAKE_MAX_TINS];
39 +       struct tc_cake_traffic_stats dropped   [TC_CAKE_MAX_TINS];
40 +       struct tc_cake_traffic_stats ecn_marked[TC_CAKE_MAX_TINS];
41 +       struct tc_cake_traffic_stats backlog   [TC_CAKE_MAX_TINS];
42 +       __u32 interval_us      [TC_CAKE_MAX_TINS];
43 +       __u32 way_indirect_hits[TC_CAKE_MAX_TINS];
44 +       __u32 way_misses       [TC_CAKE_MAX_TINS];
45 +       __u32 way_collisions   [TC_CAKE_MAX_TINS];
46 +       __u32 peak_delay_us    [TC_CAKE_MAX_TINS]; /* ~= delay to bulk flows */
47 +       __u32 avge_delay_us    [TC_CAKE_MAX_TINS];
48 +       __u32 base_delay_us    [TC_CAKE_MAX_TINS]; /* ~= delay to sparse flows */
49 +       __u16 sparse_flows     [TC_CAKE_MAX_TINS];
50 +       __u16 bulk_flows       [TC_CAKE_MAX_TINS];
51 +       __u16 unresponse_flows [TC_CAKE_MAX_TINS]; /* v4 - was u32 last_len  */
52 +       __u16 spare            [TC_CAKE_MAX_TINS]; /* v4 - split last_len */
53 +       __u32 max_skblen       [TC_CAKE_MAX_TINS];
54 +       __u32 capacity_estimate;  /* version 2 */
55 +       __u32 memory_limit;       /* version 3 */
56 +       __u32 memory_used;        /* version 3 */
57 +};
58 +
59  #endif
60 --- a/tc/Makefile
61 +++ b/tc/Makefile
62 @@ -63,6 +63,7 @@ TCMODULES += q_codel.o
63  TCMODULES += q_fq_codel.o
64  TCMODULES += q_fq.o
65  TCMODULES += q_pie.o
66 +TCMODULES += q_cake.o
67  TCMODULES += q_hhf.o
68  TCMODULES += e_bpf.o
69  
70 --- /dev/null
71 +++ b/tc/q_cake.c
72 @@ -0,0 +1,600 @@
73 +/*
74 + * Common Applications Kept Enhanced  --  CAKE
75 + *
76 + *  Copyright (C) 2014-2015 Jonathan Morton <chromatix99@gmail.com>
77 + *
78 + * Redistribution and use in source and binary forms, with or without
79 + * modification, are permitted provided that the following conditions
80 + * are met:
81 + * 1. Redistributions of source code must retain the above copyright
82 + *    notice, this list of conditions, and the following disclaimer,
83 + *    without modification.
84 + * 2. Redistributions in binary form must reproduce the above copyright
85 + *    notice, this list of conditions and the following disclaimer in the
86 + *    documentation and/or other materials provided with the distribution.
87 + * 3. The names of the authors may not be used to endorse or promote products
88 + *    derived from this software without specific prior written permission.
89 + *
90 + * Alternatively, provided that this notice is retained in full, this
91 + * software may be distributed under the terms of the GNU General
92 + * Public License ("GPL") version 2, in which case the provisions of the
93 + * GPL apply INSTEAD OF those given above.
94 + *
95 + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
96 + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
97 + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
98 + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
99 + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
100 + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
101 + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
102 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
103 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
104 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
105 + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
106 + * DAMAGE.
107 + *
108 + */
109 +
110 +#include <stddef.h>
111 +#include <stdio.h>
112 +#include <stdlib.h>
113 +#include <unistd.h>
114 +#include <syslog.h>
115 +#include <fcntl.h>
116 +#include <sys/socket.h>
117 +#include <netinet/in.h>
118 +#include <arpa/inet.h>
119 +#include <string.h>
120 +
121 +#include "utils.h"
122 +#include "tc_util.h"
123 +
124 +static void explain(void)
125 +{
126 +       fprintf(stderr, "Usage: ... cake [ bandwidth RATE | unlimited* | autorate_ingress ]\n"
127 +                       "                [ rtt TIME | datacentre | lan | metro | regional | internet* | oceanic | satellite | interplanetary ]\n"
128 +                       "                [ besteffort | precedence | diffserv8 | diffserv4* ]\n"
129 +                       "                [ flowblind | srchost | dsthost | hosts | flows* | dual-srchost | dual-dsthost | triple-isolate ]\n"
130 +                       "                [ atm | noatm* ] [ overhead N | conservative | raw* ]\n"
131 +                       "                [ memlimit LIMIT ]\n"
132 +                       "    (* marks defaults)\n");
133 +}
134 +
135 +static int cake_parse_opt(struct qdisc_util *qu, int argc, char **argv,
136 +                             struct nlmsghdr *n)
137 +{
138 +       int unlimited = 0;
139 +       unsigned bandwidth = 0;
140 +       unsigned interval = 0;
141 +       unsigned target = 0;
142 +       unsigned diffserv = 0;
143 +       unsigned memlimit = 0;
144 +       int  overhead = 0;
145 +       bool overhead_set = false;
146 +       int flowmode = -1;
147 +       int atm = -1;
148 +       int autorate = -1;
149 +       struct rtattr *tail;
150 +
151 +       while (argc > 0) {
152 +               if (strcmp(*argv, "bandwidth") == 0) {
153 +                       NEXT_ARG();
154 +                       if (get_rate(&bandwidth, *argv)) {
155 +                               fprintf(stderr, "Illegal \"bandwidth\"\n");
156 +                               return -1;
157 +                       }
158 +                       unlimited = 0;
159 +                       autorate = 0;
160 +               } else if (strcmp(*argv, "unlimited") == 0) {
161 +                       bandwidth = 0;
162 +                       unlimited = 1;
163 +                       autorate = 0;
164 +               } else if (strcmp(*argv, "autorate_ingress") == 0) {
165 +                       autorate = 1;
166 +
167 +               } else if (strcmp(*argv, "rtt") == 0) {
168 +                       NEXT_ARG();
169 +                       if (get_time(&interval, *argv)) {
170 +                               fprintf(stderr, "Illegal \"rtt\"\n");
171 +                               return -1;
172 +                       }
173 +                       target = interval / 20;
174 +                       if(!target)
175 +                               target = 1;
176 +               } else if (strcmp(*argv, "datacentre") == 0) {
177 +                       interval = 100;
178 +                       target   =   5;
179 +               } else if (strcmp(*argv, "lan") == 0) {
180 +                       interval = 1000;
181 +                       target   =   50;
182 +               } else if (strcmp(*argv, "metro") == 0) {
183 +                       interval = 10000;
184 +                       target   =   500;
185 +               } else if (strcmp(*argv, "regional") == 0) {
186 +                       interval = 30000;
187 +                       target    = 1500;
188 +               } else if (strcmp(*argv, "internet") == 0) {
189 +                       interval = 100000;
190 +                       target   =   5000;
191 +               } else if (strcmp(*argv, "oceanic") == 0) {
192 +                       interval = 300000;
193 +                       target   =  15000;
194 +               } else if (strcmp(*argv, "satellite") == 0) {
195 +                       interval = 1000000;
196 +                       target   =   50000;
197 +               } else if (strcmp(*argv, "interplanetary") == 0) {
198 +                       interval = 3600000000U;
199 +                       target   =       5000;
200 +
201 +               } else if (strcmp(*argv, "besteffort") == 0) {
202 +                       diffserv = 1;
203 +               } else if (strcmp(*argv, "precedence") == 0) {
204 +                       diffserv = 2;
205 +               } else if (strcmp(*argv, "diffserv8") == 0) {
206 +                       diffserv = 3;
207 +               } else if (strcmp(*argv, "diffserv4") == 0) {
208 +                       diffserv = 4;
209 +               } else if (strcmp(*argv, "diffserv") == 0) {
210 +                       diffserv = 4;
211 +               } else if (strcmp(*argv, "diffserv-llt") == 0) {
212 +                       diffserv = 5;
213 +
214 +               } else if (strcmp(*argv, "flowblind") == 0) {
215 +                       flowmode = 0;
216 +               } else if (strcmp(*argv, "srchost") == 0) {
217 +                       flowmode = 1;
218 +               } else if (strcmp(*argv, "dsthost") == 0) {
219 +                       flowmode = 2;
220 +               } else if (strcmp(*argv, "hosts") == 0) {
221 +                       flowmode = 3;
222 +               } else if (strcmp(*argv, "flows") == 0) {
223 +                       flowmode = 4;
224 +               } else if (strcmp(*argv, "dual-srchost") == 0) {
225 +                       flowmode = 5;
226 +               } else if (strcmp(*argv, "dual-dsthost") == 0) {
227 +                       flowmode = 6;
228 +               } else if (strcmp(*argv, "triple-isolate") == 0) {
229 +                       flowmode = 7;
230 +
231 +               } else if (strcmp(*argv, "atm") == 0) {
232 +                       atm = 1;
233 +               } else if (strcmp(*argv, "noatm") == 0) {
234 +                       atm = 0;
235 +
236 +               } else if (strcmp(*argv, "raw") == 0) {
237 +                       atm = 0;
238 +                       overhead = 0;
239 +                       overhead_set = true;
240 +               } else if (strcmp(*argv, "conservative") == 0) {
241 +                       /*
242 +                        * Deliberately over-estimate overhead:
243 +                        * one whole ATM cell plus ATM framing.
244 +                        * A safe choice if the actual overhead is unknown.
245 +                        */
246 +                       atm = 1;
247 +                       overhead = 48;
248 +                       overhead_set = true;
249 +
250 +               /* Various ADSL framing schemes */
251 +               } else if (strcmp(*argv, "ipoa-vcmux") == 0) {
252 +                       atm = 1;
253 +                       overhead += 8;
254 +                       overhead_set = true;
255 +               } else if (strcmp(*argv, "ipoa-llcsnap") == 0) {
256 +                       atm = 1;
257 +                       overhead += 16;
258 +                       overhead_set = true;
259 +               } else if (strcmp(*argv, "bridged-vcmux") == 0) {
260 +                       atm = 1;
261 +                       overhead += 24;
262 +                       overhead_set = true;
263 +               } else if (strcmp(*argv, "bridged-llcsnap") == 0) {
264 +                       atm = 1;
265 +                       overhead += 32;
266 +                       overhead_set = true;
267 +               } else if (strcmp(*argv, "pppoa-vcmux") == 0) {
268 +                       atm = 1;
269 +                       overhead += 10;
270 +                       overhead_set = true;
271 +               } else if (strcmp(*argv, "pppoa-llc") == 0) {
272 +                       atm = 1;
273 +                       overhead += 14;
274 +                       overhead_set = true;
275 +               } else if (strcmp(*argv, "pppoe-vcmux") == 0) {
276 +                       atm = 1;
277 +                       overhead += 32;
278 +                       overhead_set = true;
279 +               } else if (strcmp(*argv, "pppoe-llcsnap") == 0) {
280 +                       atm = 1;
281 +                       overhead += 40;
282 +                       overhead_set = true;
283 +
284 +               /* Typical VDSL2 framing schemes */
285 +               /* NB: PTM includes HDLC's 0x7D/7E expansion, adds extra 1/128 */
286 +               } else if (strcmp(*argv, "pppoe-ptm") == 0) {
287 +                       atm = 0;
288 +                       overhead += 27;
289 +               } else if (strcmp(*argv, "bridged-ptm") == 0) {
290 +                       atm = 0;
291 +                       overhead += 19;
292 +
293 +               } else if (strcmp(*argv, "via-ethernet") == 0) {
294 +                       /*
295 +                        * The above overheads are relative to an IP packet,
296 +                        * but if the physical interface is Ethernet, Linux
297 +                        * includes Ethernet framing overhead already.
298 +                        */
299 +                       overhead -= 14;
300 +                       overhead_set = true;
301 +
302 +               /* Additional Ethernet-related overheads used by some ISPs */
303 +               } else if (strcmp(*argv, "ether-phy") == 0) {
304 +                       /* ethernet pre-amble & interframe gap 20 bytes
305 +                        * Linux will have already accounted for MACs & frame type 14 bytes
306 +                        * you probably want to add an FCS as well*/
307 +                       overhead += 20;
308 +                       overhead_set = true;
309 +               } else if (strcmp(*argv, "ether-all") == 0) {
310 +                       /* ethernet pre-amble & interframe gap & FCS
311 +                        * Linux will have already accounted for MACs & frame type 14 bytes
312 +                        * you may need to add vlan tag*/
313 +                       overhead += 24;
314 +                       overhead_set = true;
315 +
316 +               } else if (strcmp(*argv, "ether-fcs") == 0) {
317 +                       /* Frame Check Sequence */
318 +                       /* we ignore the minimum frame size, because IP packets usually meet it */
319 +                       overhead += 4;
320 +                       overhead_set = true;
321 +               } else if (strcmp(*argv, "ether-vlan") == 0) {
322 +                       /* 802.1q VLAN tag - may be repeated */
323 +                       overhead += 4;
324 +                       overhead_set = true;
325 +
326 +               } else if (strcmp(*argv, "overhead") == 0) {
327 +                       char* p = NULL;
328 +                       NEXT_ARG();
329 +                       overhead = strtol(*argv, &p, 10);
330 +                       if(!p || *p || !*argv || overhead < -64 || overhead > 256) {
331 +                               fprintf(stderr, "Illegal \"overhead\", valid range is -64 to 256\\n");
332 +                               return -1;
333 +                       }
334 +                       overhead_set = true;
335 +
336 +               } else if (strcmp(*argv, "memlimit") == 0) {
337 +                       NEXT_ARG();
338 +                       if(get_size(&memlimit, *argv)) {
339 +                               fprintf(stderr, "Illegal value for \"memlimit\": \"%s\"\n", *argv);
340 +                               return -1;
341 +                       }
342 +
343 +               } else if (strcmp(*argv, "help") == 0) {
344 +                       explain();
345 +                       return -1;
346 +               } else {
347 +                       fprintf(stderr, "What is \"%s\"?\n", *argv);
348 +                       explain();
349 +                       return -1;
350 +               }
351 +               argc--; argv++;
352 +       }
353 +
354 +       tail = NLMSG_TAIL(n);
355 +       addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
356 +       if (bandwidth || unlimited)
357 +               addattr_l(n, 1024, TCA_CAKE_BASE_RATE, &bandwidth, sizeof(bandwidth));
358 +       if (diffserv)
359 +               addattr_l(n, 1024, TCA_CAKE_DIFFSERV_MODE, &diffserv, sizeof(diffserv));
360 +       if (atm != -1)
361 +               addattr_l(n, 1024, TCA_CAKE_ATM, &atm, sizeof(atm));
362 +       if (flowmode != -1)
363 +               addattr_l(n, 1024, TCA_CAKE_FLOW_MODE, &flowmode, sizeof(flowmode));
364 +       if (overhead_set)
365 +               addattr_l(n, 1024, TCA_CAKE_OVERHEAD, &overhead, sizeof(overhead));
366 +       if (interval)
367 +               addattr_l(n, 1024, TCA_CAKE_RTT, &interval, sizeof(interval));
368 +       if (target)
369 +               addattr_l(n, 1024, TCA_CAKE_TARGET, &target, sizeof(target));
370 +       if (autorate != -1)
371 +               addattr_l(n, 1024, TCA_CAKE_AUTORATE, &autorate, sizeof(autorate));
372 +       if (memlimit)
373 +               addattr_l(n, 1024, TCA_CAKE_MEMORY, &memlimit, sizeof(memlimit));
374 +
375 +       tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
376 +       return 0;
377 +}
378 +
379 +
380 +static int cake_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
381 +{
382 +       struct rtattr *tb[TCA_CAKE_MAX + 1];
383 +       unsigned bandwidth = 0;
384 +       unsigned diffserv = 0;
385 +       unsigned flowmode = 0;
386 +       unsigned interval = 0;
387 +       unsigned memlimit = 0;
388 +       int overhead = 0;
389 +       int atm = 0;
390 +       int autorate = 0;
391 +       SPRINT_BUF(b1);
392 +       SPRINT_BUF(b2);
393 +
394 +       if (opt == NULL)
395 +               return 0;
396 +
397 +       parse_rtattr_nested(tb, TCA_CAKE_MAX, opt);
398 +
399 +       if (tb[TCA_CAKE_BASE_RATE] &&
400 +           RTA_PAYLOAD(tb[TCA_CAKE_BASE_RATE]) >= sizeof(__u32)) {
401 +               bandwidth = rta_getattr_u32(tb[TCA_CAKE_BASE_RATE]);
402 +               if(bandwidth)
403 +                       fprintf(f, "bandwidth %s ", sprint_rate(bandwidth, b1));
404 +               else
405 +                       fprintf(f, "unlimited ");
406 +       }
407 +       if (tb[TCA_CAKE_AUTORATE] &&
408 +               RTA_PAYLOAD(tb[TCA_CAKE_AUTORATE]) >= sizeof(__u32)) {
409 +               autorate = rta_getattr_u32(tb[TCA_CAKE_AUTORATE]);
410 +               if(autorate == 1)
411 +                       fprintf(f, "autorate_ingress ");
412 +               else if(autorate)
413 +                       fprintf(f, "(?autorate?) ");
414 +       }
415 +       if (tb[TCA_CAKE_DIFFSERV_MODE] &&
416 +           RTA_PAYLOAD(tb[TCA_CAKE_DIFFSERV_MODE]) >= sizeof(__u32)) {
417 +               diffserv = rta_getattr_u32(tb[TCA_CAKE_DIFFSERV_MODE]);
418 +               switch(diffserv) {
419 +               case 1:
420 +                       fprintf(f, "besteffort ");
421 +                       break;
422 +               case 2:
423 +                       fprintf(f, "precedence ");
424 +                       break;
425 +               case 3:
426 +                       fprintf(f, "diffserv8 ");
427 +                       break;
428 +               case 4:
429 +                       fprintf(f, "diffserv4 ");
430 +                       break;
431 +               case 5:
432 +                       fprintf(f, "diffserv-llt ");
433 +                       break;
434 +               default:
435 +                       fprintf(f, "(?diffserv?) ");
436 +                       break;
437 +               };
438 +       }
439 +       if (tb[TCA_CAKE_FLOW_MODE] &&
440 +           RTA_PAYLOAD(tb[TCA_CAKE_FLOW_MODE]) >= sizeof(__u32)) {
441 +               flowmode = rta_getattr_u32(tb[TCA_CAKE_FLOW_MODE]);
442 +               switch(flowmode) {
443 +               case 0:
444 +                       fprintf(f, "flowblind ");
445 +                       break;
446 +               case 1:
447 +                       fprintf(f, "srchost ");
448 +                       break;
449 +               case 2:
450 +                       fprintf(f, "dsthost ");
451 +                       break;
452 +               case 3:
453 +                       fprintf(f, "hosts ");
454 +                       break;
455 +               case 4:
456 +                       fprintf(f, "flows ");
457 +                       break;
458 +               case 5:
459 +                       fprintf(f, "dual-srchost ");
460 +                       break;
461 +               case 6:
462 +                       fprintf(f, "dual-dsthost ");
463 +                       break;
464 +               case 7:
465 +                       fprintf(f, "triple-isolate ");
466 +                       break;
467 +               default:
468 +                       fprintf(f, "(?flowmode?) ");
469 +                       break;
470 +               };
471 +       }
472 +       if (tb[TCA_CAKE_ATM] &&
473 +           RTA_PAYLOAD(tb[TCA_CAKE_ATM]) >= sizeof(__u32)) {
474 +               atm = rta_getattr_u32(tb[TCA_CAKE_ATM]);
475 +       }
476 +       if (tb[TCA_CAKE_OVERHEAD] &&
477 +           RTA_PAYLOAD(tb[TCA_CAKE_OVERHEAD]) >= sizeof(__u32)) {
478 +               overhead = rta_getattr_u32(tb[TCA_CAKE_OVERHEAD]);
479 +       }
480 +       if (tb[TCA_CAKE_RTT] &&
481 +           RTA_PAYLOAD(tb[TCA_CAKE_RTT]) >= sizeof(__u32)) {
482 +               interval = rta_getattr_u32(tb[TCA_CAKE_RTT]);
483 +       }
484 +
485 +       if (interval)
486 +               fprintf(f, "rtt %s ", sprint_time(interval, b2));
487 +
488 +       if (atm)
489 +               fprintf(f, "atm ");
490 +       else if (overhead)
491 +               fprintf(f, "noatm ");
492 +
493 +       if (overhead || atm)
494 +               fprintf(f, "overhead %d ", overhead);
495 +
496 +       if (!atm && !overhead)
497 +               fprintf(f, "raw ");
498 +
499 +       if (memlimit)
500 +               fprintf(f, "memlimit %s", sprint_size(memlimit, b1));
501 +
502 +       return 0;
503 +}
504 +
505 +static int cake_print_xstats(struct qdisc_util *qu, FILE *f,
506 +                                struct rtattr *xstats)
507 +{
508 +       /* fq_codel stats format borrowed */
509 +       struct tc_fq_codel_xstats *st;
510 +       struct tc_cake_xstats     *stnc;
511 +       SPRINT_BUF(b1);
512 +       SPRINT_BUF(b2);
513 +
514 +       if (xstats == NULL)
515 +               return 0;
516 +
517 +       if (RTA_PAYLOAD(xstats) < sizeof(st->type))
518 +               return -1;
519 +
520 +       st   = RTA_DATA(xstats);
521 +       stnc = RTA_DATA(xstats);
522 +
523 +       if (st->type == TCA_FQ_CODEL_XSTATS_QDISC && RTA_PAYLOAD(xstats) >= sizeof(*st)) {
524 +               fprintf(f, "  maxpacket %u drop_overlimit %u new_flow_count %u ecn_mark %u",
525 +                       st->qdisc_stats.maxpacket,
526 +                       st->qdisc_stats.drop_overlimit,
527 +                       st->qdisc_stats.new_flow_count,
528 +                       st->qdisc_stats.ecn_mark);
529 +               fprintf(f, "\n  new_flows_len %u old_flows_len %u",
530 +                       st->qdisc_stats.new_flows_len,
531 +                       st->qdisc_stats.old_flows_len);
532 +       } else if (st->type == TCA_FQ_CODEL_XSTATS_CLASS && RTA_PAYLOAD(xstats) >= sizeof(*st)) {
533 +               fprintf(f, "  deficit %d count %u lastcount %u ldelay %s",
534 +                       st->class_stats.deficit,
535 +                       st->class_stats.count,
536 +                       st->class_stats.lastcount,
537 +                       sprint_time(st->class_stats.ldelay, b1));
538 +               if (st->class_stats.dropping) {
539 +                       fprintf(f, " dropping");
540 +                       if (st->class_stats.drop_next < 0)
541 +                               fprintf(f, " drop_next -%s",
542 +                                       sprint_time(-st->class_stats.drop_next, b1));
543 +                       else
544 +                               fprintf(f, " drop_next %s",
545 +                                       sprint_time(st->class_stats.drop_next, b1));
546 +               }
547 +       } else if (stnc->version >= 1 && stnc->version < 0xFF
548 +                               && stnc->max_tins == TC_CAKE_MAX_TINS
549 +                               && RTA_PAYLOAD(xstats) >= offsetof(struct tc_cake_xstats, capacity_estimate))
550 +       {
551 +               int i;
552 +
553 +               if(stnc->version >= 3)
554 +                       fprintf(f, " memory used: %s of %s\n", sprint_size(stnc->memory_used, b1), sprint_size(stnc->memory_limit, b2));
555 +
556 +               if(stnc->version >= 2)
557 +                       fprintf(f, " capacity estimate: %s\n", sprint_rate(stnc->capacity_estimate, b1));
558 +
559 +               switch(stnc->tin_cnt) {
560 +               case 4:
561 +                       fprintf(f, "                 Bulk   Best Effort      Video       Voice\n");
562 +                       break;
563 +
564 +               case 5:
565 +                       fprintf(f, "              Low Loss  Best Effort   Low Delay       Bulk  Net Control\n");
566 +                       break;
567 +
568 +               default:
569 +                       fprintf(f, "          ");
570 +                       for(i=0; i < stnc->tin_cnt; i++)
571 +                               fprintf(f, "       Tin %u", i);
572 +                       fprintf(f, "\n");
573 +               };
574 +
575 +               fprintf(f, "  thresh  ");
576 +               for(i=0; i < stnc->tin_cnt; i++)
577 +                       fprintf(f, "%12s", sprint_rate(stnc->threshold_rate[i], b1));
578 +               fprintf(f, "\n");
579 +
580 +               fprintf(f, "  target  ");
581 +               for(i=0; i < stnc->tin_cnt; i++)
582 +                       fprintf(f, "%12s", sprint_time(stnc->target_us[i], b1));
583 +               fprintf(f, "\n");
584 +
585 +               fprintf(f, "  interval");
586 +               for(i=0; i < stnc->tin_cnt; i++)
587 +                       fprintf(f, "%12s", sprint_time(stnc->interval_us[i], b1));
588 +               fprintf(f, "\n");
589 +
590 +               fprintf(f, "  pk_delay");
591 +               for(i=0; i < stnc->tin_cnt; i++)
592 +                       fprintf(f, "%12s", sprint_time(stnc->peak_delay_us[i], b1));
593 +               fprintf(f, "\n");
594 +
595 +               fprintf(f, "  av_delay");
596 +               for(i=0; i < stnc->tin_cnt; i++)
597 +                       fprintf(f, "%12s", sprint_time(stnc->avge_delay_us[i], b1));
598 +               fprintf(f, "\n");
599 +
600 +               fprintf(f, "  sp_delay");
601 +               for(i=0; i < stnc->tin_cnt; i++)
602 +                       fprintf(f, "%12s", sprint_time(stnc->base_delay_us[i], b1));
603 +               fprintf(f, "\n");
604 +
605 +               fprintf(f, "  pkts    ");
606 +               for(i=0; i < stnc->tin_cnt; i++)
607 +                       fprintf(f, "%12u", stnc->sent[i].packets);
608 +               fprintf(f, "\n");
609 +
610 +               fprintf(f, "  bytes   ");
611 +               for(i=0; i < stnc->tin_cnt; i++)
612 +                       fprintf(f, "%12llu", stnc->sent[i].bytes);
613 +               fprintf(f, "\n");
614 +
615 +               fprintf(f, "  way_inds");
616 +               for(i=0; i < stnc->tin_cnt; i++)
617 +                       fprintf(f, "%12u", stnc->way_indirect_hits[i]);
618 +               fprintf(f, "\n");
619 +
620 +               fprintf(f, "  way_miss");
621 +               for(i=0; i < stnc->tin_cnt; i++)
622 +                       fprintf(f, "%12u", stnc->way_misses[i]);
623 +               fprintf(f, "\n");
624 +
625 +               fprintf(f, "  way_cols");
626 +               for(i=0; i < stnc->tin_cnt; i++)
627 +                       fprintf(f, "%12u", stnc->way_collisions[i]);
628 +               fprintf(f, "\n");
629 +
630 +               fprintf(f, "  drops   ");
631 +               for(i=0; i < stnc->tin_cnt; i++)
632 +                       fprintf(f, "%12u", stnc->dropped[i].packets);
633 +               fprintf(f, "\n");
634 +
635 +               fprintf(f, "  marks   ");
636 +               for(i=0; i < stnc->tin_cnt; i++)
637 +                       fprintf(f, "%12u", stnc->ecn_marked[i].packets);
638 +               fprintf(f, "\n");
639 +
640 +               fprintf(f, "  sp_flows");
641 +               for(i=0; i < stnc->tin_cnt; i++)
642 +                       fprintf(f, "%12u", stnc->sparse_flows[i]);
643 +               fprintf(f, "\n");
644 +
645 +               fprintf(f, "  bk_flows");
646 +               for(i=0; i < stnc->tin_cnt; i++)
647 +                       fprintf(f, "%12u", stnc->bulk_flows[i]);
648 +               fprintf(f, "\n");
649 +
650 +               if(stnc->version >= 4) {
651 +                       fprintf(f, "  un_flows");
652 +                       for(i=0; i < stnc->tin_cnt; i++)
653 +                               fprintf(f, "%12u", stnc->unresponse_flows[i]);
654 +                       fprintf(f, "\n");
655 +               }
656 +
657 +               fprintf(f, "  max_len ");
658 +               for(i=0; i < stnc->tin_cnt; i++)
659 +                       fprintf(f, "%12u", stnc->max_skblen[i]);
660 +               fprintf(f, "\n");
661 +       } else {
662 +               return -1;
663 +       }
664 +       return 0;
665 +}
666 +
667 +struct qdisc_util cake_qdisc_util = {
668 +       .id             = "cake",
669 +       .parse_qopt     = cake_parse_opt,
670 +       .print_qopt     = cake_print_opt,
671 +       .print_xstats   = cake_print_xstats,
672 +};