Blame SOURCES/0033-tc-flower-add-support-for-tcp-flags.patch

cd1737
From 7cbf364a5f68ba008c5e0702266fe3dc606b1d6f Mon Sep 17 00:00:00 2001
cd1737
From: Kamal Heib <kheib@redhat.com>
cd1737
Date: Thu, 9 Nov 2017 04:44:32 -0500
cd1737
Subject: [PATCH] tc: flower: add support for tcp flags
cd1737
cd1737
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1456539
cd1737
cd1737
commit 0c30d14d0a2fc2fb6b7fef62bea05f2e5c3eb26a
cd1737
Author: Jiri Pirko <jiri@mellanox.com>
cd1737
Date:   Tue May 23 23:51:39 2017 +0200
cd1737
cd1737
    tc: flower: add support for tcp flags
cd1737
cd1737
    Allow user to insert a flower classifier filter rule which includes
cd1737
    match for tcp flags.
cd1737
cd1737
    Signed-off-by: Jiri Pirko <jiri@mellanox.com>
cd1737
cd1737
Signed-off-by: Kamal Heib <kheib@redhat.com>
cd1737
---
d30c09
 man/man8/tc-flower.8 |  8 ++++++
d30c09
 tc/f_flower.c        | 62 ++++++++++++++++++++++++++++++++++++++++++++
cd1737
 2 files changed, 70 insertions(+)
cd1737
cd1737
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
d30c09
index ba290657c2245..76480798d72f9 100644
cd1737
--- a/man/man8/tc-flower.8
cd1737
+++ b/man/man8/tc-flower.8
cd1737
@@ -35,6 +35,8 @@ flower \- flow based traffic control filter
cd1737
 .IR PREFIX " | { "
cd1737
 .BR dst_port " | " src_port " } "
cd1737
 .IR port_number " } | "
cd1737
+.B tcp_flags
cd1737
+.IR MASKED_TCP_FLAGS " | "
cd1737
 .B type
cd1737
 .IR MASKED_TYPE " | "
cd1737
 .B code
cd1737
@@ -136,6 +138,12 @@ Match on layer 4 protocol source or destination port number. Only available for
cd1737
 .BR ip_proto " values " udp ", " tcp  " and " sctp
cd1737
 which have to be specified in beforehand.
cd1737
 .TP
cd1737
+.BI tcp_flags " MASKED_TCP_FLAGS"
cd1737
+Match on TCP flags represented as 12bit bitfield in in hexadecimal format.
cd1737
+A mask may be optionally provided to limit the bits which are matched. A mask
cd1737
+is provided by following the value with a slash and then the mask. If the mask
cd1737
+is missing then a match on all bits is assumed.
cd1737
+.TP
cd1737
 .BI type " MASKED_TYPE"
cd1737
 .TQ
cd1737
 .BI code " MASKED_CODE"
cd1737
diff --git a/tc/f_flower.c b/tc/f_flower.c
d30c09
index ebc63ca6b2a27..1b6b46ea0177b 100644
cd1737
--- a/tc/f_flower.c
cd1737
+++ b/tc/f_flower.c
cd1737
@@ -57,6 +57,7 @@ static void explain(void)
cd1737
 		"                       src_ip PREFIX |\n"
cd1737
 		"                       dst_port PORT-NUMBER |\n"
cd1737
 		"                       src_port PORT-NUMBER |\n"
cd1737
+		"                       tcp_flags MASKED-TCP_FLAGS |\n"
cd1737
 		"                       type MASKED-ICMP-TYPE |\n"
cd1737
 		"                       code MASKED-ICMP-CODE |\n"
cd1737
 		"                       arp_tip IPV4-PREFIX |\n"
cd1737
@@ -474,6 +475,41 @@ static int flower_parse_port(char *str, __u8 ip_proto,
cd1737
 	return 0;
cd1737
 }
cd1737
 
cd1737
+#define TCP_FLAGS_MAX_MASK 0xfff
cd1737
+
cd1737
+static int flower_parse_tcp_flags(char *str, int flags_type, int mask_type,
cd1737
+				  struct nlmsghdr *n)
cd1737
+{
cd1737
+	char *slash;
cd1737
+	int ret, err = -1;
cd1737
+	__u16 flags;
cd1737
+
cd1737
+	slash = strchr(str, '/');
cd1737
+	if (slash)
cd1737
+		*slash = '\0';
cd1737
+
cd1737
+	ret = get_u16(&flags, str, 16);
cd1737
+	if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
cd1737
+		goto err;
cd1737
+
cd1737
+	addattr16(n, MAX_MSG, flags_type, htons(flags));
cd1737
+
cd1737
+	if (slash) {
cd1737
+		ret = get_u16(&flags, slash + 1, 16);
cd1737
+		if (ret < 0 || flags & ~TCP_FLAGS_MAX_MASK)
cd1737
+			goto err;
cd1737
+	} else {
cd1737
+		flags = TCP_FLAGS_MAX_MASK;
cd1737
+	}
cd1737
+	addattr16(n, MAX_MSG, mask_type, htons(flags));
cd1737
+
cd1737
+	err = 0;
cd1737
+err:
cd1737
+	if (slash)
cd1737
+		*slash = '/';
cd1737
+	return err;
cd1737
+}
cd1737
+
cd1737
 static int flower_parse_key_id(const char *str, int type, struct nlmsghdr *n)
cd1737
 {
cd1737
 	int ret;
cd1737
@@ -671,6 +707,16 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
cd1737
 				fprintf(stderr, "Illegal \"src_port\"\n");
cd1737
 				return -1;
cd1737
 			}
cd1737
+		} else if (matches(*argv, "tcp_flags") == 0) {
cd1737
+			NEXT_ARG();
cd1737
+			ret = flower_parse_tcp_flags(*argv,
cd1737
+						     TCA_FLOWER_KEY_TCP_FLAGS,
cd1737
+						     TCA_FLOWER_KEY_TCP_FLAGS_MASK,
cd1737
+						     n);
cd1737
+			if (ret < 0) {
cd1737
+				fprintf(stderr, "Illegal \"tcp_flags\"\n");
cd1737
+				return -1;
cd1737
+			}
cd1737
 		} else if (matches(*argv, "type") == 0) {
cd1737
 			NEXT_ARG();
cd1737
 			ret = flower_parse_icmp(*argv, eth_type, ip_proto,
cd1737
@@ -1000,6 +1046,19 @@ static void flower_print_port(FILE *f, char *name, struct rtattr *attr)
cd1737
 		fprintf(f, "\n  %s %d", name, rta_getattr_be16(attr));
cd1737
 }
cd1737
 
cd1737
+static void flower_print_tcp_flags(FILE *f, char *name,
cd1737
+				  struct rtattr *flags_attr,
cd1737
+				  struct rtattr *mask_attr)
cd1737
+{
cd1737
+	if (!flags_attr)
cd1737
+		return;
cd1737
+	fprintf(f, "\n  %s %x", name, rta_getattr_be16(flags_attr));
cd1737
+	if (!mask_attr)
cd1737
+		return;
cd1737
+	fprintf(f, "/%x", rta_getattr_be16(mask_attr));
cd1737
+}
cd1737
+
cd1737
+
cd1737
 static void flower_print_key_id(FILE *f, const char *name,
cd1737
 				struct rtattr *attr)
cd1737
 {
cd1737
@@ -1110,6 +1169,9 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
cd1737
 	if (nl_type >= 0)
cd1737
 		flower_print_port(f, "src_port", tb[nl_type]);
cd1737
 
cd1737
+	flower_print_tcp_flags(f, "tcp_flags", tb[TCA_FLOWER_KEY_TCP_FLAGS],
cd1737
+			       tb[TCA_FLOWER_KEY_TCP_FLAGS_MASK]);
cd1737
+
cd1737
 	nl_type = flower_icmp_attr_type(eth_type, ip_proto,
cd1737
 					FLOWER_ICMP_FIELD_TYPE);
cd1737
 	nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
cd1737
-- 
d30c09
2.21.0
cd1737