@@ -820,28 +820,28 @@ static int parse_hashkey(int *argc_p, char ***argv_p, struct tc_u32_sel *sel)
return 0;
}
-static void print_ipv4(FILE *f, const struct tc_u32_key *key)
+static int print_ipv4(FILE *f, const struct tc_u32_key *key)
{
char abuf[256];
+ if (key == NULL)
+ return 0;
+
switch (key->off) {
case 0:
switch (ntohl(key->mask)) {
case 0x0f000000:
- fprintf(f, "\n match IP ihl %u",
+ return fprintf(f, "\n match IP ihl %u",
ntohl(key->val) >> 24);
- return;
case 0x00ff0000:
- fprintf(f, "\n match IP dsfield %#x",
+ return fprintf(f, "\n match IP dsfield %#x",
ntohl(key->val) >> 16);
- return;
}
break;
case 8:
if (ntohl(key->mask) == 0x00ff0000) {
- fprintf(f, "\n match IP protocol %d",
+ return fprintf(f, "\n match IP protocol %d",
ntohl(key->val) >> 16);
- return;
}
break;
case 12:
@@ -849,12 +849,11 @@ static void print_ipv4(FILE *f, const struct tc_u32_key *key)
int bits = mask2bits(key->mask);
if (bits >= 0) {
- fprintf(f, "\n %s %s/%d",
+ return fprintf(f, "\n %s %s/%d",
key->off == 12 ? "match IP src" : "match IP dst",
inet_ntop(AF_INET, &key->val,
abuf, sizeof(abuf)),
bits);
- return;
}
}
break;
@@ -862,87 +861,100 @@ static void print_ipv4(FILE *f, const struct tc_u32_key *key)
case 20:
switch (ntohl(key->mask)) {
case 0x0000ffff:
- fprintf(f, "\n match dport %u",
+ return fprintf(f, "\n match dport %u",
ntohl(key->val) & 0xffff);
- return;
case 0xffff0000:
- fprintf(f, "\n match sport %u",
+ return fprintf(f, "\n match sport %u",
ntohl(key->val) >> 16);
- return;
case 0xffffffff:
- fprintf(f, "\n match dport %u, match sport %u",
+ return fprintf(f, "\n match dport %u, match sport %u",
ntohl(key->val) & 0xffff,
ntohl(key->val) >> 16);
- return;
}
/* XXX: Default print_raw */
}
+
+ return 0;
}
-static void print_ipv6(FILE *f, const struct tc_u32_key *key)
+static int print_ipv6(FILE *f, const struct tc_u32_key *key)
{
char abuf[256];
+ static __u32 ipv6_src_addr[4];
+ static int ipv6_src_plen;
+ static __u32 ipv6_dst_addr[4];
+ static int ipv6_dst_plen;
+
+ int ret = 0;
+
+ if ((key == NULL || key->off >= 24) && ipv6_src_plen > 0) {
+ ret = fprintf(f, "\n match ipv6 src %s/%d",
+ inet_ntop(AF_INET6, ipv6_src_addr, abuf, sizeof(abuf)), ipv6_src_plen);
+ memset(ipv6_src_addr, 0, 16);
+ ipv6_src_plen = 0;
+ }
+
+ if (key == NULL && ipv6_dst_plen > 0) {
+ ret += fprintf(f, "\n match ipv6 dst %s/%d",
+ inet_ntop(AF_INET6, ipv6_dst_addr, abuf, sizeof(abuf)), ipv6_dst_plen);
+ memset(ipv6_dst_addr, 0, 16);
+ ipv6_dst_plen = 0;
+ }
+
+ if (key == NULL)
+ return ret;
+
switch (key->off) {
case 0:
- switch (ntohl(key->mask)) {
- case 0x0f000000:
- fprintf(f, "\n match IP ihl %u",
- ntohl(key->val) >> 24);
- return;
- case 0x00ff0000:
- fprintf(f, "\n match IP dsfield %#x",
- ntohl(key->val) >> 16);
- return;
+ if (ntohl(key->mask) & 0x0ff00000) {
+ ret = fprintf(f, "\n match ipv6 class %#x %#x",
+ (ntohl(key->val) & 0x0ff00000) >> 20,
+ (ntohl(key->mask) & 0x0ff00000) >> 20);
+ }
+ if (ntohl(key->mask) & 0x000fffff) {
+ ret += fprintf(f, "\n match ipv6 flowlabel %#x %#x",
+ ntohl(key->val) & 0x000fffff,
+ ntohl(key->mask) & 0x000fffff);
}
+ return ret;
break;
- case 8:
- if (ntohl(key->mask) == 0x00ff0000) {
- fprintf(f, "\n match IP protocol %d",
- ntohl(key->val) >> 16);
- return;
+ case 4:
+ if (ntohl(key->mask) == 0x0000ff00) {
+ return fprintf(f, "\n match ipv6 protocol %d",
+ ntohl(key->val) >> 8);
}
break;
+ case 8:
case 12:
- case 16: {
- int bits = mask2bits(key->mask);
-
- if (bits >= 0) {
- fprintf(f, "\n %s %s/%d",
- key->off == 12 ? "match IP src" : "match IP dst",
- inet_ntop(AF_INET, &key->val,
- abuf, sizeof(abuf)),
- bits);
- return;
- }
+ case 16:
+ case 20: {
+ ipv6_src_plen += mask2bits(key->mask);
+ ipv6_src_addr[(key->off - 8) / 4] = key->val;
}
break;
-
- case 20:
- switch (ntohl(key->mask)) {
- case 0x0000ffff:
- fprintf(f, "\n match sport %u",
- ntohl(key->val) & 0xffff);
- return;
- case 0xffff0000:
- fprintf(f, "\n match dport %u",
- ntohl(key->val) >> 16);
- return;
- case 0xffffffff:
- fprintf(f, "\n match sport %u, match dport %u",
- ntohl(key->val) & 0xffff,
- ntohl(key->val) >> 16);
-
- return;
+ case 24:
+ case 28:
+ case 32:
+ case 36: {
+ ipv6_dst_plen += mask2bits(key->mask);
+ ipv6_dst_addr[(key->off - 24) / 4] = key->val;
}
+ break;
+
/* XXX: Default print_raw */
}
+
+ return 0;
}
-static void print_raw(FILE *f, const struct tc_u32_key *key)
+static int print_raw(FILE *f, const struct tc_u32_key *key)
{
- fprintf(f, "\n match %08x/%08x at %s%d",
+ if (key == NULL)
+ return 0;
+
+ return fprintf(f, "\n match %08x/%08x at %s%d",
(unsigned int)ntohl(key->val),
(unsigned int)ntohl(key->mask),
key->offmask ? "nexthdr+" : "",
@@ -952,14 +964,14 @@ static void print_raw(FILE *f, const struct tc_u32_key *key)
static const struct {
__u16 proto;
__u16 pad;
- void (*pprinter)(FILE *f, const struct tc_u32_key *key);
+ int (*pprinter)(FILE *f, const struct tc_u32_key *key);
} u32_pprinters[] = {
{0, 0, print_raw},
{ETH_P_IP, 0, print_ipv4},
{ETH_P_IPV6, 0, print_ipv6},
};
-static void show_keys(FILE *f, const struct tc_u32_key *key)
+static int show_keys(FILE *f, const struct tc_u32_key *key)
{
int i = 0;
@@ -969,8 +981,7 @@ static void show_keys(FILE *f, const struct tc_u32_key *key)
for (i = 0; i < ARRAY_SIZE(u32_pprinters); i++) {
if (u32_pprinters[i].proto == ntohs(f_proto)) {
show_k:
- u32_pprinters[i].pprinter(f, key);
- return;
+ return u32_pprinters[i].pprinter(f, key);
}
}
@@ -1289,12 +1300,13 @@ static int u32_print_opt(struct filter_util *qu, FILE *f, struct rtattr *opt,
if (sel) {
if (sel->nkeys) {
int i;
-
- for (i = 0; i < sel->nkeys; i++) {
- show_keys(f, sel->keys + i);
- if (show_stats && NULL != pf)
- fprintf(f, " (success %llu ) ",
- (unsigned long long) pf->kcnts[i]);
+ // The ipv6 pretty printing requires an additional call at the end.
+ // Call the show_keys with the NULL value after call with last key.
+ for (i = 0; i <= sel->nkeys; i++) {
+ if (show_keys(f, i < sel->nkeys ? sel->keys + i : NULL))
+ if (i < sel->nkeys && show_stats && NULL != pf)
+ fprintf(f, " (success %llu ) ",
+ (unsigned long long) pf->kcnts[i]);
}
}
Unexpectedly the print_ipv6 function is the copy-paste version of the print_ipv4 function. Fixed. Before patch: $ sudo tc -p -s f ls dev dummy0 filter parent 1: protocol ipv6 pref 30 u32 chain 0 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800: ht divisor 1 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) match IP src 64.0.0.0/32 (success 0 ) match IP dst 0.0.0.0/32 (success 0 ) match sport 0, match dport 0 (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) (success 0 ) (success 0 ) (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::802 order 2050 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) match IP src 0.204.0.221/32 (success 0 ) match IP dst 0.0.0.0/1 (success 0 ) (success 0 ) (success 0 ) (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::803 order 2051 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::804 order 2052 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::805 order 2053 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match IP ihl 1 (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::806 order 2054 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::807 order 2055 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) (success 0 ) After patch: $ sudo tc -p -s f ls dev dummy0 filter parent 1: protocol ipv6 pref 30 u32 chain 0 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800: ht divisor 1 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::800 order 2048 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 src 2a02:26e0:4000::/128 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::801 order 2049 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 dst 2a02:26e0:4000::/128 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::802 order 2050 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 src aa:bb:cc:dd::/65 match ipv6 dst aa:bb:cc:dd::/66 filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::803 order 2051 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 class 0xff 0xff (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::804 order 2052 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 class 0x10 0xff (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::805 order 2053 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 class 0x10 0xf0 (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::806 order 2054 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 flowlabel 0xbcde 0xffff (success 0 ) filter parent 1: protocol ipv6 pref 30 u32 chain 0 fh 800::807 order 2055 key ht 800 bkt 0 flowid 1:1 not_in_hw (rule hit 0 success 0) match ipv6 class 0x12 0xff match ipv6 flowlabel 0xbcde 0xffff (success 0 ) Signed-off-by: Anton Danilov <littlesmilingcloud@gmail.com> --- tc/f_u32.c | 152 +++++++++++++++++++++++++++++------------------------ 1 file changed, 82 insertions(+), 70 deletions(-)