19e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger/*
29e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger * q_htb.c		HTB.
39e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *
49e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *		This program is free software; you can redistribute it and/or
59e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *		modify it under the terms of the GNU General Public License
69e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *		as published by the Free Software Foundation; either version
79e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *		2 of the License, or (at your option) any later version.
89e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *
99e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger * Authors:	Martin Devera, devik@cdi.cz
109e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger *
119e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger */
129e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
139e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <stdio.h>
149e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <stdlib.h>
159e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <unistd.h>
169e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <syslog.h>
179e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <fcntl.h>
189e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <sys/socket.h>
199e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <netinet/in.h>
209e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <arpa/inet.h>
219e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include <string.h>
229e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
239e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include "utils.h"
249e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#include "tc_util.h"
259e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
269e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#define HTB_TC_VER 0x30003
279e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#if HTB_TC_VER >> 16 != TC_HTB_PROTOVER
289e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#error "Different kernel and TC HTB versions"
299e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger#endif
309e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
319e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic void explain(void)
329e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
339e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	fprintf(stderr, "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
34b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet		"                      [direct_qlen P]\n"
359e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" default  minor id of class to which unclassified packets are sent {0}\n"
369e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" r2q      DRR quantums are computed as rate in Bps/r2q {10}\n"
379e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" debug    string of 16 numbers each 0-3 {0}\n\n"
38b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet		" direct_qlen  Limit of the direct queue {in packets}\n"
39a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		"... class add ... htb rate R1 [burst B1] [mpu B] [overhead O]\n"
40a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		"                      [prio P] [slot S] [pslot PS]\n"
419e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		"                      [ceil R2] [cburst B2] [mtu MTU] [quantum Q]\n"
429e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" rate     rate allocated to this class (class can still borrow)\n"
439e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" burst    max bytes burst which can be accumulated during idle period {computed}\n"
44a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		" mpu      minimum packet size used in rate computations\n"
45a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		" overhead per-packet size overhead used in rate computations\n"
46292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		" linklay  adapting to a linklayer e.g. atm\n"
479e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" ceil     definite upper class rate (no borrows) {rate}\n"
489e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" cburst   burst but for ceil {computed}\n"
499e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" mtu      max packet size we create rate map for {1600}\n"
509e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" prio     priority of leaf; lower are served first {0}\n"
519e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		" quantum  how much bytes to serve from leaf at once {use r2q}\n"
529e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		"\nTC HTB version %d.%d\n",HTB_TC_VER>>16,HTB_TC_VER&0xffff
539e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		);
549e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
559e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
569e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic void explain1(char *arg)
579e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
589e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger    fprintf(stderr, "Illegal \"%s\"\n", arg);
599e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger    explain();
609e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
619e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
629e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
639e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
649e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
654d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA	unsigned int direct_qlen = ~0U;
669e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct tc_htb_glob opt;
679e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct rtattr *tail;
689e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	unsigned i; char *p;
699e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	memset(&opt,0,sizeof(opt));
709e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	opt.rate2quantum = 10;
719e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	opt.version = 3;
729e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
739e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	while (argc > 0) {
749e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		if (matches(*argv, "r2q") == 0) {
7522fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			NEXT_ARG();
7622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			if (get_u32(&opt.rate2quantum, *argv, 10)) {
7722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				explain1("r2q"); return -1;
7822fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			}
799e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "default") == 0) {
8022fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			NEXT_ARG();
8122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			if (get_u32(&opt.defcls, *argv, 16)) {
8222fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				explain1("default"); return -1;
8322fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			}
849e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "debug") == 0) {
8522fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			NEXT_ARG(); p = *argv;
8622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			for (i=0; i<16; i++,p++) {
8722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				if (*p<'0' || *p>'3') break;
8822fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				opt.debug |= (*p-'0')<<(2*i);
8922fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			}
904d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA		} else if (matches(*argv, "direct_qlen") == 0) {
914d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA			NEXT_ARG();
924d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA			if (get_u32(&direct_qlen, *argv, 10)) {
934d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA				explain1("direct_qlen"); return -1;
944d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA			}
959e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else {
969e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			fprintf(stderr, "What is \"%s\"?\n", *argv);
979e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			explain();
989e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			return -1;
999e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		}
1009e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		argc--; argv++;
1019e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
1021b52a7622ea8eda9980ce2dbe984985ac092d92an);	tail = NLMSG_TAIL(n);
1039e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
1049e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 2024, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt)));
1054d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA	if (direct_qlen != ~0U)
1064d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA		addattr_l(n, 2024, TCA_HTB_DIRECT_QLEN,
1074d4da09e0036107e7c49362b38df220e9a2f7b12Hiroaki SHIMODA			  &direct_qlen, sizeof(direct_qlen));
1081b52a7622ea8eda9980ce2dbe984985ac092d92avoid *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
1099e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	return 0;
1109e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
1119e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
1129e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
1139e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
1149e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	int ok=0;
1159e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct tc_htb_opt opt;
1169e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	__u32 rtab[256],ctab[256];
1179e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	unsigned buffer=0,cbuffer=0;
118a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger	int cell_log=-1,ccell_log = -1;
119bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	unsigned mtu;
120bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	unsigned short mpu = 0;
121bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	unsigned short overhead = 0;
122292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	unsigned int linklayer  = LINKLAYER_ETHERNET; /* Assume ethernet */
1239e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct rtattr *tail;
1248334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	__u64 ceil64 = 0, rate64 = 0;
1259e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
1269e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
1279e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
1289e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	while (argc > 0) {
1299e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		if (matches(*argv, "prio") == 0) {
1309e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1319e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (get_u32(&opt.prio, *argv, 10)) {
1329e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("prio"); return -1;
1339e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1349e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			ok++;
1359e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "mtu") == 0) {
1369e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1379e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (get_u32(&mtu, *argv, 10)) {
1389e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("mtu"); return -1;
1399e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
140a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		} else if (matches(*argv, "mpu") == 0) {
141a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger			NEXT_ARG();
142bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer			if (get_u16(&mpu, *argv, 10)) {
143a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger				explain1("mpu"); return -1;
144a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger			}
145a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger		} else if (matches(*argv, "overhead") == 0) {
146a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger			NEXT_ARG();
147bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer			if (get_u16(&overhead, *argv, 10)) {
148a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger				explain1("overhead"); return -1;
149a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger			}
150292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer		} else if (matches(*argv, "linklayer") == 0) {
151292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer			NEXT_ARG();
152292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer			if (get_linklayer(&linklayer, *argv)) {
153292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer				explain1("linklayer"); return -1;
154292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer			}
1559e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "quantum") == 0) {
1569e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1579e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (get_u32(&opt.quantum, *argv, 10)) {
1589e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("quantum"); return -1;
1599e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1609e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "burst") == 0 ||
16122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			   strcmp(*argv, "buffer") == 0 ||
16222fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			   strcmp(*argv, "maxburst") == 0) {
1639e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1649e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
1659e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("buffer");
1669e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1679e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1689e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			ok++;
1699e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (matches(*argv, "cburst") == 0 ||
17022fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			   strcmp(*argv, "cbuffer") == 0 ||
17122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			   strcmp(*argv, "cmaxburst") == 0) {
1729e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1739e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
1749e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("cbuffer");
1759e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1769e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1779e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			ok++;
1789e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (strcmp(*argv, "ceil") == 0) {
1799e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1808334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			if (ceil64) {
1819e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				fprintf(stderr, "Double \"ceil\" spec\n");
1829e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1839e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1848334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			if (get_rate64(&ceil64, *argv)) {
1859e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("ceil");
1869e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1879e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1889e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			ok++;
1899e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (strcmp(*argv, "rate") == 0) {
1909e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			NEXT_ARG();
1918334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			if (rate64) {
1929e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				fprintf(stderr, "Double \"rate\" spec\n");
1939e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1949e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1958334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			if (get_rate64(&rate64, *argv)) {
1969e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				explain1("rate");
1979e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				return -1;
1989e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			}
1999e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			ok++;
2009e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else if (strcmp(*argv, "help") == 0) {
2019e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			explain();
2029e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			return -1;
2039e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		} else {
2049e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			fprintf(stderr, "What is \"%s\"?\n", *argv);
2059e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			explain();
2069e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			return -1;
2079e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		}
2089e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		argc--; argv++;
2099e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
2109e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
21122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger	/*	if (!ok)
2129e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return 0;*/
2139e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2148334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (!rate64) {
2159e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		fprintf(stderr, "\"rate\" is required.\n");
2169e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return -1;
2179e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
2189e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	/* if ceil params are missing, use the same as rate */
2198334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (!ceil64)
2208334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		ceil64 = rate64;
2218334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
2228334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	opt.rate.rate = (rate64 >= (1ULL << 32)) ? ~0U : rate64;
2238334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	opt.ceil.rate = (ceil64 >= (1ULL << 32)) ? ~0U : ceil64;
2249e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2259e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	/* compute minimal allowed burst from rate; mtu is added here to make
2269e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	   sute that buffer is larger than mtu and to have some safeguard space */
2278334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (!buffer)
2288334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		buffer = rate64 / get_hz() + mtu;
2298334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (!cbuffer)
2308334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		cbuffer = ceil64 / get_hz() + mtu;
2319e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
232bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	opt.ceil.overhead = overhead;
233bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	opt.rate.overhead = overhead;
234bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer
235bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	opt.ceil.mpu = mpu;
236bccd014b866daa21002f7ac682cee57a9fe003e3Jesper Dangaard Brouer	opt.rate.mpu = mpu;
237a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger
238292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	if (tc_calc_rtable(&opt.rate, rtab, cell_log, mtu, linklayer) < 0) {
2399e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		fprintf(stderr, "htb: failed to calculate rate table.\n");
2409e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return -1;
2419e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
2428334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	opt.buffer = tc_calc_xmittime(rate64, buffer);
243ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger
244292f29b42c3444375b5ae7086484c99da7129d94Jesper Dangaard Brouer	if (tc_calc_rtable(&opt.ceil, ctab, ccell_log, mtu, linklayer) < 0) {
2459e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
2469e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return -1;
2479e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
2488334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	opt.cbuffer = tc_calc_xmittime(ceil64, cbuffer);
2499e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2501b52a7622ea8eda9980ce2dbe984985ac092d92an);	tail = NLMSG_TAIL(n);
2519e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
2528334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
2538334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (rate64 >= (1ULL << 32))
2548334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		addattr_l(n, 1124, TCA_HTB_RATE64, &rate64, sizeof(rate64));
2558334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
2568334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	if (ceil64 >= (1ULL << 32))
2578334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		addattr_l(n, 1224, TCA_HTB_CEIL64, &ceil64, sizeof(ceil64));
2588334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
2599e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
2609e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
2619e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	addattr_l(n, 4024, TCA_HTB_CTAB, ctab, 1024);
2621b52a7622ea8eda9980ce2dbe984985ac092d92avoid *) NLMSG_TAIL(n) - (void *) tail;	tail->rta_len = (void *) NLMSG_TAIL(n) - (void *) tail;
2639e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	return 0;
2649e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
2659e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2669e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
2679e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
268b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet	struct rtattr *tb[TCA_HTB_MAX + 1];
2699e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct tc_htb_opt *hopt;
2709e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct tc_htb_glob *gopt;
2719e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	double buffer,cbuffer;
2723e92ff522ac2d634b21a3cd9c4d1de278532f0adJesper Dangaard Brouer	unsigned int linklayer;
2738334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet	__u64 rate64, ceil64;
2749e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	SPRINT_BUF(b1);
2759e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	SPRINT_BUF(b2);
276a166d246d84e7d0ba784e210515708006e16a366osdl.net!shemminger	SPRINT_BUF(b3);
2773e92ff522ac2d634b21a3cd9c4d1de278532f0adJesper Dangaard Brouer	SPRINT_BUF(b4);
2789e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2799e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	if (opt == NULL)
2809e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return 0;
2819e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
282b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet	parse_rtattr_nested(tb, TCA_HTB_MAX, opt);
2839e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2849e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	if (tb[TCA_HTB_PARMS]) {
28522fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		hopt = RTA_DATA(tb[TCA_HTB_PARMS]);
28622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		if (RTA_PAYLOAD(tb[TCA_HTB_PARMS])  < sizeof(*hopt)) return -1;
2879e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
2889e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		if (!hopt->level) {
2899e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			fprintf(f, "prio %d ", (int)hopt->prio);
2909e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			if (show_details)
2919e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger				fprintf(f, "quantum %d ", (int)hopt->quantum);
2929e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		}
2938334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
2948334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		rate64 = hopt->rate.rate;
2958334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		if (tb[TCA_HTB_RATE64] &&
2968334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		    RTA_PAYLOAD(tb[TCA_HTB_RATE64]) >= sizeof(rate64)) {
2978334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			rate64 = rta_getattr_u64(tb[TCA_HTB_RATE64]);
2988334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		}
2998334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
3008334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		ceil64 = hopt->ceil.rate;
3018334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		if (tb[TCA_HTB_CEIL64] &&
3028334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		    RTA_PAYLOAD(tb[TCA_HTB_CEIL64]) >= sizeof(ceil64))
3038334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet			ceil64 = rta_getattr_u64(tb[TCA_HTB_CEIL64]);
3048334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
3058334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		fprintf(f, "rate %s ", sprint_rate(rate64, b1));
30622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		if (hopt->rate.overhead)
30722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "overhead %u ", hopt->rate.overhead);
3088334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		buffer = tc_calc_xmitsize(rate64, hopt->buffer);
3098334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet
3108334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		fprintf(f, "ceil %s ", sprint_rate(ceil64, b1));
3118334bb325d5178483a3063c5f06858b46d993dc7Eric Dumazet		cbuffer = tc_calc_xmitsize(ceil64, hopt->cbuffer);
3123e92ff522ac2d634b21a3cd9c4d1de278532f0adJesper Dangaard Brouer		linklayer = (hopt->rate.linklayer & TC_LINKLAYER_MASK);
3133e92ff522ac2d634b21a3cd9c4d1de278532f0adJesper Dangaard Brouer		if (linklayer > TC_LINKLAYER_ETHERNET || show_details)
3143e92ff522ac2d634b21a3cd9c4d1de278532f0adJesper Dangaard Brouer			fprintf(f, "linklayer %s ", sprint_linklayer(linklayer, b4));
31522fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		if (show_details) {
31622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "burst %s/%u mpu %s overhead %s ",
31722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size(buffer, b1),
31822fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				1<<hopt->rate.cell_log,
31922fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size(hopt->rate.mpu&0xFF, b2),
32022fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size((hopt->rate.mpu>>8)&0xFF, b3));
32122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "cburst %s/%u mpu %s overhead %s ",
32222fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size(cbuffer, b1),
32322fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				1<<hopt->ceil.cell_log,
32422fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size(hopt->ceil.mpu&0xFF, b2),
32522fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				sprint_size((hopt->ceil.mpu>>8)&0xFF, b3));
32622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "level %d ", (int)hopt->level);
32722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		} else {
32822fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "burst %s ", sprint_size(buffer, b1));
32922fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "cburst %s ", sprint_size(cbuffer, b1));
33022fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		}
33122fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		if (show_raw)
33222fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			fprintf(f, "buffer [%08x] cbuffer [%08x] ",
33322fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger				hopt->buffer,hopt->cbuffer);
3349e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
3359e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	if (tb[TCA_HTB_INIT]) {
33622fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		gopt = RTA_DATA(tb[TCA_HTB_INIT]);
33722fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		if (RTA_PAYLOAD(tb[TCA_HTB_INIT])  < sizeof(*gopt)) return -1;
3389e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
33922fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger		fprintf(f, "r2q %d default %x direct_packets_stat %u",
34022fa92e3671ccf5165ee1582641054a58bb9718cStephen Hemminger			gopt->rate2quantum,gopt->defcls,gopt->direct_pkts);
3419e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		if (show_details)
3429e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger			fprintf(f," ver %d.%d",gopt->version >> 16,gopt->version & 0xffff);
3439e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	}
344b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet	if (tb[TCA_HTB_DIRECT_QLEN] &&
345b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet	    RTA_PAYLOAD(tb[TCA_HTB_DIRECT_QLEN]) >= sizeof(__u32)) {
346b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet		__u32 direct_qlen = rta_getattr_u32(tb[TCA_HTB_DIRECT_QLEN]);
347b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet
348b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet		fprintf(f, " direct_qlen %u", direct_qlen);
349b43f3318280a7b4b8c110d8fef7d5e6ebf2843fdEric Dumazet	}
3509e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	return 0;
3519e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
3529e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
3539e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemmingerstatic int htb_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
3549e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger{
3559e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	struct tc_htb_xstats *st;
3569e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	if (xstats == NULL)
3579e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return 0;
3589e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
3599e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	if (RTA_PAYLOAD(xstats) < sizeof(*st))
3609e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		return -1;
3619e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
3629e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	st = RTA_DATA(xstats);
363ae665a522bd46bea44c5ea84c89c8b1731954170Stephen Hemminger	fprintf(f, " lended: %u borrowed: %u giants: %u\n",
3649e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger		st->lends,st->borrows,st->giants);
3659e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	fprintf(f, " tokens: %d ctokens: %d\n", st->tokens,st->ctokens);
3669e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger	return 0;
3679e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger}
3689e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger
36995812b56a5a66e7e9a21744cfe8bc0bb9791ea98net[shemminger]!kaberstruct qdisc_util htb_qdisc_util = {
370f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.id 		= "htb",
371f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.parse_qopt	= htb_parse_opt,
372f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_qopt	= htb_print_opt,
373f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_xstats 	= htb_print_xstats,
374f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.parse_copt	= htb_parse_class_opt,
375f2f99e2eefdbd9cb6a750b19a7b3036db351b983osdl.net!shemminger	.print_copt	= htb_print_opt,
3769e9d615e32c1e0677d2c32619253eabb331ff307org[shemminger]!shemminger};
377