blob: faad735045aa8d0f7bd62e7daf4379443e2bdfc1 [file] [log] [blame]
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +00001/*
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>
16#include <syslog.h>
17#include <fcntl.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <arpa/inet.h>
21#include <string.h>
22
23#include "utils.h"
24#include "tc_util.h"
25#include "tc_cbq.h"
26
27static void explain_class(void)
28{
29 fprintf(stderr, "Usage: ... cbq bandwidth BPS rate BPS maxburst PKTS [ avpkt BYTES ]\n");
30 fprintf(stderr, " [ minburst PKTS ] [ bounded ] [ isolated ]\n");
31 fprintf(stderr, " [ allot BYTES ] [ mpu BYTES ] [ weight RATE ]\n");
32 fprintf(stderr, " [ prio NUMBER ] [ cell BYTES ] [ ewma LOG ]\n");
33 fprintf(stderr, " [ estimator INTERVAL TIME_CONSTANT ]\n");
34 fprintf(stderr, " [ split CLASSID ] [ defmap MASK/CHANGE ]\n");
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +020035 fprintf(stderr, " [ overhead BYTES ] [ linklayer TYPE ]\n");
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000036}
37
38static void explain(void)
39{
40 fprintf(stderr, "Usage: ... cbq bandwidth BPS avpkt BYTES [ mpu BYTES ]\n");
41 fprintf(stderr, " [ cell BYTES ] [ ewma LOG ]\n");
42}
43
44static void explain1(char *arg)
45{
46 fprintf(stderr, "Illegal \"%s\"\n", arg);
47}
48
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000049
50static int cbq_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
51{
52 struct tc_ratespec r;
53 struct tc_cbq_lssopt lss;
54 __u32 rtab[256];
Stephen Hemminger32a121c2016-03-21 11:48:36 -070055 unsigned mpu = 0, avpkt = 0, allot = 0;
56 unsigned short overhead = 0;
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +020057 unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
Stephen Hemminger32a121c2016-03-21 11:48:36 -070058 int cell_log = -1;
59 int ewma_log = -1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000060 struct rtattr *tail;
61
62 memset(&lss, 0, sizeof(lss));
63 memset(&r, 0, sizeof(r));
64
65 while (argc > 0) {
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +010066 if (matches(*argv, "bandwidth") == 0 ||
67 matches(*argv, "rate") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000068 NEXT_ARG();
69 if (get_rate(&r.rate, *argv)) {
70 explain1("bandwidth");
71 return -1;
72 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +010073 } else if (matches(*argv, "ewma") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000074 NEXT_ARG();
shemmingerf332d162005-07-05 22:37:15 +000075 if (get_integer(&ewma_log, *argv, 0)) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000076 explain1("ewma");
77 return -1;
78 }
79 if (ewma_log > 31) {
80 fprintf(stderr, "ewma_log must be < 32\n");
81 return -1;
82 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +010083 } else if (matches(*argv, "cell") == 0) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -070084 unsigned int cell;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000085 int i;
Stephen Hemminger32a121c2016-03-21 11:48:36 -070086
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000087 NEXT_ARG();
88 if (get_size(&cell, *argv)) {
89 explain1("cell");
90 return -1;
91 }
Stephen Hemminger32a121c2016-03-21 11:48:36 -070092 for (i = 0; i < 32; i++)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000093 if ((1<<i) == cell)
94 break;
Stephen Hemminger32a121c2016-03-21 11:48:36 -070095 if (i >= 32) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +000096 fprintf(stderr, "cell must be 2^n\n");
97 return -1;
98 }
99 cell_log = i;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100100 } else if (matches(*argv, "avpkt") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000101 NEXT_ARG();
102 if (get_size(&avpkt, *argv)) {
103 explain1("avpkt");
104 return -1;
105 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100106 } else if (matches(*argv, "mpu") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000107 NEXT_ARG();
108 if (get_size(&mpu, *argv)) {
109 explain1("mpu");
110 return -1;
111 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100112 } else if (matches(*argv, "allot") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000113 NEXT_ARG();
114 /* Accept and ignore "allot" for backward compatibility */
115 if (get_size(&allot, *argv)) {
116 explain1("allot");
117 return -1;
118 }
Jesper Dangaard Brouer08fd0182008-03-23 23:50:49 +0100119 } else if (matches(*argv, "overhead") == 0) {
120 NEXT_ARG();
121 if (get_u16(&overhead, *argv, 10)) {
122 explain1("overhead"); return -1;
123 }
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +0200124 } else if (matches(*argv, "linklayer") == 0) {
125 NEXT_ARG();
126 if (get_linklayer(&linklayer, *argv)) {
127 explain1("linklayer"); return -1;
128 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100129 } else if (matches(*argv, "help") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000130 explain();
131 return -1;
132 } else {
133 fprintf(stderr, "What is \"%s\"?\n", *argv);
134 explain();
135 return -1;
136 }
137 argc--; argv++;
138 }
139
140 /* OK. All options are parsed. */
141
142 if (r.rate == 0) {
143 fprintf(stderr, "CBQ: bandwidth is required parameter.\n");
144 return -1;
145 }
146 if (avpkt == 0) {
147 fprintf(stderr, "CBQ: \"avpkt\" is required.\n");
148 return -1;
149 }
150 if (allot < (avpkt*3)/2)
151 allot = (avpkt*3)/2;
152
Jesper Dangaard Brouerd5f46f92007-09-05 10:47:47 +0200153 r.mpu = mpu;
Jesper Dangaard Brouer08fd0182008-03-23 23:50:49 +0100154 r.overhead = overhead;
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +0200155 if (tc_calc_rtable(&r, rtab, cell_log, allot, linklayer) < 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000156 fprintf(stderr, "CBQ: failed to calculate rate table.\n");
157 return -1;
158 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000159
160 if (ewma_log < 0)
161 ewma_log = TC_CBQ_DEF_EWMA;
162 lss.ewma_log = ewma_log;
Patrick McHardy476daa72007-03-04 20:14:56 +0100163 lss.maxidle = tc_calc_xmittime(r.rate, avpkt);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000164 lss.change = TCF_CBQ_LSS_MAXIDLE|TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
165 lss.avpkt = avpkt;
166
5!tgraf034102f2005-01-18 01:24:18 +0000167 tail = NLMSG_TAIL(n);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000168 addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
169 addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r));
170 addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
171 addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
172 if (show_raw) {
173 int i;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700174
175 for (i = 0; i < 256; i++)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000176 printf("%u ", rtab[i]);
177 printf("\n");
178 }
5!tgraf034102f2005-01-18 01:24:18 +0000179 tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000180 return 0;
181}
182
183static int cbq_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
184{
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700185 int wrr_ok = 0, fopt_ok = 0;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000186 struct tc_ratespec r;
187 struct tc_cbq_lssopt lss;
188 struct tc_cbq_wrropt wrr;
189 struct tc_cbq_fopt fopt;
190 struct tc_cbq_ovl ovl;
191 __u32 rtab[256];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700192 unsigned mpu = 0;
193 int cell_log = -1;
194 int ewma_log = -1;
195 unsigned int bndw = 0;
196 unsigned minburst = 0, maxburst = 0;
197 unsigned short overhead = 0;
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +0200198 unsigned int linklayer = LINKLAYER_ETHERNET; /* Assume ethernet */
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000199 struct rtattr *tail;
200
201 memset(&r, 0, sizeof(r));
202 memset(&lss, 0, sizeof(lss));
203 memset(&wrr, 0, sizeof(wrr));
204 memset(&fopt, 0, sizeof(fopt));
205 memset(&ovl, 0, sizeof(ovl));
206
207 while (argc > 0) {
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100208 if (matches(*argv, "rate") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000209 NEXT_ARG();
210 if (get_rate(&r.rate, *argv)) {
211 explain1("rate");
212 return -1;
213 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100214 } else if (matches(*argv, "bandwidth") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000215 NEXT_ARG();
216 if (get_rate(&bndw, *argv)) {
217 explain1("bandwidth");
218 return -1;
219 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100220 } else if (matches(*argv, "minidle") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000221 NEXT_ARG();
222 if (get_u32(&lss.minidle, *argv, 0)) {
223 explain1("minidle");
224 return -1;
225 }
226 lss.change |= TCF_CBQ_LSS_MINIDLE;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100227 } else if (matches(*argv, "minburst") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000228 NEXT_ARG();
229 if (get_u32(&minburst, *argv, 0)) {
230 explain1("minburst");
231 return -1;
232 }
233 lss.change |= TCF_CBQ_LSS_OFFTIME;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100234 } else if (matches(*argv, "maxburst") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000235 NEXT_ARG();
236 if (get_u32(&maxburst, *argv, 0)) {
237 explain1("maxburst");
238 return -1;
239 }
240 lss.change |= TCF_CBQ_LSS_MAXIDLE;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100241 } else if (matches(*argv, "bounded") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000242 lss.flags |= TCF_CBQ_LSS_BOUNDED;
243 lss.change |= TCF_CBQ_LSS_FLAGS;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100244 } else if (matches(*argv, "borrow") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000245 lss.flags &= ~TCF_CBQ_LSS_BOUNDED;
246 lss.change |= TCF_CBQ_LSS_FLAGS;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100247 } else if (matches(*argv, "isolated") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000248 lss.flags |= TCF_CBQ_LSS_ISOLATED;
249 lss.change |= TCF_CBQ_LSS_FLAGS;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100250 } else if (matches(*argv, "sharing") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000251 lss.flags &= ~TCF_CBQ_LSS_ISOLATED;
252 lss.change |= TCF_CBQ_LSS_FLAGS;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100253 } else if (matches(*argv, "ewma") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000254 NEXT_ARG();
shemmingerf332d162005-07-05 22:37:15 +0000255 if (get_integer(&ewma_log, *argv, 0)) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000256 explain1("ewma");
257 return -1;
258 }
259 if (ewma_log > 31) {
260 fprintf(stderr, "ewma_log must be < 32\n");
261 return -1;
262 }
263 lss.change |= TCF_CBQ_LSS_EWMA;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100264 } else if (matches(*argv, "cell") == 0) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700265 unsigned int cell;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000266 int i;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700267
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000268 NEXT_ARG();
269 if (get_size(&cell, *argv)) {
270 explain1("cell");
271 return -1;
272 }
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700273 for (i = 0; i < 32; i++)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000274 if ((1<<i) == cell)
275 break;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700276 if (i >= 32) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000277 fprintf(stderr, "cell must be 2^n\n");
278 return -1;
279 }
280 cell_log = i;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100281 } else if (matches(*argv, "prio") == 0) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700282 unsigned int prio;
283
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000284 NEXT_ARG();
285 if (get_u32(&prio, *argv, 0)) {
286 explain1("prio");
287 return -1;
288 }
289 if (prio > TC_CBQ_MAXPRIO) {
290 fprintf(stderr, "\"prio\" must be number in the range 1...%d\n", TC_CBQ_MAXPRIO);
291 return -1;
292 }
293 wrr.priority = prio;
294 wrr_ok++;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100295 } else if (matches(*argv, "allot") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000296 NEXT_ARG();
297 if (get_size(&wrr.allot, *argv)) {
298 explain1("allot");
299 return -1;
300 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100301 } else if (matches(*argv, "avpkt") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000302 NEXT_ARG();
303 if (get_size(&lss.avpkt, *argv)) {
304 explain1("avpkt");
305 return -1;
306 }
307 lss.change |= TCF_CBQ_LSS_AVPKT;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100308 } else if (matches(*argv, "mpu") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000309 NEXT_ARG();
310 if (get_size(&mpu, *argv)) {
311 explain1("mpu");
312 return -1;
313 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100314 } else if (matches(*argv, "weight") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000315 NEXT_ARG();
316 if (get_size(&wrr.weight, *argv)) {
317 explain1("weight");
318 return -1;
319 }
320 wrr_ok++;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100321 } else if (matches(*argv, "split") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000322 NEXT_ARG();
323 if (get_tc_classid(&fopt.split, *argv)) {
324 fprintf(stderr, "Invalid split node ID.\n");
Florian Westphal8d8de112010-01-12 21:45:01 +0100325 return -1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000326 }
327 fopt_ok++;
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100328 } else if (matches(*argv, "defmap") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000329 int err;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700330
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000331 NEXT_ARG();
332 err = sscanf(*argv, "%08x/%08x", &fopt.defmap, &fopt.defchange);
333 if (err < 1) {
334 fprintf(stderr, "Invalid defmap, should be MASK32[/MASK]\n");
335 return -1;
336 }
337 if (err == 1)
338 fopt.defchange = ~0;
339 fopt_ok++;
Jesper Dangaard Brouer08fd0182008-03-23 23:50:49 +0100340 } else if (matches(*argv, "overhead") == 0) {
341 NEXT_ARG();
342 if (get_u16(&overhead, *argv, 10)) {
343 explain1("overhead"); return -1;
344 }
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +0200345 } else if (matches(*argv, "linklayer") == 0) {
346 NEXT_ARG();
347 if (get_linklayer(&linklayer, *argv)) {
348 explain1("linklayer"); return -1;
349 }
Jesper Dangaard Brouer1db5e2e2008-03-23 23:49:11 +0100350 } else if (matches(*argv, "help") == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000351 explain_class();
352 return -1;
353 } else {
354 fprintf(stderr, "What is \"%s\"?\n", *argv);
355 explain_class();
356 return -1;
357 }
358 argc--; argv++;
359 }
360
361 /* OK. All options are parsed. */
362
363 /* 1. Prepare link sharing scheduler parameters */
364 if (r.rate) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700365 unsigned int pktsize = wrr.allot;
366
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000367 if (wrr.allot < (lss.avpkt*3)/2)
368 wrr.allot = (lss.avpkt*3)/2;
Jesper Dangaard Brouerd5f46f92007-09-05 10:47:47 +0200369 r.mpu = mpu;
Jesper Dangaard Brouer08fd0182008-03-23 23:50:49 +0100370 r.overhead = overhead;
Jesper Dangaard Brouer292f29b2008-04-09 23:01:01 +0200371 if (tc_calc_rtable(&r, rtab, cell_log, pktsize, linklayer) < 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000372 fprintf(stderr, "CBQ: failed to calculate rate table.\n");
373 return -1;
374 }
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000375 }
376 if (ewma_log < 0)
377 ewma_log = TC_CBQ_DEF_EWMA;
378 lss.ewma_log = ewma_log;
379 if (lss.change&(TCF_CBQ_LSS_OFFTIME|TCF_CBQ_LSS_MAXIDLE)) {
380 if (lss.avpkt == 0) {
381 fprintf(stderr, "CBQ: avpkt is required for max/minburst.\n");
382 return -1;
383 }
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700384 if (bndw == 0 || r.rate == 0) {
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000385 fprintf(stderr, "CBQ: bandwidth&rate are required for max/minburst.\n");
386 return -1;
387 }
388 }
389 if (wrr.priority == 0 && (n->nlmsg_flags&NLM_F_EXCL)) {
390 wrr_ok = 1;
391 wrr.priority = TC_CBQ_MAXPRIO;
392 if (wrr.allot == 0)
393 wrr.allot = (lss.avpkt*3)/2;
394 }
395 if (wrr_ok) {
396 if (wrr.weight == 0)
397 wrr.weight = (wrr.priority == TC_CBQ_MAXPRIO) ? 1 : r.rate;
398 if (wrr.allot == 0) {
399 fprintf(stderr, "CBQ: \"allot\" is required to set WRR parameters.\n");
400 return -1;
401 }
402 }
403 if (lss.change&TCF_CBQ_LSS_MAXIDLE) {
404 lss.maxidle = tc_cbq_calc_maxidle(bndw, r.rate, lss.avpkt, ewma_log, maxburst);
405 lss.change |= TCF_CBQ_LSS_MAXIDLE;
406 lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
407 }
408 if (lss.change&TCF_CBQ_LSS_OFFTIME) {
409 lss.offtime = tc_cbq_calc_offtime(bndw, r.rate, lss.avpkt, ewma_log, minburst);
410 lss.change |= TCF_CBQ_LSS_OFFTIME;
411 lss.change |= TCF_CBQ_LSS_EWMA|TCF_CBQ_LSS_AVPKT;
412 }
413 if (lss.change&TCF_CBQ_LSS_MINIDLE) {
414 lss.minidle <<= lss.ewma_log;
415 lss.change |= TCF_CBQ_LSS_EWMA;
416 }
417
5!tgraf034102f2005-01-18 01:24:18 +0000418 tail = NLMSG_TAIL(n);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000419 addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
420 if (lss.change) {
421 lss.change |= TCF_CBQ_LSS_FLAGS;
422 addattr_l(n, 1024, TCA_CBQ_LSSOPT, &lss, sizeof(lss));
423 }
424 if (wrr_ok)
425 addattr_l(n, 1024, TCA_CBQ_WRROPT, &wrr, sizeof(wrr));
426 if (fopt_ok)
427 addattr_l(n, 1024, TCA_CBQ_FOPT, &fopt, sizeof(fopt));
428 if (r.rate) {
429 addattr_l(n, 1024, TCA_CBQ_RATE, &r, sizeof(r));
430 addattr_l(n, 3024, TCA_CBQ_RTAB, rtab, 1024);
431 if (show_raw) {
432 int i;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700433
434 for (i = 0; i < 256; i++)
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000435 printf("%u ", rtab[i]);
436 printf("\n");
437 }
438 }
5!tgraf034102f2005-01-18 01:24:18 +0000439 tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000440 return 0;
441}
442
443
444static int cbq_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
445{
446 struct rtattr *tb[TCA_CBQ_MAX+1];
447 struct tc_ratespec *r = NULL;
448 struct tc_cbq_lssopt *lss = NULL;
449 struct tc_cbq_wrropt *wrr = NULL;
450 struct tc_cbq_fopt *fopt = NULL;
451 struct tc_cbq_ovl *ovl = NULL;
Jesper Dangaard Brouer3e92ff52013-08-30 14:02:10 +0200452 unsigned int linklayer;
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700453
Patrick McHardybd29e352007-03-04 20:15:01 +0100454 SPRINT_BUF(b1);
Jesper Dangaard Brouer3e92ff52013-08-30 14:02:10 +0200455 SPRINT_BUF(b2);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000456
457 if (opt == NULL)
458 return 0;
459
5!tgraf021ed132005-01-18 22:11:58 +0000460 parse_rtattr_nested(tb, TCA_CBQ_MAX, opt);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000461
462 if (tb[TCA_CBQ_RATE]) {
463 if (RTA_PAYLOAD(tb[TCA_CBQ_RATE]) < sizeof(*r))
464 fprintf(stderr, "CBQ: too short rate opt\n");
465 else
466 r = RTA_DATA(tb[TCA_CBQ_RATE]);
467 }
468 if (tb[TCA_CBQ_LSSOPT]) {
469 if (RTA_PAYLOAD(tb[TCA_CBQ_LSSOPT]) < sizeof(*lss))
470 fprintf(stderr, "CBQ: too short lss opt\n");
471 else
472 lss = RTA_DATA(tb[TCA_CBQ_LSSOPT]);
473 }
474 if (tb[TCA_CBQ_WRROPT]) {
475 if (RTA_PAYLOAD(tb[TCA_CBQ_WRROPT]) < sizeof(*wrr))
476 fprintf(stderr, "CBQ: too short wrr opt\n");
477 else
478 wrr = RTA_DATA(tb[TCA_CBQ_WRROPT]);
479 }
480 if (tb[TCA_CBQ_FOPT]) {
481 if (RTA_PAYLOAD(tb[TCA_CBQ_FOPT]) < sizeof(*fopt))
482 fprintf(stderr, "CBQ: too short fopt\n");
483 else
484 fopt = RTA_DATA(tb[TCA_CBQ_FOPT]);
485 }
486 if (tb[TCA_CBQ_OVL_STRATEGY]) {
487 if (RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]) < sizeof(*ovl))
488 fprintf(stderr, "CBQ: too short overlimit strategy %u/%u\n",
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700489 (unsigned int) RTA_PAYLOAD(tb[TCA_CBQ_OVL_STRATEGY]),
490 (unsigned int) sizeof(*ovl));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000491 else
492 ovl = RTA_DATA(tb[TCA_CBQ_OVL_STRATEGY]);
493 }
494
495 if (r) {
496 char buf[64];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700497
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000498 print_rate(buf, sizeof(buf), r->rate);
499 fprintf(f, "rate %s ", buf);
Jesper Dangaard Brouer3e92ff52013-08-30 14:02:10 +0200500 linklayer = (r->linklayer & TC_LINKLAYER_MASK);
501 if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
502 fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b2));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000503 if (show_details) {
504 fprintf(f, "cell %ub ", 1<<r->cell_log);
505 if (r->mpu)
506 fprintf(f, "mpu %ub ", r->mpu);
Jesper Dangaard Brouer08fd0182008-03-23 23:50:49 +0100507 if (r->overhead)
508 fprintf(f, "overhead %ub ", r->overhead);
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000509 }
510 }
511 if (lss && lss->flags) {
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700512 int comma = 0;
513
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000514 fprintf(f, "(");
515 if (lss->flags&TCF_CBQ_LSS_BOUNDED) {
516 fprintf(f, "bounded");
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700517 comma = 1;
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000518 }
519 if (lss->flags&TCF_CBQ_LSS_ISOLATED) {
520 if (comma)
521 fprintf(f, ",");
522 fprintf(f, "isolated");
523 }
524 fprintf(f, ") ");
525 }
526 if (wrr) {
527 if (wrr->priority != TC_CBQ_MAXPRIO)
528 fprintf(f, "prio %u", wrr->priority);
529 else
530 fprintf(f, "prio no-transmit");
531 if (show_details) {
532 char buf[64];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700533
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000534 fprintf(f, "/%u ", wrr->cpriority);
535 if (wrr->weight != 1) {
536 print_rate(buf, sizeof(buf), wrr->weight);
537 fprintf(f, "weight %s ", buf);
538 }
539 if (wrr->allot)
540 fprintf(f, "allot %ub ", wrr->allot);
541 }
542 }
543 if (lss && show_details) {
544 fprintf(f, "\nlevel %u ewma %u avpkt %ub ", lss->level, lss->ewma_log, lss->avpkt);
545 if (lss->maxidle) {
Patrick McHardybd29e352007-03-04 20:15:01 +0100546 fprintf(f, "maxidle %s ", sprint_ticks(lss->maxidle>>lss->ewma_log, b1));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000547 if (show_raw)
548 fprintf(f, "[%08x] ", lss->maxidle);
549 }
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700550 if (lss->minidle != 0x7fffffff) {
Patrick McHardybd29e352007-03-04 20:15:01 +0100551 fprintf(f, "minidle %s ", sprint_ticks(lss->minidle>>lss->ewma_log, b1));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000552 if (show_raw)
553 fprintf(f, "[%08x] ", lss->minidle);
554 }
555 if (lss->offtime) {
Patrick McHardybd29e352007-03-04 20:15:01 +0100556 fprintf(f, "offtime %s ", sprint_ticks(lss->offtime, b1));
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000557 if (show_raw)
558 fprintf(f, "[%08x] ", lss->offtime);
559 }
560 }
561 if (fopt && show_details) {
562 char buf[64];
Stephen Hemminger32a121c2016-03-21 11:48:36 -0700563
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000564 print_tc_classid(buf, sizeof(buf), fopt->split);
565 fprintf(f, "\nsplit %s ", buf);
566 if (fopt->defmap) {
567 fprintf(f, "defmap %08x", fopt->defmap);
568 }
569 }
570 return 0;
571}
572
573static int cbq_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
574{
575 struct tc_cbq_xstats *st;
576
577 if (xstats == NULL)
578 return 0;
579
580 if (RTA_PAYLOAD(xstats) < sizeof(*st))
581 return -1;
582
583 st = RTA_DATA(xstats);
584 fprintf(f, " borrowed %u overactions %u avgidle %g undertime %g", st->borrows,
585 st->overactions, (double)st->avgidle, (double)st->undertime);
586 return 0;
587}
588
net[shemminger]!kaber95812b52004-09-28 18:35:49 +0000589struct qdisc_util cbq_qdisc_util = {
osdl.net!shemmingerf2f99e22004-08-31 17:45:21 +0000590 .id = "cbq",
591 .parse_qopt = cbq_parse_opt,
592 .print_qopt = cbq_print_opt,
593 .print_xstats = cbq_print_xstats,
594 .parse_copt = cbq_parse_class_opt,
595 .print_copt = cbq_print_opt,
osdl.org!shemmingeraba5acd2004-04-15 20:56:59 +0000596};