Blame SOURCES/0139-tc-flower-support-masked-ICMP-code-and-type-match.patch

4aca6e
From aa7beedaa4ac1371c1d08e8afc8d9b6cfd72e22e Mon Sep 17 00:00:00 2001
4aca6e
From: Phil Sutter <psutter@redhat.com>
4aca6e
Date: Fri, 17 Mar 2017 13:25:13 +0100
4aca6e
Subject: [PATCH] tc: flower: support masked ICMP code and type match
4aca6e
4aca6e
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1422629
4aca6e
Upstream Status: iproute2.git commit 6374961a00d4b
4aca6e
4aca6e
commit 6374961a00d4b862bdf87c0f22af86d3ff7d0d67
4aca6e
Author: Simon Horman <simon.horman@netronome.com>
4aca6e
Date:   Thu Feb 9 14:49:01 2017 +0100
4aca6e
4aca6e
    tc: flower: support masked ICMP code and type match
4aca6e
4aca6e
    Extend ICMP code and type match to support masks.
4aca6e
4aca6e
    Also add missing documentation to synopsis in manpage.
4aca6e
4aca6e
    tc qdisc add dev eth0 ingress
4aca6e
    tc filter add dev eth0 protocol ipv6 parent ffff: flower \
4aca6e
            indev eth0 ip_proto icmpv6 type 128/240 code 0 action drop
4aca6e
4aca6e
    Signed-off-by: Simon Horman <simon.horman@netronome.com>
4aca6e
---
4aca6e
 man/man8/tc-flower.8 | 16 ++++++++++----
4aca6e
 tc/f_flower.c        | 59 ++++++++++++++++++++++++++++++----------------------
4aca6e
 2 files changed, 46 insertions(+), 29 deletions(-)
4aca6e
4aca6e
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
4aca6e
index b1bef8b..fc5bac5 100644
4aca6e
--- a/man/man8/tc-flower.8
4aca6e
+++ b/man/man8/tc-flower.8
4aca6e
@@ -34,7 +34,11 @@ flower \- flow based traffic control filter
4aca6e
 .BR dst_ip " | " src_ip " } "
4aca6e
 .IR PREFIX " | { "
4aca6e
 .BR dst_port " | " src_port " } "
4aca6e
-.IR port_number " } | { "
4aca6e
+.IR port_number " } | "
4aca6e
+.B type
4aca6e
+.IR MASKED_TYPE " | "
4aca6e
+.B code
4aca6e
+.IR MASKED_CODE " | { "
4aca6e
 .BR arp_tip " | " arp_sip " } "
4aca6e
 .IR IPV4_PREFIX " | "
4aca6e
 .BR arp_op " { " request " | " reply " | "
4aca6e
@@ -132,10 +136,14 @@ Match on layer 4 protocol source or destination port number. Only available for
4aca6e
 .BR ip_proto " values " udp ", " tcp  " and " sctp
4aca6e
 which have to be specified in beforehand.
4aca6e
 .TP
4aca6e
-.BI type " NUMBER"
4aca6e
+.BI type " MASKED_TYPE"
4aca6e
 .TQ
4aca6e
-.BI code " NUMBER"
4aca6e
-Match on ICMP type or code. Only available for
4aca6e
+.BI code " MASKED_CODE"
4aca6e
+Match on ICMP type or code. A mask may be optionally provided to limit the
4aca6e
+bits of the address which are matched. A mask is provided by following the
4aca6e
+address with a slash and then the mask. The mask must be as a number which
4aca6e
+represents a bitwise mask If the mask is missing then a match on all bits
4aca6e
+is assumed.  Only available for
4aca6e
 .BR ip_proto " values " icmp  " and " icmpv6
4aca6e
 which have to be specified in beforehand.
4aca6e
 .TP
4aca6e
diff --git a/tc/f_flower.c b/tc/f_flower.c
4aca6e
index 9c13e53..e9d3a96 100644
4aca6e
--- a/tc/f_flower.c
4aca6e
+++ b/tc/f_flower.c
4aca6e
@@ -57,8 +57,8 @@ static void explain(void)
4aca6e
 		"                       src_ip PREFIX |\n"
4aca6e
 		"                       dst_port PORT-NUMBER |\n"
4aca6e
 		"                       src_port PORT-NUMBER |\n"
4aca6e
-		"                       type ICMP-TYPE |\n"
4aca6e
-		"                       code ICMP-CODE |\n"
4aca6e
+		"                       type MASKED-ICMP-TYPE |\n"
4aca6e
+		"                       code MASKED-ICMP-CODE |\n"
4aca6e
 		"                       arp_tip IPV4-PREFIX |\n"
4aca6e
 		"                       arp_sip IPV4-PREFIX |\n"
4aca6e
 		"                       arp_op [ request | reply | OP ] |\n"
4aca6e
@@ -407,24 +407,32 @@ static int flower_icmp_attr_type(__be16 eth_type, __u8 ip_proto,
4aca6e
 	return -1;
4aca6e
 }
4aca6e
 
4aca6e
+static int flower_icmp_attr_mask_type(__be16 eth_type, __u8 ip_proto,
4aca6e
+				      enum flower_icmp_field field)
4aca6e
+{
4aca6e
+	if (eth_type == htons(ETH_P_IP) && ip_proto == IPPROTO_ICMP)
4aca6e
+		return field == FLOWER_ICMP_FIELD_CODE ?
4aca6e
+			TCA_FLOWER_KEY_ICMPV4_CODE_MASK :
4aca6e
+			TCA_FLOWER_KEY_ICMPV4_TYPE_MASK;
4aca6e
+	else if (eth_type == htons(ETH_P_IPV6) && ip_proto == IPPROTO_ICMPV6)
4aca6e
+		return field == FLOWER_ICMP_FIELD_CODE ?
4aca6e
+			TCA_FLOWER_KEY_ICMPV6_CODE_MASK :
4aca6e
+			TCA_FLOWER_KEY_ICMPV6_TYPE_MASK;
4aca6e
+
4aca6e
+	return -1;
4aca6e
+}
4aca6e
+
4aca6e
 static int flower_parse_icmp(char *str, __u16 eth_type, __u8 ip_proto,
4aca6e
 			     enum flower_icmp_field field, struct nlmsghdr *n)
4aca6e
 {
4aca6e
-	int ret;
4aca6e
-	int type;
4aca6e
-	uint8_t value;
4aca6e
-
4aca6e
-	type = flower_icmp_attr_type(eth_type, ip_proto, field);
4aca6e
-	if (type < 0)
4aca6e
-		return -1;
4aca6e
+	int value_type, mask_type;
4aca6e
 
4aca6e
-	ret = get_u8(&value, str, 10);
4aca6e
-	if (ret)
4aca6e
+	value_type = flower_icmp_attr_type(eth_type, ip_proto, field);
4aca6e
+	mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto, field);
4aca6e
+	if (value_type < 0 || mask_type < 0)
4aca6e
 		return -1;
4aca6e
 
4aca6e
-	addattr8(n, MAX_MSG, type, value);
4aca6e
-
4aca6e
-	return 0;
4aca6e
+	return flower_parse_u8(str, value_type, mask_type, NULL, NULL, n);
4aca6e
 }
4aca6e
 
4aca6e
 static int flower_port_attr_type(__u8 ip_proto, enum flower_endpoint endpoint)
4aca6e
@@ -1000,12 +1008,6 @@ static void flower_print_key_id(FILE *f, const char *name,
4aca6e
 		fprintf(f, "\n  %s %d", name, rta_getattr_be32(attr));
4aca6e
 }
4aca6e
 
4aca6e
-static void flower_print_icmp(FILE *f, char *name, struct rtattr *attr)
4aca6e
-{
4aca6e
-	if (attr)
4aca6e
-		fprintf(f, "\n  %s %d", name, rta_getattr_u8(attr));
4aca6e
-}
4aca6e
-
4aca6e
 static void flower_print_masked_u8(FILE *f, const char *name,
4aca6e
 				   struct rtattr *attr,
4aca6e
 				   struct rtattr *mask_attr,
4aca6e
@@ -1045,9 +1047,9 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
4aca6e
 			    struct rtattr *opt, __u32 handle)
4aca6e
 {
4aca6e
 	struct rtattr *tb[TCA_FLOWER_MAX + 1];
4aca6e
+	int nl_type, nl_mask_type;
4aca6e
 	__be16 eth_type = 0;
4aca6e
 	__u8 ip_proto = 0xff;
4aca6e
-	int nl_type;
4aca6e
 
4aca6e
 	if (!opt)
4aca6e
 		return 0;
4aca6e
@@ -1111,12 +1113,19 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
4aca6e
 
4aca6e
 	nl_type = flower_icmp_attr_type(eth_type, ip_proto,
4aca6e
 					FLOWER_ICMP_FIELD_TYPE);
4aca6e
-	if (nl_type >= 0)
4aca6e
-		flower_print_icmp(f, "icmp_type", tb[nl_type]);
4aca6e
+	nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
4aca6e
+						  FLOWER_ICMP_FIELD_TYPE);
4aca6e
+	if (nl_type >= 0 && nl_mask_type >= 0)
4aca6e
+		flower_print_masked_u8(f, "icmp_type", tb[nl_type],
4aca6e
+				       tb[nl_mask_type], NULL);
4aca6e
+
4aca6e
 	nl_type = flower_icmp_attr_type(eth_type, ip_proto,
4aca6e
 					FLOWER_ICMP_FIELD_CODE);
4aca6e
-	if (nl_type >= 0)
4aca6e
-		flower_print_icmp(f, "icmp_code", tb[nl_type]);
4aca6e
+	nl_mask_type = flower_icmp_attr_mask_type(eth_type, ip_proto,
4aca6e
+						  FLOWER_ICMP_FIELD_CODE);
4aca6e
+	if (nl_type >= 0 && nl_mask_type >= 0)
4aca6e
+		flower_print_masked_u8(f, "icmp_code", tb[nl_type],
4aca6e
+				       tb[nl_mask_type], NULL);
4aca6e
 
4aca6e
 	flower_print_ip4_addr(f, "arp_sip", tb[TCA_FLOWER_KEY_ARP_SIP],
4aca6e
 			     tb[TCA_FLOWER_KEY_ARP_SIP_MASK]);
4aca6e
-- 
4aca6e
1.8.3.1
4aca6e