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