]> rtime.felk.cvut.cz Git - lisovros/iproute2_canprio.git/commitdiff
new stuff from jamal.
authorosdl.net!shemminger <osdl.net!shemminger>
Fri, 13 Aug 2004 23:54:55 +0000 (23:54 +0000)
committerosdl.net!shemminger <osdl.net!shemminger>
Fri, 13 Aug 2004 23:54:55 +0000 (23:54 +0000)
(Logical change 1.66)

tc/f_u32.c
tc/m_police.c
tc/tc.c
tc/tc_class.c
tc/tc_common.h
tc/tc_filter.c
tc/tc_qdisc.c
tc/tc_util.c
tc/tc_util.h

index 3e76e9cfb76f38d6322d002ff6ab1cea80ea711a..923a68b3f0fe5392bf59c555c065d52627f780be 100644 (file)
@@ -19,6 +19,7 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <string.h>
+#include <linux/if.h>
 
 #include "utils.h"
 #include "tc_util.h"
@@ -122,6 +123,8 @@ static int pack_key(struct tc_u32_sel *sel, __u32 key, __u32 mask, int off, int
                                return -1;
                        sel->keys[i].val |= key;
                        sel->keys[i].mask |= mask;
+                       sel->keys[i].off = 0;
+                       sel->keys[i].offmask = 0;
                        return 0;
                }
        }
@@ -367,7 +370,8 @@ static int parse_ip6_addr(int *argc_p, char ***argv_p, struct tc_u32_sel *sel, i
 
        plen = addr.bitlen;
        for (i=0; i<plen; i+=32) {
-               if (((i+31)&~0x1F)<=plen) {
+//             if (((i+31)&~0x1F)<=plen) {
+               if (((i+31))<=plen) {
                        if ((res = pack_key(sel, addr.data[i/32], 0xFFFFFFFF, off+4*(i/32), offmask)) < 0)
                                return -1;
                } else if (i<plen) {
@@ -706,10 +710,19 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
        while (argc > 0) {
                if (matches(*argv, "mask") == 0) {
                        __u32 mask;
+                       int i = 0;
                        NEXT_ARG();
                        if (get_u32(&mask, *argv, 16))
                                return -1;
                        sel->hmask = htonl(mask);
+                       mask = sel->hmask;
+                       while (!(mask & 1)) {
+                               i++;
+                               mask>>=1;
+                       }
+#ifdef fix_u32_bug
+                       sel->fshift = i;
+#endif
                } else if (matches(*argv, "at") == 0) {
                        int num;
                        NEXT_ARG();
@@ -753,7 +766,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                return 0;
 
        tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
-       addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);
+       addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);
 
        while (argc > 0) {
                if (matches(*argv, "match") == 0) {
@@ -786,7 +799,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                                fprintf(stderr, "Illegal \"classid\"\n");
                                return -1;
                        }
-                       addattr_l(n, 4096, TCA_U32_CLASSID, &handle, 4);
+                       addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &handle, 4);
                        sel.sel.flags |= TC_U32_TERMINAL;
                } else if (matches(*argv, "divisor") == 0) {
                        unsigned divisor;
@@ -796,7 +809,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                                fprintf(stderr, "Illegal \"divisor\"\n");
                                return -1;
                        }
-                       addattr_l(n, 4096, TCA_U32_DIVISOR, &divisor, 4);
+                       addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
                } else if (matches(*argv, "order") == 0) {
                        NEXT_ARG();
                        if (get_u32(&order, *argv, 0)) {
@@ -814,7 +827,7 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                                fprintf(stderr, "\"link\" must be a hash table.\n");
                                return -1;
                        }
-                       addattr_l(n, 4096, TCA_U32_LINK, &handle, 4);
+                       addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4);
                } else if (strcmp(*argv, "ht") == 0) {
                        unsigned handle;
                        NEXT_ARG();
@@ -851,6 +864,24 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
                        htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000);
                        sample_ok = 1;
                        continue;
+               } else if (strcmp(*argv, "indev") == 0) {
+                       char ind[IFNAMSIZ + 1];
+                       memset(ind, 0, sizeof (ind));
+                       argc--;
+                       argv++;
+                       if (argc < 1) {
+                               fprintf(stderr, "Illegal indev\n");
+                               return -1;
+                       }
+                       strncpy(ind, *argv, sizeof (ind) - 1);
+                       addattr_l(n, MAX_MSG, TCA_U32_INDEV, ind, strlen(ind) + 1);
+               } else if (matches(*argv, "action") == 0) {
+                       NEXT_ARG();
+                       if (parse_action(&argc, &argv, TCA_U32_ACT, n)) {
+                               fprintf(stderr, "Illegal \"action\"\n");
+                               return -1;
+                       }
+                       continue;
                } else if (matches(*argv, "police") == 0) {
                        NEXT_ARG();
                        if (parse_police(&argc, &argv, TCA_U32_POLICE, n)) {
@@ -878,9 +909,9 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
        }
 
        if (htid)
-               addattr_l(n, 4096, TCA_U32_HASH, &htid, 4);
+               addattr_l(n, MAX_MSG, TCA_U32_HASH, &htid, 4);
        if (sel_ok)
-               addattr_l(n, 4096, TCA_U32_SEL, &sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_u32_key));
+               addattr_l(n, MAX_MSG, TCA_U32_SEL, &sel, sizeof(sel.sel)+sel.sel.nkeys*sizeof(struct tc_u32_key));
        tail->rta_len = (((void*)n)+n->nlmsg_len) - (void*)tail;
        return 0;
 }
@@ -932,22 +963,19 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __
                SPRINT_BUF(b1);
                fprintf(f, "link %s ", sprint_u32_handle(*(__u32*)RTA_DATA(tb[TCA_U32_LINK]), b1));
        }
-       if (tb[TCA_U32_POLICE]) {
-               fprintf(f, "\n");
-               tc_print_police(f, tb[TCA_U32_POLICE]);
-       }
+
 
        if (sel) {
                int i;
                struct tc_u32_key *key = sel->keys;
-
                if (sel->nkeys) {
-                       for (i=0; i<sel->nkeys; i++, key++)
+                       for (i=0; i<sel->nkeys; i++, key++) {
                                fprintf(f, "\n  match %08x/%08x at %s%d",
                                        (unsigned int)ntohl(key->val),
                                        (unsigned int)ntohl(key->mask),
                                        key->offmask ? "nexthdr+" : "",
                                        key->off);
+                       }
                }
 
                if (sel->flags&(TC_U32_VAROFFSET|TC_U32_OFFSET)) {
@@ -966,6 +994,23 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __
                }
        }
 
+       if (show_stats && tb[TCA_U32_PCNT]){
+               struct tc_u32_pcnt *p = RTA_DATA(tb[TCA_U32_PCNT]);
+               fprintf(f, " (rule hit %llu success %llu)",
+                       p->rcnt, p->rhit);
+       }
+       if (tb[TCA_U32_POLICE]) {
+               fprintf(f, "\n");
+               tc_print_police(f, tb[TCA_U32_POLICE]);
+       }
+       if (tb[TCA_U32_INDEV]) {
+               struct rtattr *idev = tb[TCA_U32_INDEV];
+               fprintf(f, "\n  input dev %s\n", (char *) RTA_DATA(idev));
+       }
+       if (tb[TCA_U32_ACT]) {
+               tc_print_action(f, tb[TCA_U32_ACT]);
+       }
+
        return 0;
 }
 
index 0e76efc50502ba60efd5df850fd8833df1b8d73e..79025a5dc79ef62dd3a327ad8f8a3db0f5a1f3ef 100644 (file)
@@ -9,6 +9,8 @@
  * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
  * FIXES:       19990619 - J Hadi Salim (hadi@cyberus.ca) 
  *             simple addattr packaging fix.            
+ *             2002: J Hadi Salim - Add tc action extensions syntax
+ *
  */
 
 #include <stdio.h>
 #include "utils.h"
 #include "tc_util.h"
 
+struct action_util police_util = {
+       .id = "police",
+       .parse_aopt = act_parse_police,
+       .print_aopt = print_police,
+       .print_xstats = police_print_xstats,
+};
+
 static void explain(void)
 {
        fprintf(stderr, "Usage: ... police rate BPS burst BYTES[/BYTES] [ mtu BYTES[/BYTES] ]\n");
        fprintf(stderr, "                [ peakrate BPS ] [ avrate BPS ]\n");
-       fprintf(stderr, "                [ ACTION ]\n");
-       fprintf(stderr, "Where: ACTION := reclassify | drop | continue \n");
+       fprintf(stderr, "                [ ACTIONTERM ]\n");
+       fprintf(stderr, "Old Syntax ACTIOTERMN := action <EXCEEDACT>[/NOTEXCEEDACT] \n"); 
+       fprintf(stderr, "New Syntax ACTIONTERM := conform-exceed <EXCEEDACT>[/NOTEXCEEDACT] \n"); 
+       fprintf(stderr, "Where: *EXCEEDACT := pipe | ok | reclassify | drop | continue \n");
+       fprintf(stderr, "Where:  pipe is only valid for new syntax \n");
 }
 
 static void explain1(char *arg)
@@ -54,6 +66,8 @@ char *police_action_n2a(int action, char *buf, int len)
                break;
        case TC_POLICE_RECLASSIFY:
                return "reclassify";
+       case TC_POLICE_PIPE:
+               return "pipe";
        default:
                snprintf(buf, len, "%d", action);
                return buf;
@@ -76,6 +90,8 @@ int police_action_a2n(char *arg, int *result)
                res = TC_POLICE_OK;
        else if (matches(arg, "reclassify") == 0)
                res = TC_POLICE_RECLASSIFY;
+       else if (matches(arg, "pipe") == 0)
+               res = TC_POLICE_PIPE;
        else {
                char dummy;
                if (sscanf(arg, "%d%c", &res, &dummy) != 1)
@@ -107,7 +123,8 @@ int get_police_result(int *action, int *result, char *arg)
        return 0;
 }
 
-int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
+
+int act_parse_police(struct action_util *a,int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
 {
        int argc = *argc_p;
        char **argv = *argv_p;
@@ -125,13 +142,17 @@ int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
        memset(&p, 0, sizeof(p));
        p.action = TC_POLICE_RECLASSIFY;
 
+       if (a) /* new way of doing things */
+               NEXT_ARG();
+
        if (argc <= 0)
                return -1;
 
        while (argc > 0) {
+
                if (matches(*argv, "index") == 0) {
                        NEXT_ARG();
-                       if (get_u32(&p.index, *argv, 16)) {
+                       if (get_u32(&p.index, *argv, 10)) {
                                fprintf(stderr, "Illegal \"index\"\n");
                                return -1;
                        }
@@ -207,7 +228,9 @@ int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
                        p.action = TC_POLICE_UNSPEC;
                } else if (matches(*argv, "pass") == 0) {
                        p.action = TC_POLICE_OK;
-               } else if (strcmp(*argv, "action") == 0) {
+               } else if (matches(*argv, "pipe") == 0) {
+                       p.action = TC_POLICE_PIPE;
+               } else if (strcmp(*argv, "conform-exceed") == 0) {
                        NEXT_ARG();
                        if (get_police_result(&p.action, &presult, *argv)) {
                                fprintf(stderr, "Illegal \"action\"\n");
@@ -261,18 +284,16 @@ int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
        }
 
        tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
-       addattr_l(n, 1024, tca_id, NULL, 0);
-       addattr_l(n, 2024, TCA_POLICE_TBF, &p, sizeof(p));
+       addattr_l(n, MAX_MSG, tca_id, NULL, 0);
+       addattr_l(n, MAX_MSG, TCA_POLICE_TBF, &p, sizeof(p));
        if (p.rate.rate)
-               addattr_l(n, 3024, TCA_POLICE_RATE, rtab, 1024);
+               addattr_l(n, MAX_MSG, TCA_POLICE_RATE, rtab, 1024);
        if (p.peakrate.rate)
-                addattr_l(n, 4096, TCA_POLICE_PEAKRATE, ptab, 1024);
+                addattr_l(n, MAX_MSG, TCA_POLICE_PEAKRATE, ptab, 1024);
        if (avrate)
-               addattr32(n, 4096, TCA_POLICE_AVRATE, avrate);
+               addattr32(n, MAX_MSG, TCA_POLICE_AVRATE, avrate);
        if (presult)
-               addattr32(n, 4096, TCA_POLICE_RESULT, presult);
-#if 0
-#endif
+               addattr32(n, MAX_MSG, TCA_POLICE_RESULT, presult);
 
        tail->rta_len = (((void*)n)+NLMSG_ALIGN(n->nlmsg_len)) - (void*)tail;
        res = 0;
@@ -282,8 +303,13 @@ int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
        return res;
 }
 
+int parse_police(int *argc_p, char ***argv_p, int tca_id, struct nlmsghdr *n)
+{
+       return act_parse_police(NULL,argc_p,argv_p,tca_id,n);
+}
 
-int tc_print_police(FILE *f, struct rtattr *arg)
+int 
+print_police(struct action_util *a,FILE *f, struct rtattr *arg)
 {
        SPRINT_BUF(b1);
        struct tc_police *p;
@@ -300,18 +326,15 @@ int tc_print_police(FILE *f, struct rtattr *arg)
                fprintf(f, "[NULL police tbf]");
                return 0;
        }
+#ifndef STOOPID_8BYTE
        if (RTA_PAYLOAD(tb[TCA_POLICE_TBF])  < sizeof(*p)) {
                fprintf(f, "[truncated police tbf]");
                return -1;
        }
+#endif
        p = RTA_DATA(tb[TCA_POLICE_TBF]);
 
-       fprintf(f, "police %x ", p->index);
-       fprintf(f, "action %s", police_action_n2a(p->action, b1, sizeof(b1)));
-       if (tb[TCA_POLICE_RESULT]) {
-               fprintf(f, "/%s ", police_action_n2a(*(int*)RTA_DATA(tb[TCA_POLICE_RESULT]), b1, sizeof(b1)));
-       } else
-               fprintf(f, " ");
+       fprintf(f, " police 0x%x ", p->index);
        fprintf(f, "rate %s ", sprint_rate(p->rate.rate, b1));
        buffer = ((double)p->rate.rate*tc_core_tick2usec(p->burst))/1000000;
        fprintf(f, "burst %s ", sprint_size(buffer, b1));
@@ -322,7 +345,24 @@ int tc_print_police(FILE *f, struct rtattr *arg)
                fprintf(f, "peakrate %s ", sprint_rate(p->peakrate.rate, b1));
        if (tb[TCA_POLICE_AVRATE])
                fprintf(f, "avrate %s ", sprint_rate(*(__u32*)RTA_DATA(tb[TCA_POLICE_AVRATE]), b1));
+       fprintf(f, "action %s", police_action_n2a(p->action, b1, sizeof(b1)));
+       if (tb[TCA_POLICE_RESULT]) {
+               fprintf(f, "/%s ", police_action_n2a(*(int*)RTA_DATA(tb[TCA_POLICE_RESULT]), b1, sizeof(b1)));
+       } else
+               fprintf(f, " ");
+       fprintf(f, "\nref %d bind %d\n",p->refcnt, p->bindcnt);
 
        return 0;
 }
 
+int 
+tc_print_police(FILE *f, struct rtattr *arg) {
+       return print_police(&police_util,f,arg);
+}
+
+int
+police_print_xstats(struct action_util *au, FILE *f, struct rtattr *xstats)
+{
+       return 0;
+}
+
diff --git a/tc/tc.c b/tc/tc.c
index b34875123d1ba896e526b4f893115e129ea04757..abf56f5b8efe56b68c6d38b6b8bdd3d3614baa03 100644 (file)
--- a/tc/tc.c
+++ b/tc/tc.c
@@ -176,7 +176,7 @@ static void usage(void) __attribute__((noreturn));
 static void usage(void)
 {
        fprintf(stderr, "Usage: tc [ OPTIONS ] OBJECT { COMMAND | help }\n"
-                       "where  OBJECT := { qdisc | class | filter }\n"
+                       "where  OBJECT := { qdisc | class | filter | action }\n"
                        "       OPTIONS := { -s[tatistics] | -d[etails] | -r[aw] | -b[atch] file }\n");
        exit(-1);
 }
@@ -242,6 +242,8 @@ int main(int argc, char **argv)
                                ret += do_class(largc-1, largv+1);
                        } else if (matches(largv[0], "filter") == 0) {
                                ret += do_filter(largc-1, largv+1);
+                       } else if (matches(largv[0], "action") == 0) {
+                               ret += do_action(largc-1, largv+1);
                        } else if (matches(largv[0], "help") == 0) {
                                usage();        /* note that usage() doesn't return */
                        } else {
@@ -286,6 +288,8 @@ int main(int argc, char **argv)
                        return do_class(argc-2, argv+2);
                if (matches(argv[1], "filter") == 0)
                        return do_filter(argc-2, argv+2);
+               if (matches(argv[1], "actions") == 0)
+                       return do_action(argc-2, argv+2);
                if (matches(argv[1], "help") == 0)
                        usage();
                fprintf(stderr, "Object \"%s\" is unknown, try \"tc help\".\n", argv[1]);
index 542f8d5fb94b997b902fa10f8e9b5ee7d6cf9017..0c91f42f7e873f6ae747f8045fe3a5e9186a05b4 100644 (file)
@@ -201,7 +201,7 @@ int print_class(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
 
        if (tb[TCA_KIND] == NULL) {
-               fprintf(stderr, "NULL kind\n");
+               fprintf(stderr, "print_class: NULL kind\n");
                return -1;
        }
 
@@ -241,14 +241,18 @@ int print_class(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        fprintf(fp, "\n");
        if (show_stats) {
                if (tb[TCA_STATS]) {
+#ifndef STOOPID_8BYTE
                        if (RTA_PAYLOAD(tb[TCA_STATS]) < sizeof(struct tc_stats))
                                fprintf(fp, "statistics truncated");
                        else {
+#endif
                                struct tc_stats st;
                                memcpy(&st, RTA_DATA(tb[TCA_STATS]), sizeof(st));
                                print_class_tcstats(fp, &st);
                                fprintf(fp, "\n");
+#ifndef STOOPID_8BYTE
                        }
+#endif
                }
                if (q && tb[TCA_XSTATS]) {
                        q->print_xstats(q, fp, tb[TCA_XSTATS]);
@@ -323,11 +327,13 @@ int tc_class_list(int argc, char **argv)
 
        if (rtnl_dump_request(&rth, RTM_GETTCLASS, &t, sizeof(t)) < 0) {
                perror("Cannot send dump request");
+               rtnl_close(&rth);
                exit(1);
        }
 
        if (rtnl_dump_filter(&rth, print_class, stdout, NULL, NULL) < 0) {
                fprintf(stderr, "Dump terminated\n");
+               rtnl_close(&rth);
                exit(1);
        }
 
index d695ca2d85d9da8b855d1d65e44cc3727cbaf1ed..e19a867ec5a920544d08e1f32cf66448cd86e6f2 100644 (file)
@@ -1,5 +1,6 @@
 extern int do_qdisc(int argc, char **argv);
 extern int do_class(int argc, char **argv);
 extern int do_filter(int argc, char **argv);
+extern int do_action(int argc, char **argv);
 
 extern int parse_estimator(int *p_argc, char ***p_argv, struct tc_estimator *est);
index 300c3e70abf3347e80e8926b1e912533e5127077..2cace200998f0bd742629ee4150b12d5938b6088 100644 (file)
@@ -53,7 +53,7 @@ int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv)
        struct {
                struct nlmsghdr         n;
                struct tcmsg            t;
-               char                    buf[4096];
+               char                    buf[MAX_MSG];
        } req;
        struct filter_util *q = NULL;
        __u32 prio = 0;
@@ -165,12 +165,16 @@ int tc_filter_modify(int cmd, unsigned flags, int argc, char **argv)
 
                if ((req.t.tcm_ifindex = ll_name_to_index(d)) == 0) {
                        fprintf(stderr, "Cannot find device \"%s\"\n", d);
+                       rtnl_close(&rth);
                        exit(1);
                }
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) {
+               fprintf(stderr, "We have an error talking to the kernel\n");
+               rtnl_close(&rth);
                exit(2);
+       }
 
        rtnl_close(&rth);
        return 0;
@@ -204,7 +208,7 @@ int print_filter(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
 
        if (tb[TCA_KIND] == NULL) {
-               fprintf(stderr, "NULL kind\n");
+               fprintf(stderr, "print_filter: NULL kind\n");
                return -1;
        }
 
@@ -250,14 +254,18 @@ int print_filter(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
 
        if (show_stats) {
                if (tb[TCA_STATS]) {
+#ifndef STOOPID_8BYTE
                        if (RTA_PAYLOAD(tb[TCA_STATS]) < sizeof(struct tc_stats))
                                fprintf(fp, "statistics truncated");
                        else {
+#endif
                                struct tc_stats st;
                                memcpy(&st, RTA_DATA(tb[TCA_STATS]), sizeof(st));
                                print_tcstats(fp, &st);
                                fprintf(fp, "\n");
+#ifndef STOOPID_8BYTE
                        }
+#endif
                }
        }
        fflush(fp);
@@ -342,6 +350,7 @@ int tc_filter_list(int argc, char **argv)
        if (d[0]) {
                if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) {
                        fprintf(stderr, "Cannot find device \"%s\"\n", d);
+                       rtnl_close(&rth);
                        exit(1);
                }
                filter_ifindex = t.tcm_ifindex;
@@ -349,6 +358,7 @@ int tc_filter_list(int argc, char **argv)
 
        if (rtnl_dump_request(&rth, RTM_GETTFILTER, &t, sizeof(t)) < 0) {
                perror("Cannot send dump request");
+               rtnl_close(&rth);
                exit(1);
        }
 
index 361ca8aaddc631b53ec6be4e529bfcf07829b842..c7f22e1720d1b5ef076f2e0bd2e6b85b392f59de 100644 (file)
@@ -141,6 +141,7 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
 
        if (rtnl_open(&rth, 0) < 0) {
                fprintf(stderr, "Cannot open rtnetlink\n");
+               rtnl_close(&rth);
                exit(1);
        }
 
@@ -151,13 +152,16 @@ int tc_qdisc_modify(int cmd, unsigned flags, int argc, char **argv)
 
                if ((idx = ll_name_to_index(d)) == 0) {
                        fprintf(stderr, "Cannot find device \"%s\"\n", d);
+                       rtnl_close(&rth);
                        exit(1);
                }
                req.t.tcm_ifindex = idx;
        }
 
-       if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0)
+       if (rtnl_talk(&rth, &req.n, 0, 0, NULL, NULL, NULL) < 0) {
+               rtnl_close(&rth);
                exit(2);
+       }
 
        rtnl_close(&rth);
        return 0;
@@ -167,8 +171,9 @@ void print_tcstats(FILE *fp, struct tc_stats *st)
 {
        SPRINT_BUF(b1);
 
-       fprintf(fp, " Sent %llu bytes %u pkts (dropped %u, overlimits %u) ",
+       fprintf(fp, " Sent %llu bytes %u pkts (dropped %u, overlimits %u ) ",
                (unsigned long long)st->bytes, st->packets, st->drops, st->overlimits);
+
        if (st->bps || st->pps || st->qlen || st->backlog) {
                fprintf(fp, "\n ");
                if (st->bps || st->pps) {
@@ -216,7 +221,7 @@ int print_qdisc(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        parse_rtattr(tb, TCA_MAX, TCA_RTA(t), len);
 
        if (tb[TCA_KIND] == NULL) {
-               fprintf(stderr, "NULL kind\n");
+               fprintf(stderr, "print_qdisc: NULL kind\n");
                return -1;
        }
 
@@ -235,7 +240,13 @@ int print_qdisc(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        if (t->tcm_info != 1) {
                fprintf(fp, "refcnt %d ", t->tcm_info);
        }
-       q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND]));
+       /* pfifo_fast is generic enough to warrant the hardcoding --JHS */      
+               
+       if (0 == strcmp("pfifo_fast", RTA_DATA(tb[TCA_KIND])))
+               q = get_qdisc_kind("prio");
+       else
+               q = get_qdisc_kind(RTA_DATA(tb[TCA_KIND]));
+       
        if (tb[TCA_OPTIONS]) {
                if (q)
                        q->print_qopt(q, fp, tb[TCA_OPTIONS]);
@@ -245,15 +256,19 @@ int print_qdisc(struct sockaddr_nl *who, struct nlmsghdr *n, void *arg)
        fprintf(fp, "\n");
        if (show_stats) {
                if (tb[TCA_STATS]) {
+#ifndef STOOPID_8BYTE
                        if (RTA_PAYLOAD(tb[TCA_STATS]) < sizeof(struct tc_stats))
                                fprintf(fp, "statistics truncated");
                        else {
+#endif
                                struct tc_stats st;
                                memcpy(&st, RTA_DATA(tb[TCA_STATS]), sizeof(st));
                                print_tcstats(fp, &st);
                                fprintf(fp, "\n");
                        }
+#ifndef STOOPID_8BYTE
                }
+#endif
                if (q && tb[TCA_XSTATS]) {
                        q->print_xstats(q, fp, tb[TCA_XSTATS]);
                        fprintf(fp, "\n");
@@ -306,6 +321,7 @@ int tc_qdisc_list(int argc, char **argv)
        if (d[0]) {
                if ((t.tcm_ifindex = ll_name_to_index(d)) == 0) {
                        fprintf(stderr, "Cannot find device \"%s\"\n", d);
+                       rtnl_close(&rth);
                        exit(1);
                }
                filter_ifindex = t.tcm_ifindex;
@@ -313,11 +329,13 @@ int tc_qdisc_list(int argc, char **argv)
 
        if (rtnl_dump_request(&rth, RTM_GETQDISC, &t, sizeof(t)) < 0) {
                perror("Cannot send dump request");
+               rtnl_close(&rth);
                exit(1);
        }
 
        if (rtnl_dump_filter(&rth, print_qdisc, stdout, NULL, NULL) < 0) {
                fprintf(stderr, "Dump terminated\n");
+               rtnl_close(&rth);
                exit(1);
        }
 
index d87085c2272ae46c26bf73bced63840f90d984a6..ad72b63eadc5bf07b679ca7e424895ffb4d9d850 100644 (file)
@@ -369,4 +369,62 @@ char * sprint_qdisc_handle(__u32 h, char *buf)
        return buf;
 }
 
+char * action_n2a(int action, char *buf, int len)
+{
+       switch (action) {
+       case -1:
+               return "continue";
+               break;
+       case TC_ACT_OK:
+               return "pass";
+               break;
+       case TC_ACT_SHOT:
+               return "drop";
+               break;
+       case TC_ACT_RECLASSIFY:
+               return "reclassify";
+       case TC_ACT_PIPE:
+               return "pipe";
+       case TC_ACT_STOLEN:
+               return "stolen";
+       default:
+               snprintf(buf, len, "%d", action);
+               return buf;
+       }
+}
 
+int action_a2n(char *arg, int *result)
+{
+       int res;
+
+       if (matches(arg, "continue") == 0)
+               res = -1;
+       else if (matches(arg, "drop") == 0)
+               res = TC_ACT_SHOT;
+       else if (matches(arg, "shot") == 0)
+               res = TC_ACT_SHOT;
+       else if (matches(arg, "pass") == 0)
+               res = TC_ACT_OK;
+       else if (strcmp(arg, "ok") == 0)
+               res = TC_ACT_OK;
+       else if (matches(arg, "reclassify") == 0)
+               res = TC_ACT_RECLASSIFY;
+       else {
+               char dummy;
+               if (sscanf(arg, "%d%c", &res, &dummy) != 1)
+                       return -1;
+       }
+       *result = res;
+       return 0;
+}
+
+void print_tm(FILE * f, struct tcf_t *tm)
+{
+       int hz = get_hz();
+       if (tm->install != 0)
+               fprintf(f, " installed %d sec", tm->install/hz);
+       if (tm->lastuse != 0)
+               fprintf(f, " used %d sec", tm->lastuse/hz);
+       if (tm->expires != 0)
+               fprintf(f, " expires %d sec", tm->expires/hz);
+}
index b3d70da92afeffc19ba2410d7de1cf45a0bbc743..3a2576086c5bda5a3c7edecb494d5bd02f7ed218 100644 (file)
@@ -1,13 +1,14 @@
 #ifndef _TC_UTIL_H_
 #define _TC_UTIL_H_ 1
 
+#define MAX_MSG 16384
 #include <linux/pkt_sched.h>
 #include <linux/pkt_cls.h>
 #include "tc_core.h"
 
 struct qdisc_util
 {
-       struct qdisc_util *next;
+       struct  qdisc_util *next;
        char    id[16];
        int     (*parse_qopt)(struct qdisc_util *qu, int argc, char **argv, struct nlmsghdr *n);
        int     (*print_qopt)(struct qdisc_util *qu, FILE *f, struct rtattr *opt);
@@ -25,6 +26,16 @@ struct filter_util
        int     (*print_fopt)(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 fhandle);
 };
 
+struct action_util
+{
+       struct  action_util *next;
+       char    id[16];
+       int     (*parse_aopt)(struct action_util *a, int *argc, char ***argv, int code, struct nlmsghdr *n);
+       int     (*print_aopt)(struct action_util *au, FILE *f, struct rtattr *opt);
+       int     (*print_xstats)(struct action_util *au, FILE *f, struct rtattr *xstats);
+        
+};
 
 extern struct qdisc_util *get_qdisc_kind(const char *str);
 extern struct filter_util *get_filter_kind(const char *str);
@@ -56,5 +67,14 @@ extern char * sprint_tc_classid(__u32 h, char *buf);
 extern int tc_print_police(FILE *f, struct rtattr *tb);
 extern int parse_police(int *, char ***, int, struct nlmsghdr *);
 
+extern char *action_n2a(int action, char *buf, int len);
+extern int  action_a2n(char *arg, int *result);
+extern int  act_parse_police(struct action_util *a,int *, char ***, int, struct nlmsghdr *);
+extern int  print_police(struct action_util *a,FILE *f, struct rtattr *tb);
+extern int  police_print_xstats(struct action_util *a,FILE *f, struct rtattr *tb);
+extern int  tc_print_action(FILE *f, struct rtattr *tb);
+extern int  tc_print_ipt(FILE *f, struct rtattr *tb);
+extern int  parse_action(int *, char ***, int, struct nlmsghdr *);
+extern void print_tm(FILE *f, struct tcf_t *tm);
 
 #endif