new stuff from jamal.

(Logical change 1.66)
This commit is contained in:
osdl.net!shemminger 2004-08-13 23:54:55 +00:00
parent 6d3692a94c
commit 2373fde9b0
9 changed files with 245 additions and 43 deletions

View 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;
}

View 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>
@ -24,12 +26,22 @@
#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;
}

View File

@ -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]);

View 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);
}

View 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);

View 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);
}

View 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);
}

View 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);
}

View 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