naccyde / rpms / iproute

Forked from rpms/iproute 9 months ago
Clone

Blame SOURCES/0133-tc-flower-Refactor-matching-flags-to-be-more-user-fr.patch

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