diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8 index df4d8e19..9ae10e6f 100644 --- a/man/man8/tc-flower.8 +++ b/man/man8/tc-flower.8 @@ -18,7 +18,9 @@ flower \- flow based traffic control filter .ti -8 .IR MATCH " := { " .B indev -.IR ifname " | { " +.IR ifname " | " +.BR skip_sw " | " skip_hw +.R " | { " .BR dst_mac " | " src_mac " } " .IR mac_address " | " .BR eth_type " { " ipv4 " | " ipv6 " | " @@ -55,6 +57,13 @@ is the name of an interface which must exist at the time of .B tc invocation. .TP +.BI skip_sw +Do not process filter by software. If hardware has no offload support for this +filter, or TC offload is not enabled for the interface, operation will fail. +.TP +.BI skip_hw +Do not process filter by hardware. +.TP .BI dst_mac " mac_address" .TQ .BI src_mac " mac_address" diff --git a/tc/f_flower.c b/tc/f_flower.c index fd2014b3..7b46ceb1 100644 --- a/tc/f_flower.c +++ b/tc/f_flower.c @@ -25,6 +25,7 @@ static void explain(void) { fprintf(stderr, "Usage: ... flower [ MATCH-LIST ]\n"); + fprintf(stderr, " [ skip_sw | skip_hw ]\n"); fprintf(stderr, " [ action ACTION-SPEC ] [ classid CLASSID ]\n"); fprintf(stderr, "\n"); fprintf(stderr, "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n"); @@ -167,6 +168,7 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, struct rtattr *tail; __be16 eth_type = TC_H_MIN(t->tcm_info); __u8 ip_proto = 0xff; + __u32 flags = 0; if (handle) { ret = get_u32(&t->tcm_handle, handle, 0); @@ -196,6 +198,10 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, return -1; } addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4); + } else if (matches(*argv, "skip_hw") == 0) { + flags |= TCA_CLS_FLAGS_SKIP_HW; + } else if (matches(*argv, "skip_sw") == 0) { + flags |= TCA_CLS_FLAGS_SKIP_SW; } else if (matches(*argv, "indev") == 0) { char ifname[IFNAMSIZ]; @@ -294,6 +300,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle, } parse_done: + addattr32(n, MAX_MSG, TCA_FLOWER_FLAGS, flags); + ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type); if (ret) { fprintf(stderr, "Illegal \"eth_type\"(0x%x)\n", @@ -498,6 +506,15 @@ static int flower_print_opt(struct filter_util *qu, FILE *f, tb[TCA_FLOWER_KEY_TCP_SRC], tb[TCA_FLOWER_KEY_UDP_SRC]); + if (tb[TCA_FLOWER_FLAGS]) { + __u32 flags = rta_getattr_u32(tb[TCA_FLOWER_FLAGS]); + + if (flags & TCA_CLS_FLAGS_SKIP_HW) + fprintf(f, "\n skip_hw"); + if (flags & TCA_CLS_FLAGS_SKIP_SW) + fprintf(f, "\n skip_sw"); + } + if (tb[TCA_FLOWER_ACT]) { tc_print_action(f, tb[TCA_FLOWER_ACT]); }