|
|
4aca6e |
From c121d1c4937a0495e917dc637fac6aa6846e8ea6 Mon Sep 17 00:00:00 2001
|
|
|
4aca6e |
From: Phil Sutter <psutter@redhat.com>
|
|
|
4aca6e |
Date: Fri, 17 Mar 2017 13:24:35 +0100
|
|
|
4aca6e |
Subject: [PATCH] tc: flower: Refactor matching flags to be more user friendly
|
|
|
4aca6e |
|
|
|
4aca6e |
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1422629
|
|
|
4aca6e |
Upstream Status: iproute2.git commit 08f66c80c094e
|
|
|
4aca6e |
|
|
|
4aca6e |
commit 08f66c80c094eaa5d71abc0395fd114ff919af7a
|
|
|
4aca6e |
Author: Paul Blakey <paulb@mellanox.com>
|
|
|
4aca6e |
Date: Fri Jan 20 10:36:45 2017 -0800
|
|
|
4aca6e |
|
|
|
4aca6e |
tc: flower: Refactor matching flags to be more user friendly
|
|
|
4aca6e |
|
|
|
4aca6e |
Instead of "magic numbers" we can now specify each flag
|
|
|
4aca6e |
by name. Prefix of "no" (e.g nofrag) unsets the flag,
|
|
|
4aca6e |
otherwise it wil be set.
|
|
|
4aca6e |
|
|
|
4aca6e |
Example:
|
|
|
4aca6e |
# add a flower filter that will drop fragmented packets
|
|
|
4aca6e |
tc filter add dev ens4f0 protocol ip parent ffff: \
|
|
|
4aca6e |
flower \
|
|
|
4aca6e |
src_mac e4:1d:2d:fd:8b:01 \
|
|
|
4aca6e |
dst_mac e4:1d:2d:fd:8b:02 \
|
|
|
4aca6e |
indev ens4f0 \
|
|
|
4aca6e |
ip_flags frag \
|
|
|
4aca6e |
action drop
|
|
|
4aca6e |
|
|
|
4aca6e |
# add a flower filter that will drop non-fragmented packets
|
|
|
4aca6e |
tc filter add dev ens4f0 protocol ip parent ffff: \
|
|
|
4aca6e |
flower \
|
|
|
4aca6e |
src_mac e4:1d:2d:fd:8b:01 \
|
|
|
4aca6e |
dst_mac e4:1d:2d:fd:8b:02 \
|
|
|
4aca6e |
indev ens4f0 \
|
|
|
4aca6e |
ip_flags nofrag \
|
|
|
4aca6e |
action drop
|
|
|
4aca6e |
|
|
|
4aca6e |
Fixes: 22a8f019891c ('tc: flower: support matching flags')
|
|
|
4aca6e |
Signed-off-by: Paul Blakey <paulb@mellanox.com>
|
|
|
4aca6e |
Reviewed-by: Roi Dayan <roid@mellanox.com>
|
|
|
4aca6e |
Reviewed-by: Jiri Benc <jbenc@redhat.com>
|
|
|
4aca6e |
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
|
|
|
4aca6e |
---
|
|
|
4aca6e |
man/man8/tc-flower.8 | 12 +++++-
|
|
|
4aca6e |
tc/f_flower.c | 117 ++++++++++++++++++++++++++++++++++++++++-----------
|
|
|
4aca6e |
2 files changed, 102 insertions(+), 27 deletions(-)
|
|
|
4aca6e |
|
|
|
4aca6e |
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
|
|
|
4aca6e |
index 2dd2c5e..2bdd2ef 100644
|
|
|
4aca6e |
--- a/man/man8/tc-flower.8
|
|
|
4aca6e |
+++ b/man/man8/tc-flower.8
|
|
|
4aca6e |
@@ -46,7 +46,9 @@ flower \- flow based traffic control filter
|
|
|
4aca6e |
.BR enc_dst_ip " | " enc_src_ip " } { "
|
|
|
4aca6e |
.IR ipv4_address " | " ipv6_address " } | "
|
|
|
4aca6e |
.B enc_dst_port
|
|
|
4aca6e |
-.IR port_number
|
|
|
4aca6e |
+.IR port_number " | "
|
|
|
4aca6e |
+.BR ip_flags
|
|
|
4aca6e |
+.IR IP_FLAGS
|
|
|
4aca6e |
.SH DESCRIPTION
|
|
|
4aca6e |
The
|
|
|
4aca6e |
.B flower
|
|
|
4aca6e |
@@ -183,13 +185,19 @@ prefix length. If the prefix is missing, \fBtc\fR assumes a full-length
|
|
|
4aca6e |
host match. Dst port
|
|
|
4aca6e |
.I NUMBER
|
|
|
4aca6e |
is a 16 bit UDP dst port.
|
|
|
4aca6e |
+.TP
|
|
|
4aca6e |
+.BI ip_flags " IP_FLAGS"
|
|
|
4aca6e |
+.I IP_FLAGS
|
|
|
4aca6e |
+may be either
|
|
|
4aca6e |
+.BR frag " or " nofrag
|
|
|
4aca6e |
+to match on fragmented packets or not respectively.
|
|
|
4aca6e |
.SH NOTES
|
|
|
4aca6e |
As stated above where applicable, matches of a certain layer implicitly depend
|
|
|
4aca6e |
on the matches of the next lower layer. Precisely, layer one and two matches
|
|
|
4aca6e |
(\fBindev\fR, \fBdst_mac\fR and \fBsrc_mac\fR)
|
|
|
4aca6e |
have no dependency, layer three matches
|
|
|
4aca6e |
(\fBip_proto\fR, \fBdst_ip\fR, \fBsrc_ip\fR, \fBarp_tip\fR, \fBarp_sip\fR,
|
|
|
4aca6e |
-\fBarp_op\fR, \fBarp_tha\fR and \fBarp_sha\fR)
|
|
|
4aca6e |
+\fBarp_op\fR, \fBarp_tha\fR, \fBarp_sha\fR and \fBip_flags\fR)
|
|
|
4aca6e |
depend on the
|
|
|
4aca6e |
.B protocol
|
|
|
4aca6e |
option of tc filter, layer four port matches
|
|
|
4aca6e |
diff --git a/tc/f_flower.c b/tc/f_flower.c
|
|
|
4aca6e |
index 2473aea..ddf64c2 100644
|
|
|
4aca6e |
--- a/tc/f_flower.c
|
|
|
4aca6e |
+++ b/tc/f_flower.c
|
|
|
4aca6e |
@@ -24,6 +24,10 @@
|
|
|
4aca6e |
#include "tc_util.h"
|
|
|
4aca6e |
#include "rt_names.h"
|
|
|
4aca6e |
|
|
|
4aca6e |
+enum flower_matching_flags {
|
|
|
4aca6e |
+ FLOWER_IP_FLAGS,
|
|
|
4aca6e |
+};
|
|
|
4aca6e |
+
|
|
|
4aca6e |
enum flower_endpoint {
|
|
|
4aca6e |
FLOWER_ENDPOINT_SRC,
|
|
|
4aca6e |
FLOWER_ENDPOINT_DST
|
|
|
4aca6e |
@@ -63,7 +67,7 @@ static void explain(void)
|
|
|
4aca6e |
" enc_dst_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
|
|
|
4aca6e |
" enc_src_ip [ IPV4-ADDR | IPV6-ADDR ] |\n"
|
|
|
4aca6e |
" enc_key_id [ KEY-ID ] |\n"
|
|
|
4aca6e |
- " matching_flags MATCHING-FLAGS | \n"
|
|
|
4aca6e |
+ " ip_flags IP-FLAGS | \n"
|
|
|
4aca6e |
" enc_dst_port [ port_number ] }\n"
|
|
|
4aca6e |
" FILTERID := X:Y:Z\n"
|
|
|
4aca6e |
" MASKED_LLADDR := { LLADDR | LLADDR/MASK | LLADDR/BITS }\n"
|
|
|
4aca6e |
@@ -136,28 +140,56 @@ static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
|
|
|
4aca6e |
return 0;
|
|
|
4aca6e |
}
|
|
|
4aca6e |
|
|
|
4aca6e |
-static int flower_parse_matching_flags(char *str, int type, int mask_type,
|
|
|
4aca6e |
- struct nlmsghdr *n)
|
|
|
4aca6e |
-{
|
|
|
4aca6e |
- __u32 mtf, mtf_mask;
|
|
|
4aca6e |
- char *c;
|
|
|
4aca6e |
+struct flag_to_string {
|
|
|
4aca6e |
+ int flag;
|
|
|
4aca6e |
+ enum flower_matching_flags type;
|
|
|
4aca6e |
+ char *string;
|
|
|
4aca6e |
+};
|
|
|
4aca6e |
|
|
|
4aca6e |
- c = strchr(str, '/');
|
|
|
4aca6e |
- if (c)
|
|
|
4aca6e |
- *c = '\0';
|
|
|
4aca6e |
+static struct flag_to_string flags_str[] = {
|
|
|
4aca6e |
+ { TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT, FLOWER_IP_FLAGS, "frag" },
|
|
|
4aca6e |
+};
|
|
|
4aca6e |
|
|
|
4aca6e |
- if (get_u32(&mtf, str, 0))
|
|
|
4aca6e |
- return -1;
|
|
|
4aca6e |
+static int flower_parse_matching_flags(char *str,
|
|
|
4aca6e |
+ enum flower_matching_flags type,
|
|
|
4aca6e |
+ __u32 *mtf, __u32 *mtf_mask)
|
|
|
4aca6e |
+{
|
|
|
4aca6e |
+ char *token;
|
|
|
4aca6e |
+ bool no;
|
|
|
4aca6e |
+ bool found;
|
|
|
4aca6e |
+ int i;
|
|
|
4aca6e |
|
|
|
4aca6e |
- if (c) {
|
|
|
4aca6e |
- if (get_u32(&mtf_mask, ++c, 0))
|
|
|
4aca6e |
+ token = strtok(str, "/");
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ while (token) {
|
|
|
4aca6e |
+ if (!strncmp(token, "no", 2)) {
|
|
|
4aca6e |
+ no = true;
|
|
|
4aca6e |
+ token += 2;
|
|
|
4aca6e |
+ } else
|
|
|
4aca6e |
+ no = false;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ found = false;
|
|
|
4aca6e |
+ for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
|
|
|
4aca6e |
+ if (type != flags_str[i].type)
|
|
|
4aca6e |
+ continue;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ if (!strcmp(token, flags_str[i].string)) {
|
|
|
4aca6e |
+ if (no)
|
|
|
4aca6e |
+ *mtf &= ~flags_str[i].flag;
|
|
|
4aca6e |
+ else
|
|
|
4aca6e |
+ *mtf |= flags_str[i].flag;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ *mtf_mask |= flags_str[i].flag;
|
|
|
4aca6e |
+ found = true;
|
|
|
4aca6e |
+ break;
|
|
|
4aca6e |
+ }
|
|
|
4aca6e |
+ }
|
|
|
4aca6e |
+ if (!found)
|
|
|
4aca6e |
return -1;
|
|
|
4aca6e |
- } else {
|
|
|
4aca6e |
- mtf_mask = 0xffffffff;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ token = strtok(NULL, "/");
|
|
|
4aca6e |
}
|
|
|
4aca6e |
|
|
|
4aca6e |
- addattr32(n, MAX_MSG, type, htonl(mtf));
|
|
|
4aca6e |
- addattr32(n, MAX_MSG, mask_type, htonl(mtf_mask));
|
|
|
4aca6e |
return 0;
|
|
|
4aca6e |
}
|
|
|
4aca6e |
|
|
|
4aca6e |
@@ -433,6 +465,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
4aca6e |
__be16 vlan_ethtype = 0;
|
|
|
4aca6e |
__u8 ip_proto = 0xff;
|
|
|
4aca6e |
__u32 flags = 0;
|
|
|
4aca6e |
+ __u32 mtf = 0;
|
|
|
4aca6e |
+ __u32 mtf_mask = 0;
|
|
|
4aca6e |
|
|
|
4aca6e |
if (handle) {
|
|
|
4aca6e |
ret = get_u32(&t->tcm_handle, handle, 0);
|
|
|
4aca6e |
@@ -462,14 +496,14 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
|
|
|
4aca6e |
return -1;
|
|
|
4aca6e |
}
|
|
|
4aca6e |
addattr_l(n, MAX_MSG, TCA_FLOWER_CLASSID, &handle, 4);
|
|
|
4aca6e |
- } else if (matches(*argv, "matching_flags") == 0) {
|
|
|
4aca6e |
+ } else if (matches(*argv, "ip_flags") == 0) {
|
|
|
4aca6e |
NEXT_ARG();
|
|
|
4aca6e |
ret = flower_parse_matching_flags(*argv,
|
|
|
4aca6e |
- TCA_FLOWER_KEY_FLAGS,
|
|
|
4aca6e |
- TCA_FLOWER_KEY_FLAGS_MASK,
|
|
|
4aca6e |
- n);
|
|
|
4aca6e |
+ FLOWER_IP_FLAGS,
|
|
|
4aca6e |
+ &mtf,
|
|
|
4aca6e |
+ &mtf_mask);
|
|
|
4aca6e |
if (ret < 0) {
|
|
|
4aca6e |
- fprintf(stderr, "Illegal \"matching_flags\"\n");
|
|
|
4aca6e |
+ fprintf(stderr, "Illegal \"ip_flags\"\n");
|
|
|
4aca6e |
return -1;
|
|
|
4aca6e |
}
|
|
|
4aca6e |
} else if (matches(*argv, "skip_hw") == 0) {
|
|
|
4aca6e |
@@ -726,6 +760,16 @@ parse_done:
|
|
|
4aca6e |
if (ret)
|
|
|
4aca6e |
return ret;
|
|
|
4aca6e |
|
|
|
4aca6e |
+ if (mtf_mask) {
|
|
|
4aca6e |
+ ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS, htonl(mtf));
|
|
|
4aca6e |
+ if (ret)
|
|
|
4aca6e |
+ return ret;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ ret = addattr32(n, MAX_MSG, TCA_FLOWER_KEY_FLAGS_MASK, htonl(mtf_mask));
|
|
|
4aca6e |
+ if (ret)
|
|
|
4aca6e |
+ return ret;
|
|
|
4aca6e |
+ }
|
|
|
4aca6e |
+
|
|
|
4aca6e |
ret = addattr16(n, MAX_MSG, TCA_FLOWER_KEY_ETH_TYPE, eth_type);
|
|
|
4aca6e |
if (ret)
|
|
|
4aca6e |
return ret;
|
|
|
4aca6e |
@@ -828,14 +872,36 @@ static void flower_print_ip_proto(FILE *f, __u8 *p_ip_proto,
|
|
|
4aca6e |
}
|
|
|
4aca6e |
|
|
|
4aca6e |
static void flower_print_matching_flags(FILE *f, char *name,
|
|
|
4aca6e |
+ enum flower_matching_flags type,
|
|
|
4aca6e |
struct rtattr *attr,
|
|
|
4aca6e |
struct rtattr *mask_attr)
|
|
|
4aca6e |
{
|
|
|
4aca6e |
+ int i;
|
|
|
4aca6e |
+ int count = 0;
|
|
|
4aca6e |
+ __u32 mtf;
|
|
|
4aca6e |
+ __u32 mtf_mask;
|
|
|
4aca6e |
+
|
|
|
4aca6e |
if (!mask_attr || RTA_PAYLOAD(mask_attr) != 4)
|
|
|
4aca6e |
return;
|
|
|
4aca6e |
|
|
|
4aca6e |
- fprintf(f, "\n %s 0x%08x/0x%08x", name, ntohl(rta_getattr_u32(attr)),
|
|
|
4aca6e |
- mask_attr ? ntohl(rta_getattr_u32(mask_attr)) : 0xffffffff);
|
|
|
4aca6e |
+ mtf = ntohl(rta_getattr_u32(attr));
|
|
|
4aca6e |
+ mtf_mask = ntohl(rta_getattr_u32(mask_attr));
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ for (i = 0; i < ARRAY_SIZE(flags_str); i++) {
|
|
|
4aca6e |
+ if (type != flags_str[i].type)
|
|
|
4aca6e |
+ continue;
|
|
|
4aca6e |
+ if (mtf_mask & flags_str[i].flag) {
|
|
|
4aca6e |
+ if (++count == 1)
|
|
|
4aca6e |
+ fprintf(f, "\n %s ", name);
|
|
|
4aca6e |
+ else
|
|
|
4aca6e |
+ fprintf(f, "/");
|
|
|
4aca6e |
+
|
|
|
4aca6e |
+ if (mtf & flags_str[i].flag)
|
|
|
4aca6e |
+ fprintf(f, "%s", flags_str[i].string);
|
|
|
4aca6e |
+ else
|
|
|
4aca6e |
+ fprintf(f, "no%s", flags_str[i].string);
|
|
|
4aca6e |
+ }
|
|
|
4aca6e |
+ }
|
|
|
4aca6e |
}
|
|
|
4aca6e |
|
|
|
4aca6e |
static void flower_print_ip_addr(FILE *f, char *name, __be16 eth_type,
|
|
|
4aca6e |
@@ -1034,7 +1100,8 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
|
|
|
4aca6e |
flower_print_port(f, "enc_dst_port",
|
|
|
4aca6e |
tb[TCA_FLOWER_KEY_ENC_UDP_DST_PORT]);
|
|
|
4aca6e |
|
|
|
4aca6e |
- flower_print_matching_flags(f, "matching_flags",
|
|
|
4aca6e |
+ flower_print_matching_flags(f, "ip_flags",
|
|
|
4aca6e |
+ FLOWER_IP_FLAGS,
|
|
|
4aca6e |
tb[TCA_FLOWER_KEY_FLAGS],
|
|
|
4aca6e |
tb[TCA_FLOWER_KEY_FLAGS_MASK]);
|
|
|
4aca6e |
|
|
|
4aca6e |
--
|
|
|
4aca6e |
1.8.3.1
|
|
|
4aca6e |
|