1 --- iproute2/tc/q_htb.c Sun Oct 21 22:07:29 2001
2 +++ iproute2new/tc/q_htb.c Wed Dec 19 16:51:41 2001
7 + * This program is free software; you can redistribute it and/or
8 + * modify it under the terms of the GNU General Public License
9 + * as published by the Free Software Foundation; either version
10 + * 2 of the License, or (at your option) any later version.
12 + * Authors: Martin Devera, devik@cdi.cz
21 +#include <sys/socket.h>
22 +#include <netinet/in.h>
23 +#include <arpa/inet.h>
29 +#ifndef TC_HTB_NUMPRIO
31 +#define TC_HTB_NUMPRIO 4
32 +#define TC_HTB_MAXDEPTH 4
36 + struct tc_ratespec rate;
37 + struct tc_ratespec ceil;
40 + __u32 quantum; /* out only */
41 + __u32 level; /* out only */
43 + __u8 injectd; /* inject class distance */
48 + __u32 rate2quantum; /* bps->quantum divisor */
49 + __u32 defcls; /* default class number */
50 + __u32 use_dcache; /* use dequeue cache ? */
51 + __u32 debug; /* debug flags */
55 + __u32 deq_rate; /* dequeue rate */
56 + __u32 utilz; /* dequeue utilization */
57 + __u32 trials; /* deq_prio trials per dequeue */
59 + __u32 direct_pkts; /* count of non shapped packets */
73 + __u32 giants; /* too big packets (rate will not be accurate) */
74 + __u32 injects; /* how many times leaf used injected bw */
80 +static void explain(void)
82 + fprintf(stderr, "Usage: ... qdisc add ... htb [default N] [r2q N]\n"
83 + " default number of class to which unclassified packets are sent {1}\n"
84 + " dcache whether to use dequeue cache; it limits fairness but makes\n"
85 + " possible to use HTB on very fast devices\n"
86 + " r2q DRR quantums are computed as rate in Bps/r2q {10}\n"
87 + " debug string of 16 numbers each 0-3 {0}\n\n"
88 + "... class add ... htb rate R1 burst B1 [prio P] [slot S] [pslot PS]\n"
89 + " [ceil R2] [cburst B2] [gated]\n"
90 + " rate rate allocated to this class (class can still borrow)\n"
91 + " burst max bytes burst which can be accumulated during idle period {computed}\n"
92 + " ceil definite upper class rate (no borrows) {rate}\n"
93 + " cburst burst but for ceil {computed}\n"
94 + " mtu max packet size {1600}\n"
95 + " prio priority of leaf; lower are served first {0}\n"
96 + " inject distance to parent we inject bandwidth to {100}\n"
100 +static void explain1(char *arg)
102 + fprintf(stderr, "Illegal \"%s\"\n", arg);
107 +#define usage() return(-1)
109 +static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
111 + struct tc_htb_glob opt;
112 + struct rtattr *tail;
113 + unsigned i; char *p;
114 + opt.rate2quantum = 10; opt.defcls = 1; opt.use_dcache = 0;
118 + if (matches(*argv, "r2q") == 0) {
120 + if (get_u32(&opt.rate2quantum, *argv, 10)) {
121 + explain1("r2q"); return -1;
123 + } else if (matches(*argv, "default") == 0) {
125 + if (get_u32(&opt.defcls, *argv, 16)) {
126 + explain1("default"); return -1;
128 + } else if (matches(*argv, "debug") == 0) {
129 + NEXT_ARG(); p = *argv;
130 + for (i=0; i<16; i++,p++) {
131 + if (*p<'0' || *p>'3') break;
132 + opt.debug |= (*p-'0')<<(2*i);
134 + } else if (matches(*argv, "dcache") == 0) {
135 + opt.use_dcache = 1;
137 + fprintf(stderr, "What is \"%s\"?\n", *argv);
143 + tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
144 + addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
145 + addattr_l(n, 2024, TCA_HTB_INIT, &opt, NLMSG_ALIGN(sizeof(opt)));
146 + tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
150 +static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
153 + struct tc_htb_opt opt;
154 + __u32 rtab[256],ctab[256];
155 + unsigned buffer=0,cbuffer=0;
156 + int cell_log=-1,ccell_log = -1,mtu;
157 + struct rtattr *tail;
159 + memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
160 + opt.injectd = 100; /* disable injecting */
163 + if (matches(*argv, "prio") == 0) {
165 + if (get_u8(&opt.prio, *argv, 10)) {
166 + explain1("prio"); return -1;
169 + } else if (matches(*argv, "mtu") == 0) {
171 + if (get_u32(&mtu, *argv, 10)) {
172 + explain1("mtu"); return -1;
174 + } else if (matches(*argv, "inject") == 0) {
176 + if (get_u8(&opt.injectd, *argv, 10)) {
177 + explain1("inject"); return -1;
179 + } else if (matches(*argv, "burst") == 0 ||
180 + strcmp(*argv, "buffer") == 0 ||
181 + strcmp(*argv, "maxburst") == 0) {
183 + if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
184 + explain1("buffer");
188 + } else if (matches(*argv, "cburst") == 0 ||
189 + strcmp(*argv, "cbuffer") == 0 ||
190 + strcmp(*argv, "cmaxburst") == 0) {
192 + if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
193 + explain1("cbuffer");
197 + } else if (strcmp(*argv, "ceil") == 0) {
199 + if (opt.ceil.rate) {
200 + fprintf(stderr, "Double \"ceil\" spec\n");
203 + if (get_rate(&opt.ceil.rate, *argv)) {
208 + } else if (strcmp(*argv, "rate") == 0) {
210 + if (opt.rate.rate) {
211 + fprintf(stderr, "Double \"rate\" spec\n");
214 + if (get_rate(&opt.rate.rate, *argv)) {
219 + } else if (strcmp(*argv, "help") == 0) {
223 + fprintf(stderr, "What is \"%s\"?\n", *argv);
233 + if (opt.rate.rate == 0) {
234 + fprintf(stderr, "\"rate\" is required.\n");
237 + /* if ceil params are missing, use the same as rate */
238 + if (!opt.ceil.rate) opt.ceil = opt.rate;
240 + /* compute minimal allowed burst from rate; mtu is added here to make
241 + sute that buffer is larger than mtu and to have some safeguard space */
242 + if (!buffer) buffer = opt.rate.rate / HZ + mtu;
243 + if (!cbuffer) cbuffer = opt.ceil.rate / HZ + mtu;
245 + if ((cell_log = tc_calc_rtable(opt.rate.rate, rtab, cell_log, mtu, 0)) < 0) {
246 + fprintf(stderr, "htb: failed to calculate rate table.\n");
249 + opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
250 + opt.rate.cell_log = cell_log;
252 + if ((ccell_log = tc_calc_rtable(opt.ceil.rate, ctab, cell_log, mtu, 0)) < 0) {
253 + fprintf(stderr, "htb: failed to calculate ceil rate table.\n");
256 + opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
257 + opt.ceil.cell_log = ccell_log;
259 + tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
260 + addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
261 + addattr_l(n, 2024, TCA_HTB_PARMS, &opt, sizeof(opt));
262 + addattr_l(n, 3024, TCA_HTB_RTAB, rtab, 1024);
263 + addattr_l(n, 4024, TCA_HTB_CTAB, ctab, 1024);
264 + tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
268 +static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
270 + struct rtattr *tb[TCA_HTB_RTAB+1];
271 + struct tc_htb_opt *hopt;
272 + struct tc_htb_glob *gopt;
273 + double buffer,cbuffer;
280 + memset(tb, 0, sizeof(tb));
281 + parse_rtattr(tb, TCA_HTB_RTAB, RTA_DATA(opt), RTA_PAYLOAD(opt));
283 + if (tb[TCA_HTB_PARMS]) {
285 + hopt = RTA_DATA(tb[TCA_HTB_PARMS]);
286 + if (RTA_PAYLOAD(tb[TCA_HTB_PARMS]) < sizeof(*hopt)) return -1;
288 + fprintf(f, "prio %d ", (int)hopt->prio);
289 + fprintf(f, "rate %s ", sprint_rate(hopt->rate.rate, b1));
290 + buffer = ((double)hopt->rate.rate*tc_core_tick2usec(hopt->buffer))/1000000;
291 + fprintf(f, "ceil %s ", sprint_rate(hopt->ceil.rate, b1));
292 + cbuffer = ((double)hopt->ceil.rate*tc_core_tick2usec(hopt->cbuffer))/1000000;
293 + if (show_details) {
294 + fprintf(f, "burst %s/%u mpu %s ", sprint_size(buffer, b1),
295 + 1<<hopt->rate.cell_log, sprint_size(hopt->rate.mpu, b2));
296 + fprintf(f, "cburst %s/%u mpu %s ", sprint_size(cbuffer, b1),
297 + 1<<hopt->ceil.cell_log, sprint_size(hopt->ceil.mpu, b2));
298 + fprintf(f, "quantum %d ", (int)hopt->quantum);
299 + fprintf(f, "level %d ", (int)hopt->level);
301 + fprintf(f, "burst %s ", sprint_size(buffer, b1));
302 + fprintf(f, "cburst %s ", sprint_size(cbuffer, b1));
305 + fprintf(f, "buffer [%08x] cbuffer [%08x] ",
306 + hopt->buffer,hopt->cbuffer);
308 + if (tb[TCA_HTB_INIT]) {
309 + gopt = RTA_DATA(tb[TCA_HTB_INIT]);
310 + if (RTA_PAYLOAD(tb[TCA_HTB_INIT]) < sizeof(*gopt)) return -1;
312 + fprintf(f, "r2q %d default %x dcache %d\n"
313 + " deq_util 1/%d deq_rate %d trials_per_deq %d\n dcache_hits %u direct_packets %u",
314 + gopt->rate2quantum,gopt->defcls,gopt->use_dcache,1000000/(1+gopt->utilz),
315 + gopt->deq_rate, gopt->trials/(1+gopt->deq_rate),gopt->dcache_hits,gopt->direct_pkts);
320 +static int htb_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
322 + struct tc_htb_xstats *st;
323 + if (xstats == NULL)
326 + if (RTA_PAYLOAD(xstats) < sizeof(*st))
329 + st = RTA_DATA(xstats);
330 + fprintf(f, " lended: %u borrowed: %u giants: %u injects: %u\n",
331 + st->lends,st->borrows,st->giants,st->injects);
332 + fprintf(f, " tokens: %d ctokens: %d\n", st->tokens,st->ctokens);
336 +struct qdisc_util htb_util = {
342 + htb_parse_class_opt,
346 diff -uNr iproute2.pld/tc/Makefile iproute2/tc/Makefile
347 --- iproute2.pld/tc/Makefile Sun Apr 16 19:42:53 2000
348 +++ iproute2/tc/Makefile Thu Feb 28 21:09:16 2002
352 #TCMODULES += q_csz.o
353 +TCMODULES += q_htb.o
354 #TCMODULES += q_hpfq.o
355 #TCMODULES += q_hfsc.o