1 diff -uNr iproute2.orig/tc/Makefile iproute2/tc/Makefile
2 --- iproute2.orig/tc/Makefile 2004-04-06 04:13:37.944868904 +0200
3 +++ iproute2/tc/Makefile 2004-04-06 04:22:48.397187432 +0200
8 -#TCMODULES += q_hfsc.o
13 diff -uNr iproute2.orig/tc/q_hfsc.c iproute2/tc/q_hfsc.c
14 --- iproute2.orig/tc/q_hfsc.c 2000-04-16 19:42:54.000000000 +0200
15 +++ iproute2/tc/q_hfsc.c 2004-04-06 04:22:48.416184544 +0200
21 * This program is free software; you can redistribute it and/or
22 * modify it under the terms of the GNU General Public License
23 * as published by the Free Software Foundation; either version
24 * 2 of the License, or (at your option) any later version.
26 - * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
27 + * Authors: Patrick McHardy, <kaber@trash.ner>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
40 -static void explain()
41 +static int hfsc_get_sc(int *, char ***, struct tc_service_curve *);
48 + "Usage: ... hfsc [ default CLASSID ]\n"
50 + " default: default class for unclassified packets\n"
57 - fprintf(stderr, "Usage: ... hfsc \n");
59 + "Usage: ... hfsc [ rt SC ] [ ls SC ] [ ul SC ]\n"
61 + "SC := [ [ m1 BPS ] [ d SEC ] m2 BPS\n"
63 + " m1 : slope of first segment\n"
64 + " d : x-coordinate of intersection\n"
65 + " m2 : slope of second segment\n"
67 + "Alternative format:\n"
69 + "SC := [ [ umax BYTE ] dmax SEC ] rate BPS\n"
71 + " umax : maximum unit of work\n"
72 + " dmax : maximum delay\n"
78 -static void explain1(char *arg)
82 - fprintf(stderr, "Illegal \"%s\"\n", arg);
83 + fprintf(stderr, "HFSC: Illegal \"%s\"\n", arg);
87 +hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
89 + struct tc_hfsc_qopt qopt;
91 + memset(&qopt, 0, sizeof(qopt));
94 + if (matches(*argv, "default") == 0) {
96 + if (qopt.defcls != 0) {
97 + fprintf(stderr, "HFSC: Double \"default\"\n");
100 + if (get_u16(&qopt.defcls, *argv, 16) < 0) {
101 + explain1("default");
104 + } else if (matches(*argv, "help") == 0) {
108 + fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
115 -#define usage() return(-1)
116 + addattr_l(n, 1024, TCA_OPTIONS, &qopt, sizeof(qopt));
120 -static int hfsc_parse_opt(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n)
122 +hfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
125 + struct tc_hfsc_qopt *qopt;
129 + if (RTA_PAYLOAD(opt) < sizeof(*qopt))
131 + qopt = RTA_DATA(opt);
133 + if (qopt->defcls != 0)
134 + fprintf(f, "default %x ", qopt->defcls);
139 -static int hfsc_print_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
141 +hfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
144 + struct tc_hfsc_stats *st;
146 + if (xstats == NULL)
148 + if (RTA_PAYLOAD(xstats) < sizeof(*st))
150 + st = RTA_DATA(xstats);
152 + fprintf(f, " period %u ", st->period);
154 + fprintf(f, "work %llu bytes ", st->work);
155 + if (st->rtwork != 0)
156 + fprintf(f, "rtwork %llu bytes ", st->rtwork);
157 + fprintf(f, "level %u ", st->level);
163 -static int hfsc_print_xstats(struct qdisc_util *qu, FILE *f, struct rtattr *xstats)
165 +hfsc_parse_class_opt(struct qdisc_util *qu, int argc, char **argv,
166 + struct nlmsghdr *n)
169 + struct tc_service_curve rsc, fsc, usc;
170 + int rsc_ok, fsc_ok, usc_ok;
171 + struct rtattr *tail;
173 + memset(&rsc, 0, sizeof(rsc));
174 + memset(&fsc, 0, sizeof(fsc));
175 + memset(&usc, 0, sizeof(usc));
176 + rsc_ok = fsc_ok = usc_ok = 0;
179 + if (matches(*argv, "rt") == 0) {
181 + if (hfsc_get_sc(&argc, &argv, &rsc) < 0) {
186 + } else if (matches(*argv, "ls") == 0) {
188 + if (hfsc_get_sc(&argc, &argv, &fsc) < 0) {
193 + } else if (matches(*argv, "ul") == 0) {
195 + if (hfsc_get_sc(&argc, &argv, &usc) < 0) {
200 + } else if (matches(*argv, "help") == 0) {
204 + fprintf(stderr, "HFSC: What is \"%s\" ?\n", *argv);
211 + if (!(rsc_ok || fsc_ok || usc_ok)) {
212 + fprintf(stderr, "HFSC: no parameters given\n");
216 + if (usc_ok && !fsc_ok) {
217 + fprintf(stderr, "HFSC: Upper-limit Service Curve without "
218 + "Link-Share Service Curve\n");
223 + tail = (struct rtattr*)(((void*)n) + NLMSG_ALIGN(n->nlmsg_len));
225 + addattr_l(n, 1024, TCA_OPTIONS, NULL, 0);
227 + addattr_l(n, 1024, TCA_HFSC_RSC, &rsc, sizeof(rsc));
229 + addattr_l(n, 1024, TCA_HFSC_FSC, &fsc, sizeof(fsc));
231 + addattr_l(n, 1024, TCA_HFSC_USC, &usc, sizeof(usc));
233 + tail->rta_len = (((void*)n) + NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
238 +hfsc_print_sc(FILE *f, char *name, struct tc_service_curve *sc)
242 + fprintf(f, "%s ", name);
243 + fprintf(f, "m1 %s ", sprint_rate(sc->m1, b1));
244 + fprintf(f, "d %s ", sprint_usecs(sc->d, b1));
245 + fprintf(f, "m2 %s ", sprint_rate(sc->m2, b1));
249 +hfsc_print_class_opt(struct qdisc_util *qu, FILE *f, struct rtattr *opt)
251 + struct rtattr *tb[TCA_HFSC_MAX+1];
252 + struct tc_service_curve *rsc = NULL, *fsc = NULL, *usc = NULL;
257 + memset(tb, 0, sizeof(tb));
258 + parse_rtattr(tb, TCA_HFSC_MAX, RTA_DATA(opt), RTA_PAYLOAD(opt));
260 + if (tb[TCA_HFSC_RSC]) {
261 + if (RTA_PAYLOAD(tb[TCA_HFSC_RSC]) < sizeof(*rsc))
262 + fprintf(stderr, "HFSC: truncated realtime option\n");
264 + rsc = RTA_DATA(tb[TCA_HFSC_RSC]);
266 + if (tb[TCA_HFSC_FSC]) {
267 + if (RTA_PAYLOAD(tb[TCA_HFSC_FSC]) < sizeof(*fsc))
268 + fprintf(stderr, "HFSC: truncated linkshare option\n");
270 + fsc = RTA_DATA(tb[TCA_HFSC_FSC]);
272 + if (tb[TCA_HFSC_USC]) {
273 + if (RTA_PAYLOAD(tb[TCA_HFSC_USC]) < sizeof(*usc))
274 + fprintf(stderr, "HFSC: truncated upperlimit option\n");
276 + usc = RTA_DATA(tb[TCA_HFSC_USC]);
280 + hfsc_print_sc(f, "rt", rsc);
282 + hfsc_print_sc(f, "ls", fsc);
284 + hfsc_print_sc(f, "ul", usc);
289 struct qdisc_util hfsc_util = {
294 + hfsc_parse_class_opt,
295 + hfsc_print_class_opt,
299 +hfsc_get_sc1(int *argcp, char ***argvp, struct tc_service_curve *sc)
301 + char **argv = *argvp;
303 + unsigned int m1 = 0, d = 0, m2 = 0;
305 + if (matches(*argv, "m1") == 0) {
307 + if (get_rate(&m1, *argv) < 0) {
314 + if (matches(*argv, "d") == 0) {
316 + if (get_usecs(&d, *argv) < 0) {
323 + if (matches(*argv, "m2") == 0) {
325 + if (get_rate(&m2, *argv) < 0) {
342 +hfsc_get_sc2(int *argcp, char ***argvp, struct tc_service_curve *sc)
344 + char **argv = *argvp;
346 + unsigned int umax = 0, dmax = 0, rate = 0;
348 + if (matches(*argv, "umax") == 0) {
350 + if (get_size(&umax, *argv) < 0) {
357 + if (matches(*argv, "dmax") == 0) {
359 + if (get_usecs(&dmax, *argv) < 0) {
366 + if (matches(*argv, "rate") == 0) {
368 + if (get_rate(&rate, *argv) < 0) {
375 + if (umax != 0 && dmax == 0) {
376 + fprintf(stderr, "HFSC: umax given but dmax is zero.\n");
380 + if (dmax != 0 && ceil(umax * 1000000.0 / dmax) > rate) {
382 + * concave curve, slope of first segment is umax/dmax,
383 + * intersection is at dmax
385 + sc->m1 = ceil(umax * 1000000.0 / dmax); /* in bps */
390 + * convex curve, slope of first segment is 0, intersection
391 + * is at dmax - umax / rate
394 + sc->d = ceil(dmax - umax * 1000000.0 / rate); /* in usec */
404 +hfsc_get_sc(int *argcp, char ***argvp, struct tc_service_curve *sc)
406 + if (hfsc_get_sc1(argcp, argvp, sc) < 0 &&
407 + hfsc_get_sc2(argcp, argvp, sc) < 0)
410 + if (sc->m1 == 0 && sc->m2 == 0) {
411 + fprintf(stderr, "HFSC: Service Curve has two zero slopes\n");