Commit 6b1ac654 authored by Stephen Hemminger's avatar Stephen Hemminger

add decode of match rules

Show ip address etc when decoding output of tc filter show
Signed-off-by: default avatarStephen Hemminger <stephen.hemminger@vyatta.com>
parent ea5dd59c
...@@ -74,6 +74,7 @@ extern int get_addr_1(inet_prefix *dst, const char *arg, int family); ...@@ -74,6 +74,7 @@ extern int get_addr_1(inet_prefix *dst, const char *arg, int family);
extern int get_prefix_1(inet_prefix *dst, char *arg, int family); extern int get_prefix_1(inet_prefix *dst, char *arg, int family);
extern int get_addr(inet_prefix *dst, const char *arg, int family); extern int get_addr(inet_prefix *dst, const char *arg, int family);
extern int get_prefix(inet_prefix *dst, char *arg, int family); extern int get_prefix(inet_prefix *dst, char *arg, int family);
extern int mask2bits(__u32 netmask);
extern int get_integer(int *val, const char *arg, int base); extern int get_integer(int *val, const char *arg, int base);
extern int get_unsigned(unsigned *val, const char *arg, int base); extern int get_unsigned(unsigned *val, const char *arg, int base);
......
...@@ -47,27 +47,18 @@ int get_integer(int *val, const char *arg, int base) ...@@ -47,27 +47,18 @@ int get_integer(int *val, const char *arg, int base)
return 0; return 0;
} }
/* a valid netmask must be 2^n - 1 */ int mask2bits(__u32 netmask)
static int is_valid_netmask(const inet_prefix *addr)
{
uint32_t host;
if (addr->family != AF_INET)
return 0;
host = ~ntohl(addr->data[0]);
return (host & (host + 1)) == 0;
}
static unsigned cidr(const inet_prefix *addr)
{ {
unsigned bits = 0; unsigned bits = 0;
u_int32_t mask; __u32 mask = ntohl(netmask);
__u32 host = ~mask;
for (mask = ntohl(addr->data[0]); mask; mask <<= 1) /* a valid netmask must be 2^n - 1 */
++bits; if ((host & (host + 1)) != 0)
return -1;
for (; mask; mask <<= 1)
++bits;
return bits; return bits;
} }
...@@ -79,11 +70,13 @@ static int get_netmask(unsigned *val, const char *arg, int base) ...@@ -79,11 +70,13 @@ static int get_netmask(unsigned *val, const char *arg, int base)
return 0; return 0;
/* try coverting dotted quad to CIDR */ /* try coverting dotted quad to CIDR */
if (!get_addr_1(&addr, arg, AF_INET)) { if (!get_addr_1(&addr, arg, AF_INET) && addr.family == AF_INET) {
if (is_valid_netmask(&addr)) int b = mask2bits(addr.data[0]);
return 0;
*val = cidr(&addr); if (b >= 0) {
*val = b;
return 0;
}
} }
return -1; return -1;
......
...@@ -564,6 +564,7 @@ done: ...@@ -564,6 +564,7 @@ done:
return res; return res;
} }
static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) static int parse_icmp(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
{ {
int res = -1; int res = -1;
...@@ -771,7 +772,47 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel) ...@@ -771,7 +772,47 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
return 0; return 0;
} }
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n) static void show_key(FILE *f, const struct tc_u32_key *key)
{
char abuf[256];
if (show_raw)
goto raw;
switch (key->off) {
case 12:
case 16: {
int bits = mask2bits(key->mask);
if (bits >= 0) {
fprintf(f, "\n %s %s/%d\n",
key->off == 12 ? "src" : "dst",
inet_ntop(AF_INET, &key->val, abuf, sizeof(abuf)),
bits);
return;
}
}
break;
case 20:
case 22:
if (key->mask == ntohl(0xffff)) {
fprintf(f, "\n %s %u\n",
key->off == 20 ? "sport" : "dport",
(unsigned short) ntohl(key->val));
return;
}
}
raw:
fprintf(f, "\n match %08x/%08x at %s%d",
(unsigned int)ntohl(key->val),
(unsigned int)ntohl(key->mask),
key->offmask ? "nexthdr+" : "",
key->off);
}
static int u32_parse_opt(struct filter_util *qu, char *handle,
int argc, char **argv, struct nlmsghdr *n)
{ {
struct { struct {
struct tc_u32_sel sel; struct tc_u32_sel sel;
...@@ -966,7 +1007,8 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char ** ...@@ -966,7 +1007,8 @@ static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **
return 0; return 0;
} }
static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __u32 handle) static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
__u32 handle)
{ {
struct rtattr *tb[TCA_U32_MAX+1]; struct rtattr *tb[TCA_U32_MAX+1];
struct tc_u32_sel *sel = NULL; struct tc_u32_sel *sel = NULL;
...@@ -1037,17 +1079,12 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __ ...@@ -1037,17 +1079,12 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt, __
} }
if (sel) { if (sel) {
int i;
struct tc_u32_key *key = sel->keys;
if (sel->nkeys) { if (sel->nkeys) {
for (i=0; i<sel->nkeys; i++, key++) { int i;
fprintf(f, "\n match %08x/%08x at %s%d", for (i=0; i<sel->nkeys; i++) {
(unsigned int)ntohl(key->val), show_key(f, sel->keys + i);
(unsigned int)ntohl(key->mask),
key->offmask ? "nexthdr+" : "",
key->off);
if (show_stats && NULL != pf) if (show_stats && NULL != pf)
fprintf(f, " (success %lld ) ", fprintf(f, " (success %llu ) ",
(unsigned long long) pf->kcnts[i]); (unsigned long long) pf->kcnts[i]);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment