]> git.pld-linux.org Git - packages/iproute2.git/blob - iproute2-htb2_tc.patch
- new
[packages/iproute2.git] / iproute2-htb2_tc.patch
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
3 @@ -0,0 +1,342 @@
4 +/*
5 + * q_htb.c             HTB.
6 + *
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.
11 + *
12 + * Authors:    Martin Devera, devik@cdi.cz
13 + *
14 + */
15 +
16 +#include <stdio.h>
17 +#include <stdlib.h>
18 +#include <unistd.h>
19 +#include <syslog.h>
20 +#include <fcntl.h>
21 +#include <sys/socket.h>
22 +#include <netinet/in.h>
23 +#include <arpa/inet.h>
24 +#include <string.h>
25 +
26 +#include "utils.h"
27 +#include "tc_util.h"
28 +
29 +#ifndef TC_HTB_NUMPRIO
30 +/* HTB section */
31 +#define TC_HTB_NUMPRIO         4
32 +#define TC_HTB_MAXDEPTH                4
33 +
34 +struct tc_htb_opt
35 +{
36 +       struct tc_ratespec      rate;
37 +       struct tc_ratespec      ceil;
38 +       __u32   buffer;
39 +       __u32   cbuffer;
40 +       __u32   quantum;        /* out only */
41 +       __u32   level;          /* out only */
42 +       __u8    prio;
43 +       __u8    injectd;        /* inject class distance */
44 +       __u8    pad[2];
45 +};
46 +struct tc_htb_glob
47 +{
48 +       __u32 rate2quantum;     /* bps->quantum divisor */
49 +       __u32 defcls;           /* default class number */
50 +       __u32 use_dcache;       /* use dequeue cache ? */
51 +       __u32 debug;            /* debug flags */
52 +
53 +
54 +       /* stats */
55 +       __u32 deq_rate; /* dequeue rate */
56 +       __u32 utilz;    /* dequeue utilization */
57 +       __u32 trials;   /* deq_prio trials per dequeue */
58 +       __u32 dcache_hits;
59 +       __u32 direct_pkts; /* count of non shapped packets */
60 +};
61 +enum
62 +{
63 +       TCA_HTB_UNSPEC,
64 +       TCA_HTB_PARMS,
65 +       TCA_HTB_INIT,
66 +       TCA_HTB_CTAB,
67 +       TCA_HTB_RTAB,
68 +};
69 +struct tc_htb_xstats
70 +{
71 +       __u32 lends;
72 +       __u32 borrows;
73 +       __u32 giants;   /* too big packets (rate will not be accurate) */
74 +       __u32 injects;  /* how many times leaf used injected bw */      
75 +       __u32 tokens;
76 +       __u32 ctokens;
77 +};
78 +#endif
79 +
80 +static void explain(void)
81 +{
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"
97 +               );
98 +}
99 +
100 +static void explain1(char *arg)
101 +{
102 +    fprintf(stderr, "Illegal \"%s\"\n", arg);
103 +    explain();
104 +}
105 +
106 +
107 +#define usage() return(-1)
108 +
109 +static int htb_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
110 +{
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;
115 +       opt.debug = 0;
116 +
117 +       while (argc > 0) {
118 +               if (matches(*argv, "r2q") == 0) {
119 +                   NEXT_ARG();
120 +                   if (get_u32(&opt.rate2quantum, *argv, 10)) {
121 +                       explain1("r2q"); return -1;
122 +                   }
123 +               } else if (matches(*argv, "default") == 0) {
124 +                   NEXT_ARG();
125 +                   if (get_u32(&opt.defcls, *argv, 16)) {
126 +                       explain1("default"); return -1;
127 +                   }
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);
133 +                   }
134 +               } else if (matches(*argv, "dcache") == 0) {
135 +                   opt.use_dcache = 1;
136 +               } else {
137 +                       fprintf(stderr, "What is \"%s\"?\n", *argv);
138 +                       explain();
139 +                       return -1;
140 +               }
141 +               argc--; argv++;
142 +       }
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;
147 +       return 0;
148 +}
149 +
150 +static int htb_parse_class_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
151 +{
152 +       int ok=0;
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;
158 +
159 +       memset(&opt, 0, sizeof(opt)); mtu = 1600; /* eth packet len */
160 +       opt.injectd = 100; /* disable injecting */
161 +
162 +       while (argc > 0) {
163 +               if (matches(*argv, "prio") == 0) {
164 +                       NEXT_ARG();
165 +                       if (get_u8(&opt.prio, *argv, 10)) {
166 +                               explain1("prio"); return -1;
167 +                       }
168 +                       ok++;
169 +               } else if (matches(*argv, "mtu") == 0) {
170 +                       NEXT_ARG();
171 +                       if (get_u32(&mtu, *argv, 10)) {
172 +                               explain1("mtu"); return -1;
173 +                       }
174 +               } else if (matches(*argv, "inject") == 0) {
175 +                       NEXT_ARG();
176 +                       if (get_u8(&opt.injectd, *argv, 10)) {
177 +                               explain1("inject"); return -1;
178 +                       }
179 +               } else if (matches(*argv, "burst") == 0 ||
180 +                       strcmp(*argv, "buffer") == 0 ||
181 +                       strcmp(*argv, "maxburst") == 0) {
182 +                       NEXT_ARG();
183 +                       if (get_size_and_cell(&buffer, &cell_log, *argv) < 0) {
184 +                               explain1("buffer");
185 +                               return -1;
186 +                       }
187 +                       ok++;
188 +               } else if (matches(*argv, "cburst") == 0 ||
189 +                       strcmp(*argv, "cbuffer") == 0 ||
190 +                       strcmp(*argv, "cmaxburst") == 0) {
191 +                       NEXT_ARG();
192 +                       if (get_size_and_cell(&cbuffer, &ccell_log, *argv) < 0) {
193 +                               explain1("cbuffer");
194 +                               return -1;
195 +                       }
196 +                       ok++;
197 +               } else if (strcmp(*argv, "ceil") == 0) {
198 +                       NEXT_ARG();
199 +                       if (opt.ceil.rate) {
200 +                               fprintf(stderr, "Double \"ceil\" spec\n");
201 +                               return -1;
202 +                       }
203 +                       if (get_rate(&opt.ceil.rate, *argv)) {
204 +                               explain1("ceil");
205 +                               return -1;
206 +                       }
207 +                       ok++;
208 +               } else if (strcmp(*argv, "rate") == 0) {
209 +                       NEXT_ARG();
210 +                       if (opt.rate.rate) {
211 +                               fprintf(stderr, "Double \"rate\" spec\n");
212 +                               return -1;
213 +                       }
214 +                       if (get_rate(&opt.rate.rate, *argv)) {
215 +                               explain1("rate");
216 +                               return -1;
217 +                       }
218 +                       ok++;
219 +               } else if (strcmp(*argv, "help") == 0) {
220 +                       explain();
221 +                       return -1;
222 +               } else {
223 +                       fprintf(stderr, "What is \"%s\"?\n", *argv);
224 +                       explain();
225 +                       return -1;
226 +               }
227 +               argc--; argv++;
228 +       }
229 +
230 +/*     if (!ok)
231 +               return 0;*/
232 +
233 +       if (opt.rate.rate == 0) {
234 +               fprintf(stderr, "\"rate\" is required.\n");
235 +               return -1;
236 +       }
237 +       /* if ceil params are missing, use the same as rate */
238 +       if (!opt.ceil.rate) opt.ceil = opt.rate;
239 +
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;
244 +
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");
247 +               return -1;
248 +       }
249 +       opt.buffer = tc_calc_xmittime(opt.rate.rate, buffer);
250 +       opt.rate.cell_log = cell_log;
251 +       
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");
254 +               return -1;
255 +       }
256 +       opt.cbuffer = tc_calc_xmittime(opt.ceil.rate, cbuffer);
257 +       opt.ceil.cell_log = ccell_log;
258 +
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;
265 +       return 0;
266 +}
267 +
268 +static int htb_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
269 +{
270 +       struct rtattr *tb[TCA_HTB_RTAB+1];
271 +       struct tc_htb_opt *hopt;
272 +       struct tc_htb_glob *gopt;
273 +       double buffer,cbuffer;
274 +       SPRINT_BUF(b1);
275 +       SPRINT_BUF(b2);
276 +
277 +       if (opt == NULL)
278 +               return 0;
279 +
280 +       memset(tb, 0, sizeof(tb));
281 +       parse_rtattr(tb, TCA_HTB_RTAB, RTA_DATA(opt), RTA_PAYLOAD(opt));
282 +
283 +       if (tb[TCA_HTB_PARMS]) {
284 +
285 +           hopt = RTA_DATA(tb[TCA_HTB_PARMS]);
286 +           if (RTA_PAYLOAD(tb[TCA_HTB_PARMS])  < sizeof(*hopt)) return -1;
287 +
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);
300 +           } else {
301 +               fprintf(f, "burst %s ", sprint_size(buffer, b1));
302 +               fprintf(f, "cburst %s ", sprint_size(cbuffer, b1));
303 +           }
304 +           if (show_raw)
305 +               fprintf(f, "buffer [%08x] cbuffer [%08x] ", 
306 +                       hopt->buffer,hopt->cbuffer);
307 +       }
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;
311 +
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);
316 +       }
317 +       return 0;
318 +}
319 +
320 +static int htb_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
321 +{
322 +       struct tc_htb_xstats *st;
323 +       if (xstats == NULL)
324 +               return 0;
325 +
326 +       if (RTA_PAYLOAD(xstats) < sizeof(*st))
327 +               return -1;
328 +
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);
333 +       return 0;
334 +}
335 +
336 +struct qdisc_util htb_util = {
337 +       NULL,
338 +       "htb",
339 +       htb_parse_opt,
340 +       htb_print_opt,
341 +       htb_print_xstats,
342 +       htb_parse_class_opt,
343 +       htb_print_opt,
344 +};
345 +
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
349 @@ -25,6 +25,7 @@
350  endif
351  
352  #TCMODULES += q_csz.o
353 +TCMODULES += q_htb.o
354  #TCMODULES += q_hpfq.o
355  #TCMODULES += q_hfsc.o
356  
This page took 0.066345 seconds and 3 git commands to generate.