mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-11-02 16:56:11 +00:00
new stuff from jamal.
(Logical change 1.66)
This commit is contained in:
parent
6d3692a94c
commit
2373fde9b0
71
tc/f_u32.c
71
tc/f_u32.c
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
6
tc/tc.c
6
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]);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
58
tc/tc_util.c
58
tc/tc_util.c
@ -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);
|
||||
}
|
||||
|
||||
22
tc/tc_util.h
22
tc/tc_util.h
@ -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
|
||||
|
||||
Loading…
Reference in New Issue
Block a user