]> git.proxmox.com Git - mirror_iproute2.git/blame - tc/q_cbq.c
treewide: refactor help messages
[mirror_iproute2.git] / tc / q_cbq.c
CommitLineData
aba5acdf
SH
1/*
2 * q_cbq.c CBQ.
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
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
10 *
11 */
12
13#include <stdio.h>
14#include <stdlib.h>
15#include <unistd.h>
aba5acdf
SH
16#include <fcntl.h>
17#include <sys/socket.h>
18#include <netinet/in.h>
19#include <arpa/inet.h>
20#include <string.h>
21
22#include "utils.h"
23#include "tc_util.h"
24#include "tc_cbq.h"
25
26static void explain_class(void)
27{
8589eb4e
MC
28 fprintf(stderr,
29 "Usage: ... cbq bandwidth BPS rate BPS maxburst PKTS [ avpkt BYTES ]\n"
30 " [ minburst PKTS ] [ bounded ] [ isolated ]\n"
31 " [ allot BYTES ] [ mpu BYTES ] [ weight RATE ]\n"
32 " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n"
33 " [ estimator INTERVAL TIME_CONSTANT ]\n"
34 " [ split CLASSID ] [ defmap MASK/CHANGE ]\n"
35 " [ overhead BYTES ] [ linklayer TYPE ]\n");
aba5acdf
SH
36}
37
38static void explain(void)
39{
8589eb4e
MC
40 fprintf(stderr,
41 "Usage: ... cbq bandwidth BPS avpkt BYTES [ mpu BYTES ]\n"
42 " [ cell BYTES ] [ ewma LOG ]\n");
aba5acdf
SH
43}
44
45static void explain1(char *arg)
46{
47 fprintf(stderr, "Illegal \"%s\"\n", arg);
48}
49
aba5acdf 50
927e3cfb 51static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
aba5acdf 52{
d17b136f
PS
53 struct tc_ratespec r = {};
54 struct tc_cbq_lssopt lss = {};
aba5acdf 55 __u32 rtab[256];
32a121cb
SH
56 unsigned mpu = 0, avpkt = 0, allot = 0;
57 unsigned short overhead = 0;
292f29b4 58 unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
32a121cb
SH
59 int cell_log = -1;
60 int ewma_log = -1;
aba5acdf
SH
61 struct rtattr *tail;
62
aba5acdf 63 while (argc > 0) {
1db5e2ec
JDB
64 if (matches(*argv, "bandwidth") == 0 ||
65 matches(*argv, "rate") == 0) {
aba5acdf 66 NEXT_ARG();
927e3cfb
ND
67 if (strchr(*argv, '%')) {
68 if (get_percent_rate(&r.rate, *argv, dev)) {
69 explain1("bandwidth");
70 return -1;
71 }
72 } else if (get_rate(&r.rate, *argv)) {
aba5acdf
SH
73 explain1("bandwidth");
74 return -1;
75 }
1db5e2ec 76 } else if (matches(*argv, "ewma") == 0) {
aba5acdf 77 NEXT_ARG();
f332d169 78 if (get_integer(&ewma_log, *argv, 0)) {
aba5acdf
SH
79 explain1("ewma");
80 return -1;
81 }
82 if (ewma_log > 31) {
83 fprintf(stderr, "ewma_log must be < 32\n");
84 return -1;
85 }
1db5e2ec 86 } else if (matches(*argv, "cell") == 0) {
32a121cb 87 unsigned int cell;
aba5acdf 88 int i;
32a121cb 89
aba5acdf
SH
90 NEXT_ARG();
91 if (get_size(&cell, *argv)) {
92 explain1("cell");
93 return -1;
94 }
32a121cb 95 for (i = 0; i < 32; i++)
aba5acdf
SH
96 if ((1<<i) == cell)
97 break;
32a121cb 98 if (i >= 32) {
aba5acdf
SH
99 fprintf(stderr, "cell must be 2^n\n");
100 return -1;
101 }
102 cell_log = i;
1db5e2ec 103 } else if (matches(*argv, "avpkt") == 0) {
aba5acdf
SH
104 NEXT_ARG();
105 if (get_size(&avpkt, *argv)) {
106 explain1("avpkt");
107 return -1;
108 }
1db5e2ec 109 } else if (matches(*argv, "mpu") == 0) {
aba5acdf
SH
110 NEXT_ARG();
111 if (get_size(&mpu, *argv)) {
112 explain1("mpu");
113 return -1;
114 }
1db5e2ec 115 } else if (matches(*argv, "allot") == 0) {
aba5acdf
SH
116 NEXT_ARG();
117 /* Accept and ignore "allot" for backward compatibility */
118 if (get_size(&allot, *argv)) {
119 explain1("allot");
120 return -1;
121 }
08fd0184
JDB
122 } else if (matches(*argv, "overhead") == 0) {
123 NEXT_ARG();
124 if (get_u16(&overhead, *argv, 10)) {
125 explain1("overhead"); return -1;
126 }
292f29b4
JDB
127 } else if (matches(*argv, "linklayer") == 0) {
128 NEXT_ARG();
129 if (get_linklayer(&linklayer, *argv)) {
130 explain1("linklayer"); return -1;
131 }
1db5e2ec 132 } else if (matches(*argv, "help") == 0) {
aba5acdf
SH
133 explain();
134 return -1;
135 } else {
136 fprintf(stderr, "What is \"%s\"?\n", *argv);
137 explain();
138 return -1;
139 }
140 argc--; argv++;
141 }
142
143 /* OK. All options are parsed. */
144
145 if (r.rate == 0) {
146 fprintf(stderr, "CBQ: bandwidth is required parameter.\n");
147 return -1;
148 }
149 if (avpkt == 0) {
150 fprintf(stderr, "CBQ: \"avpkt\" is required.\n");
151 return -1;
152 }
153 if (allot < (avpkt*3)/2)
154 allot = (avpkt*3)/2;
155
d5f46f9c 156 r.mpu = mpu;
08fd0184 157 r.overhead = overhead;
292f29b4 158 if (tc_calc_rtable(&r, rtab, cell_log, allot, linklayer) < 0) {
aba5acdf
SH
159 fprintf(stderr, "CBQ: failed to calculate rate table.\n");
160 return -1;
161 }
aba5acdf
SH
162
163 if (ewma_log < 0)
164 ewma_log = TC_CBQ_DEF_EWMA;
165 lss.ewma_log = ewma_log;
476daa72 166 lss.maxidle = tc_calc_xmittime(r.rate, avpkt);
aba5acdf
SH
167 lss.change = TCF_CBQ_LSS_MAXIDLE|TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
168 lss.avpkt = avpkt;
169
c14f9d92 170 tail = addattr_nest(n, 1024, TCA_OPTIONS);
aba5acdf
SH
171 addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r));
172 addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
173 addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
174 if (show_raw) {
175 int i;
32a121cb
SH
176
177 for (i = 0; i < 256; i++)
aba5acdf
SH
178 printf("%u ", rtab[i]);
179 printf("\n");
180 }
c14f9d92 181 addattr_nest_end(n, tail);
aba5acdf
SH
182 return 0;
183}
184
927e3cfb 185static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n, const char *dev)
aba5acdf 186{
32a121cb 187 int wrr_ok = 0, fopt_ok = 0;
d17b136f
PS
188 struct tc_ratespec r = {};
189 struct tc_cbq_lssopt lss = {};
190 struct tc_cbq_wrropt wrr = {};
191 struct tc_cbq_fopt fopt = {};
aba5acdf 192 __u32 rtab[256];
32a121cb
SH
193 unsigned mpu = 0;
194 int cell_log = -1;
195 int ewma_log = -1;
196 unsigned int bndw = 0;
197 unsigned minburst = 0, maxburst = 0;
198 unsigned short overhead = 0;
292f29b4 199 unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
aba5acdf
SH
200 struct rtattr *tail;
201
aba5acdf 202 while (argc > 0) {
1db5e2ec 203 if (matches(*argv, "rate") == 0) {
aba5acdf 204 NEXT_ARG();
927e3cfb
ND
205 if (strchr(*argv, '%')) {
206 if (get_percent_rate(&r.rate, *argv, dev)) {
207 explain1("rate");
208 return -1;
209 }
210 } else if (get_rate(&r.rate, *argv)) {
aba5acdf
SH
211 explain1("rate");
212 return -1;
213 }
1db5e2ec 214 } else if (matches(*argv, "bandwidth") == 0) {
aba5acdf 215 NEXT_ARG();
927e3cfb
ND
216 if (strchr(*argv, '%')) {
217 if (get_percent_rate(&bndw, *argv, dev)) {
218 explain1("bandwidth");
219 return -1;
220 }
221 } else if (get_rate(&bndw, *argv)) {
aba5acdf
SH
222 explain1("bandwidth");
223 return -1;
224 }
1db5e2ec 225 } else if (matches(*argv, "minidle") == 0) {
aba5acdf
SH
226 NEXT_ARG();
227 if (get_u32(&lss.minidle, *argv, 0)) {
228 explain1("minidle");
229 return -1;
230 }
231 lss.change |= TCF_CBQ_LSS_MINIDLE;
1db5e2ec 232 } else if (matches(*argv, "minburst") == 0) {
aba5acdf
SH
233 NEXT_ARG();
234 if (get_u32(&minburst, *argv, 0)) {
235 explain1("minburst");
236 return -1;
237 }
238 lss.change |= TCF_CBQ_LSS_OFFTIME;
1db5e2ec 239 } else if (matches(*argv, "maxburst") == 0) {
aba5acdf
SH
240 NEXT_ARG();
241 if (get_u32(&maxburst, *argv, 0)) {
242 explain1("maxburst");
243 return -1;
244 }
245 lss.change |= TCF_CBQ_LSS_MAXIDLE;
1db5e2ec 246 } else if (matches(*argv, "bounded") == 0) {
aba5acdf
SH
247 lss.flags |= TCF_CBQ_LSS_BOUNDED;
248 lss.change |= TCF_CBQ_LSS_FLAGS;
1db5e2ec 249 } else if (matches(*argv, "borrow") == 0) {
aba5acdf
SH
250 lss.flags &= ~TCF_CBQ_LSS_BOUNDED;
251 lss.change |= TCF_CBQ_LSS_FLAGS;
1db5e2ec 252 } else if (matches(*argv, "isolated") == 0) {
aba5acdf
SH
253 lss.flags |= TCF_CBQ_LSS_ISOLATED;
254 lss.change |= TCF_CBQ_LSS_FLAGS;
1db5e2ec 255 } else if (matches(*argv, "sharing") == 0) {
aba5acdf
SH
256 lss.flags &= ~TCF_CBQ_LSS_ISOLATED;
257 lss.change |= TCF_CBQ_LSS_FLAGS;
1db5e2ec 258 } else if (matches(*argv, "ewma") == 0) {
aba5acdf 259 NEXT_ARG();
f332d169 260 if (get_integer(&ewma_log, *argv, 0)) {
aba5acdf
SH
261 explain1("ewma");
262 return -1;
263 }
264 if (ewma_log > 31) {
265 fprintf(stderr, "ewma_log must be < 32\n");
266 return -1;
267 }
268 lss.change |= TCF_CBQ_LSS_EWMA;
1db5e2ec 269 } else if (matches(*argv, "cell") == 0) {
32a121cb 270 unsigned int cell;
aba5acdf 271 int i;
32a121cb 272
aba5acdf
SH
273 NEXT_ARG();
274 if (get_size(&cell, *argv)) {
275 explain1("cell");
276 return -1;
277 }
32a121cb 278 for (i = 0; i < 32; i++)
aba5acdf
SH
279 if ((1<<i) == cell)
280 break;
32a121cb 281 if (i >= 32) {
aba5acdf
SH
282 fprintf(stderr, "cell must be 2^n\n");
283 return -1;
284 }
285 cell_log = i;
1db5e2ec 286 } else if (matches(*argv, "prio") == 0) {
32a121cb
SH
287 unsigned int prio;
288
aba5acdf
SH
289 NEXT_ARG();
290 if (get_u32(&prio, *argv, 0)) {
291 explain1("prio");
292 return -1;
293 }
294 if (prio > TC_CBQ_MAXPRIO) {
295 fprintf(stderr, "\"prio\" must be number in the range 1...%d\n", TC_CBQ_MAXPRIO);
296 return -1;
297 }
298 wrr.priority = prio;
299 wrr_ok++;
1db5e2ec 300 } else if (matches(*argv, "allot") == 0) {
aba5acdf
SH
301 NEXT_ARG();
302 if (get_size(&wrr.allot, *argv)) {
303 explain1("allot");
304 return -1;
305 }
1db5e2ec 306 } else if (matches(*argv, "avpkt") == 0) {
aba5acdf
SH
307 NEXT_ARG();
308 if (get_size(&lss.avpkt, *argv)) {
309 explain1("avpkt");
310 return -1;
311 }
312 lss.change |= TCF_CBQ_LSS_AVPKT;
1db5e2ec 313 } else if (matches(*argv, "mpu") == 0) {
aba5acdf
SH
314 NEXT_ARG();
315 if (get_size(&mpu, *argv)) {
316 explain1("mpu");
317 return -1;
318 }
1db5e2ec 319 } else if (matches(*argv, "weight") == 0) {
aba5acdf
SH
320 NEXT_ARG();
321 if (get_size(&wrr.weight, *argv)) {
322 explain1("weight");
323 return -1;
324 }
325 wrr_ok++;
1db5e2ec 326 } else if (matches(*argv, "split") == 0) {
aba5acdf
SH
327 NEXT_ARG();
328 if (get_tc_classid(&fopt.split, *argv)) {
329 fprintf(stderr, "Invalid split node ID.\n");
8d8de113 330 return -1;
aba5acdf
SH
331 }
332 fopt_ok++;
1db5e2ec 333 } else if (matches(*argv, "defmap") == 0) {
aba5acdf 334 int err;
32a121cb 335
aba5acdf
SH
336 NEXT_ARG();
337 err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange);
338 if (err < 1) {
339 fprintf(stderr, "Invalid defmap, should be MASK32[/MASK]\n");
340 return -1;
341 }
342 if (err == 1)
343 fopt.defchange = ~0;
344 fopt_ok++;
08fd0184
JDB
345 } else if (matches(*argv, "overhead") == 0) {
346 NEXT_ARG();
347 if (get_u16(&overhead, *argv, 10)) {
348 explain1("overhead"); return -1;
349 }
292f29b4
JDB
350 } else if (matches(*argv, "linklayer") == 0) {
351 NEXT_ARG();
352 if (get_linklayer(&linklayer, *argv)) {
353 explain1("linklayer"); return -1;
354 }
1db5e2ec 355 } else if (matches(*argv, "help") == 0) {
aba5acdf
SH
356 explain_class();
357 return -1;
358 } else {
359 fprintf(stderr, "What is \"%s\"?\n", *argv);
360 explain_class();
361 return -1;
362 }
363 argc--; argv++;
364 }
365
366 /* OK. All options are parsed. */
367
368 /* 1. Prepare link sharing scheduler parameters */
369 if (r.rate) {
32a121cb
SH
370 unsigned int pktsize = wrr.allot;
371
aba5acdf
SH
372 if (wrr.allot < (lss.avpkt*3)/2)
373 wrr.allot = (lss.avpkt*3)/2;
d5f46f9c 374 r.mpu = mpu;
08fd0184 375 r.overhead = overhead;
292f29b4 376 if (tc_calc_rtable(&r, rtab, cell_log, pktsize, linklayer) < 0) {
aba5acdf
SH
377 fprintf(stderr, "CBQ: failed to calculate rate table.\n");
378 return -1;
379 }
aba5acdf
SH
380 }
381 if (ewma_log < 0)
382 ewma_log = TC_CBQ_DEF_EWMA;
383 lss.ewma_log = ewma_log;
384 if (lss.change&(TCF_CBQ_LSS_OFFTIME|TCF_CBQ_LSS_MAXIDLE)) {
385 if (lss.avpkt == 0) {
386 fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n");
387 return -1;
388 }
32a121cb 389 if (bndw == 0 || r.rate == 0) {
aba5acdf
SH
390 fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n");
391 return -1;
392 }
393 }
394 if (wrr.priority == 0 && (n->nlmsg_flags&NLM_F_EXCL)) {
395 wrr_ok = 1;
396 wrr.priority = TC_CBQ_MAXPRIO;
397 if (wrr.allot == 0)
398 wrr.allot = (lss.avpkt*3)/2;
399 }
400 if (wrr_ok) {
401 if (wrr.weight == 0)
402 wrr.weight = (wrr.priority == TC_CBQ_MAXPRIO) ? 1 : r.rate;
403 if (wrr.allot == 0) {
404 fprintf(stderr, "CBQ: \"allot\" is required to set WRR parameters.\n");
405 return -1;
406 }
407 }
408 if (lss.change&TCF_CBQ_LSS_MAXIDLE) {
409 lss.maxidle = tc_cbq_calc_maxidle(bndw, r.rate, lss.avpkt, ewma_log, maxburst);
410 lss.change |= TCF_CBQ_LSS_MAXIDLE;
411 lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
412 }
413 if (lss.change&TCF_CBQ_LSS_OFFTIME) {
414 lss.offtime = tc_cbq_calc_offtime(bndw, r.rate, lss.avpkt, ewma_log, minburst);
415 lss.change |= TCF_CBQ_LSS_OFFTIME;
416 lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
417 }
418 if (lss.change&TCF_CBQ_LSS_MINIDLE) {
419 lss.minidle <<= lss.ewma_log;
420 lss.change |= TCF_CBQ_LSS_EWMA;
421 }
422
c14f9d92 423 tail = addattr_nest(n, 1024, TCA_OPTIONS);
aba5acdf
SH
424 if (lss.change) {
425 lss.change |= TCF_CBQ_LSS_FLAGS;
426 addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
427 }
428 if (wrr_ok)
429 addattr_l(n, 1024, TCA_CBQ_WRROPT, &wrr, sizeof(wrr));
430 if (fopt_ok)
431 addattr_l(n, 1024, TCA_CBQ_FOPT, &fopt, sizeof(fopt));
432 if (r.rate) {
433 addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r));
434 addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
435 if (show_raw) {
436 int i;
32a121cb
SH
437
438 for (i = 0; i < 256; i++)
aba5acdf
SH
439 printf("%u ", rtab[i]);
440 printf("\n");
441 }
442 }
c14f9d92 443 addattr_nest_end(n, tail);
aba5acdf
SH
444 return 0;
445}
446
447
448static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
449{
450 struct rtattr *tb[TCA_CBQ_MAX+1];
451 struct tc_ratespec *r = NULL;
452 struct tc_cbq_lssopt *lss = NULL;
453 struct tc_cbq_wrropt *wrr = NULL;
454 struct tc_cbq_fopt *fopt = NULL;
455 struct tc_cbq_ovl *ovl = NULL;
3e92ff52 456 unsigned int linklayer;
32a121cb 457
bd29e35d 458 SPRINT_BUF(b1);
3e92ff52 459 SPRINT_BUF(b2);
aba5acdf
SH
460
461 if (opt == NULL)
462 return 0;
463
021ed13f 464 parse_rtattr_nested(tb, TCA_CBQ_MAX, opt);
aba5acdf
SH
465
466 if (tb[TCA_CBQ_RATE]) {
467 if (RTA_PAYLOAD(tb[TCA_CBQ_RATE]) < sizeof(*r))
468 fprintf(stderr, "CBQ: too short rate opt\n");
469 else
470 r = RTA_DATA(tb[TCA_CBQ_RATE]);
471 }
472 if (tb[TCA_CBQ_LSSOPT]) {
473 if (RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT]) < sizeof(*lss))
474 fprintf(stderr, "CBQ: too short lss opt\n");
475 else
476 lss = RTA_DATA(tb[TCA_CBQ_LSSOPT]);
477 }
478 if (tb[TCA_CBQ_WRROPT]) {
479 if (RTA_PAYLOAD(tb[TCA_CBQ_WRROPT]) < sizeof(*wrr))
480 fprintf(stderr, "CBQ: too short wrr opt\n");
481 else
482 wrr = RTA_DATA(tb[TCA_CBQ_WRROPT]);
483 }
484 if (tb[TCA_CBQ_FOPT]) {
485 if (RTA_PAYLOAD(tb[TCA_CBQ_FOPT]) < sizeof(*fopt))
486 fprintf(stderr, "CBQ: too short fopt\n");
487 else
488 fopt = RTA_DATA(tb[TCA_CBQ_FOPT]);
489 }
490 if (tb[TCA_CBQ_OVL_STRATEGY]) {
491 if (RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(*ovl))
492 fprintf(stderr, "CBQ: too short overlimit strategy %u/%u\n",
32a121cb
SH
493 (unsigned int) RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]),
494 (unsigned int) sizeof(*ovl));
aba5acdf
SH
495 else
496 ovl = RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY]);
497 }
498
499 if (r) {
500 char buf[64];
32a121cb 501
aba5acdf
SH
502 print_rate(buf, sizeof(buf), r->rate);
503 fprintf(f, "rate %s ", buf);
3e92ff52
JDB
504 linklayer = (r->linklayer & TC_LINKLAYER_MASK);
505 if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
506 fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
aba5acdf
SH
507 if (show_details) {
508 fprintf(f, "cell %ub ", 1<<r->cell_log);
509 if (r->mpu)
510 fprintf(f, "mpu %ub ", r->mpu);
08fd0184
JDB
511 if (r->overhead)
512 fprintf(f, "overhead %ub ", r->overhead);
aba5acdf
SH
513 }
514 }
515 if (lss && lss->flags) {
32a121cb
SH
516 int comma = 0;
517
aba5acdf
SH
518 fprintf(f, "(");
519 if (lss->flags&TCF_CBQ_LSS_BOUNDED) {
520 fprintf(f, "bounded");
32a121cb 521 comma = 1;
aba5acdf
SH
522 }
523 if (lss->flags&TCF_CBQ_LSS_ISOLATED) {
524 if (comma)
525 fprintf(f, ",");
526 fprintf(f, "isolated");
527 }
528 fprintf(f, ") ");
529 }
530 if (wrr) {
531 if (wrr->priority != TC_CBQ_MAXPRIO)
532 fprintf(f, "prio %u", wrr->priority);
533 else
534 fprintf(f, "prio no-transmit");
535 if (show_details) {
536 char buf[64];
32a121cb 537
aba5acdf
SH
538 fprintf(f, "/%u ", wrr->cpriority);
539 if (wrr->weight != 1) {
540 print_rate(buf, sizeof(buf), wrr->weight);
541 fprintf(f, "weight %s ", buf);
542 }
543 if (wrr->allot)
544 fprintf(f, "allot %ub ", wrr->allot);
545 }
546 }
547 if (lss && show_details) {
548 fprintf(f, "\nlevel %u ewma %u avpkt %ub ", lss->level, lss->ewma_log, lss->avpkt);
549 if (lss->maxidle) {
bd29e35d 550 fprintf(f, "maxidle %s ", sprint_ticks(lss->maxidle>>lss->ewma_log, b1));
aba5acdf
SH
551 if (show_raw)
552 fprintf(f, "[%08x] ", lss->maxidle);
553 }
32a121cb 554 if (lss->minidle != 0x7fffffff) {
bd29e35d 555 fprintf(f, "minidle %s ", sprint_ticks(lss->minidle>>lss->ewma_log, b1));
aba5acdf
SH
556 if (show_raw)
557 fprintf(f, "[%08x] ", lss->minidle);
558 }
559 if (lss->offtime) {
bd29e35d 560 fprintf(f, "offtime %s ", sprint_ticks(lss->offtime, b1));
aba5acdf
SH
561 if (show_raw)
562 fprintf(f, "[%08x] ", lss->offtime);
563 }
564 }
565 if (fopt && show_details) {
566 char buf[64];
32a121cb 567
aba5acdf
SH
568 print_tc_classid(buf, sizeof(buf), fopt->split);
569 fprintf(f, "\nsplit %s ", buf);
570 if (fopt->defmap) {
571 fprintf(f, "defmap %08x", fopt->defmap);
572 }
573 }
574 return 0;
575}
576
577static int cbq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
578{
579 struct tc_cbq_xstats *st;
580
581 if (xstats == NULL)
582 return 0;
583
584 if (RTA_PAYLOAD(xstats) < sizeof(*st))
585 return -1;
586
587 st = RTA_DATA(xstats);
588 fprintf(f, " borrowed %u overactions %u avgidle %g undertime %g", st->borrows,
589 st->overactions, (double)st->avgidle, (double)st->undertime);
590 return 0;
591}
592
95812b56 593struct qdisc_util cbq_qdisc_util = {
f2f99e2e
SH
594 .id = "cbq",
595 .parse_qopt = cbq_parse_opt,
596 .print_qopt = cbq_print_opt,
597 .print_xstats = cbq_print_xstats,
598 .parse_copt = cbq_parse_class_opt,
599 .print_copt = cbq_print_opt,
aba5acdf 600};