naccyde / rpms / iproute

Forked from rpms/iproute 9 months ago
Clone

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

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