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