naccyde / rpms / iproute

Forked from rpms/iproute 9 months ago
Clone

Blame SOURCES/0109-tc-flower-Introduce-vlan-support.patch

4aca6e
From 54549fa07c9ad748ffa9ecf6865c12641cd71329 Mon Sep 17 00:00:00 2001
4aca6e
From: Phil Sutter <psutter@redhat.com>
4aca6e
Date: Fri, 17 Mar 2017 13:21:33 +0100
4aca6e
Subject: [PATCH] tc: flower: Introduce vlan support
4aca6e
4aca6e
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1422629
4aca6e
Upstream Status: iproute2.git commit 745d91726006f
4aca6e
Conflicts: Context changes due to missing commit 32a121cba2579
4aca6e
           ("tc: code cleanup").
4aca6e
4aca6e
commit 745d91726006fcaa9006f491f9a596c4025cecf7
4aca6e
Author: Hadar Hen Zion <hadarh@mellanox.com>
4aca6e
Date:   Thu Sep 1 09:45:47 2016 +0300
4aca6e
4aca6e
    tc: flower: Introduce vlan support
4aca6e
4aca6e
    Classification according to vlan id and vlan priority.
4aca6e
4aca6e
    Example script that adds vlan filter:
4aca6e
4aca6e
     # add ingress qdisc
4aca6e
     tc qdisc add dev ens4f0 ingress
4aca6e
4aca6e
     # add a flower filter with vlan id and priority classification
4aca6e
     tc filter add dev ens4f0 protocol 802.1Q parent ffff: \
4aca6e
            flower \
4aca6e
                    indev ens4f0 \
4aca6e
                    vlan_ethtype ipv4 \
4aca6e
                    vlan_id 100 \
4aca6e
                    vlan_prio 3 \
4aca6e
            action vlan pop
4aca6e
4aca6e
    Signed-off-by: Hadar Hen Zion <hadarh@mellanox.com>
4aca6e
    Acked-by: Jiri Pirko <jiri@mellanox.com>
4aca6e
---
4aca6e
 man/man8/tc-flower.8 | 25 ++++++++++++++++-
4aca6e
 tc/f_flower.c        | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--
4aca6e
 2 files changed, 99 insertions(+), 4 deletions(-)
4aca6e
4aca6e
diff --git a/man/man8/tc-flower.8 b/man/man8/tc-flower.8
4aca6e
index 9ae10e6..74f7664 100644
4aca6e
--- a/man/man8/tc-flower.8
4aca6e
+++ b/man/man8/tc-flower.8
4aca6e
@@ -23,7 +23,13 @@ flower \- flow based traffic control filter
4aca6e
 .R " | { "
4aca6e
 .BR dst_mac " | " src_mac " } "
4aca6e
 .IR mac_address " | "
4aca6e
-.BR eth_type " { " ipv4 " | " ipv6 " | "
4aca6e
+.BR eth_type " { " ipv4 " | " ipv6 " | " 802.1Q " | "
4aca6e
+.IR ETH_TYPE " } | "
4aca6e
+.B vlan_id
4aca6e
+.IR VID " | "
4aca6e
+.B vlan_prio
4aca6e
+.IR PRIORITY " | "
4aca6e
+.BR vlan_eth_type " { " ipv4 " | " ipv6 " | "
4aca6e
 .IR ETH_TYPE " } | "
4aca6e
 .BR ip_proto " { " tcp " | " udp " | "
4aca6e
 .IR IP_PROTO " } | { "
4aca6e
@@ -70,6 +76,23 @@ Do not process filter by hardware.
4aca6e
 Match on source or destination MAC address.
4aca6e
 .TP
4aca6e
 .BI eth_type " ETH_TYPE"
4aca6e
+Match on the next protocol.
4aca6e
+.I ETH_TYPE
4aca6e
+may be either
4aca6e
+.BR ipv4 , ipv6 , 802.1Q ,
4aca6e
+or an unsigned 16bit value in hexadecimal format.
4aca6e
+.TP
4aca6e
+.BI vlan_id " VID"
4aca6e
+Match on vlan tag id.
4aca6e
+.I VID
4aca6e
+is an unsigned 12bit value in decimal format.
4aca6e
+.TP
4aca6e
+.BI vlan_prio " priority"
4aca6e
+Match on vlan tag priority.
4aca6e
+.I PRIORITY
4aca6e
+is an unsigned 3bit value in decimal format.
4aca6e
+.TP
4aca6e
+.BI vlan_eth_type " VLAN_ETH_TYPE"
4aca6e
 Match on layer three protocol.
4aca6e
 .I ETH_TYPE
4aca6e
 may be either
4aca6e
diff --git a/tc/f_flower.c b/tc/f_flower.c
4aca6e
index 01527c8..dec7d9d 100644
4aca6e
--- a/tc/f_flower.c
4aca6e
+++ b/tc/f_flower.c
4aca6e
@@ -17,6 +17,7 @@
4aca6e
 #include <net/if.h>
4aca6e
 #include <linux/if_ether.h>
4aca6e
 #include <linux/ip.h>
4aca6e
+#include <linux/tc_act/tc_vlan.h>
4aca6e
 
4aca6e
 #include "utils.h"
4aca6e
 #include "tc_util.h"
4aca6e
@@ -30,6 +31,9 @@ static void explain(void)
4aca6e
 	fprintf(stderr, "\n");
4aca6e
 	fprintf(stderr, "Where: MATCH-LIST := [ MATCH-LIST ] MATCH\n");
4aca6e
 	fprintf(stderr, "       MATCH      := { indev DEV-NAME | \n");
4aca6e
+	fprintf(stderr, "                       vlan_id VID |\n");
4aca6e
+	fprintf(stderr, "                       vlan_prio PRIORITY |\n");
4aca6e
+	fprintf(stderr, "                       vlan_ethtype [ ipv4 | ipv6 | ETH-TYPE ] |\n");
4aca6e
 	fprintf(stderr, "                       dst_mac MAC-ADDR | \n");
4aca6e
 	fprintf(stderr, "                       src_mac MAC-ADDR | \n");
4aca6e
 	fprintf(stderr, "                       [ipv4 | ipv6 ] | \n");
4aca6e
@@ -61,6 +65,23 @@ static int flower_parse_eth_addr(char *str, int addr_type, int mask_type,
4aca6e
 	return 0;
4aca6e
 }
4aca6e
 
4aca6e
+static int flower_parse_vlan_eth_type(char *str, __be16 eth_type, int type,
4aca6e
+				      __be16 *p_vlan_eth_type, struct nlmsghdr *n)
4aca6e
+{
4aca6e
+	__be16 vlan_eth_type;
4aca6e
+
4aca6e
+	if (eth_type != htons(ETH_P_8021Q)) {
4aca6e
+		fprintf(stderr, "Can't set \"vlan_ethtype\" if ethertype isn't 802.1Q\n");
4aca6e
+		return -1;
4aca6e
+	}
4aca6e
+
4aca6e
+	if (ll_proto_a2n(&vlan_eth_type, str))
4aca6e
+		invarg("invalid vlan_ethtype", str);
4aca6e
+	addattr16(n, MAX_MSG, type, vlan_eth_type);
4aca6e
+	*p_vlan_eth_type = vlan_eth_type;
4aca6e
+	return 0;
4aca6e
+}
4aca6e
+
4aca6e
 static int flower_parse_ip_proto(char *str, __be16 eth_type, int type,
4aca6e
 				 __u8 *p_ip_proto, struct nlmsghdr *n)
4aca6e
 {
4aca6e
@@ -167,6 +188,7 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
4aca6e
 	struct tcmsg *t = NLMSG_DATA(n);
4aca6e
 	struct rtattr *tail;
4aca6e
 	__be16 eth_type = TC_H_MIN(t->tcm_info);
4aca6e
+	__be16 vlan_ethtype = 0;
4aca6e
 	__u8 ip_proto = 0xff;
4aca6e
 	__u32 flags = 0;
4aca6e
 
4aca6e
@@ -209,6 +231,41 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
4aca6e
 			memset(ifname, 0, sizeof(ifname));
4aca6e
 			strncpy(ifname, *argv, sizeof(ifname) - 1);
4aca6e
 			addattrstrz(n, MAX_MSG, TCA_FLOWER_INDEV, ifname);
4aca6e
+		} else if (matches(*argv, "vlan_id") == 0) {
4aca6e
+			__u16 vid;
4aca6e
+
4aca6e
+			NEXT_ARG();
4aca6e
+			if (eth_type != htons(ETH_P_8021Q)) {
4aca6e
+				fprintf(stderr, "Can't set \"vlan_id\" if ethertype isn't 802.1Q\n");
4aca6e
+				return -1;
4aca6e
+			}
4aca6e
+			ret = get_u16(&vid, *argv, 10);
4aca6e
+			if (ret < 0 || vid & ~0xfff) {
4aca6e
+				fprintf(stderr, "Illegal \"vlan_id\"\n");
4aca6e
+				return -1;
4aca6e
+			}
4aca6e
+			addattr16(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_ID, vid);
4aca6e
+		} else if (matches(*argv, "vlan_prio") == 0) {
4aca6e
+			__u8 vlan_prio;
4aca6e
+
4aca6e
+			NEXT_ARG();
4aca6e
+			if (eth_type != htons(ETH_P_8021Q)) {
4aca6e
+				fprintf(stderr, "Can't set \"vlan_prio\" if ethertype isn't 802.1Q\n");
4aca6e
+				return -1;
4aca6e
+			}
4aca6e
+			ret = get_u8(&vlan_prio, *argv, 10);
4aca6e
+			if (ret < 0 || vlan_prio & ~0x7) {
4aca6e
+				fprintf(stderr, "Illegal \"vlan_prio\"\n");
4aca6e
+				return -1;
4aca6e
+			}
4aca6e
+			addattr8(n, MAX_MSG, TCA_FLOWER_KEY_VLAN_PRIO, vlan_prio);
4aca6e
+		} else if (matches(*argv, "vlan_ethtype") == 0) {
4aca6e
+			NEXT_ARG();
4aca6e
+			ret = flower_parse_vlan_eth_type(*argv, eth_type,
4aca6e
+							 TCA_FLOWER_KEY_VLAN_ETH_TYPE,
4aca6e
+							 &vlan_ethtype, n);
4aca6e
+			if (ret < 0)
4aca6e
+				return -1;
4aca6e
 		} else if (matches(*argv, "dst_mac") == 0) {
4aca6e
 			NEXT_ARG();
4aca6e
 			ret = flower_parse_eth_addr(*argv,
4aca6e
@@ -231,7 +288,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
4aca6e
 			}
4aca6e
 		} else if (matches(*argv, "ip_proto") == 0) {
4aca6e
 			NEXT_ARG();
4aca6e
-			ret = flower_parse_ip_proto(*argv, eth_type,
4aca6e
+			ret = flower_parse_ip_proto(*argv, vlan_ethtype ?
4aca6e
+						    vlan_ethtype : eth_type,
4aca6e
 						    TCA_FLOWER_KEY_IP_PROTO,
4aca6e
 						    &ip_proto, n);
4aca6e
 			if (ret < 0) {
4aca6e
@@ -240,7 +298,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
4aca6e
 			}
4aca6e
 		} else if (matches(*argv, "dst_ip") == 0) {
4aca6e
 			NEXT_ARG();
4aca6e
-			ret = flower_parse_ip_addr(*argv, eth_type,
4aca6e
+			ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
4aca6e
+						   vlan_ethtype : eth_type,
4aca6e
 						   TCA_FLOWER_KEY_IPV4_DST,
4aca6e
 						   TCA_FLOWER_KEY_IPV4_DST_MASK,
4aca6e
 						   TCA_FLOWER_KEY_IPV6_DST,
4aca6e
@@ -252,7 +311,8 @@ static int flower_parse_opt(struct filter_util *qu, char *handle,
4aca6e
 			}
4aca6e
 		} else if (matches(*argv, "src_ip") == 0) {
4aca6e
 			NEXT_ARG();
4aca6e
-			ret = flower_parse_ip_addr(*argv, eth_type,
4aca6e
+			ret = flower_parse_ip_addr(*argv, vlan_ethtype ?
4aca6e
+						   vlan_ethtype : eth_type,
4aca6e
 						   TCA_FLOWER_KEY_IPV4_SRC,
4aca6e
 						   TCA_FLOWER_KEY_IPV4_SRC_MASK,
4aca6e
 						   TCA_FLOWER_KEY_IPV6_SRC,
4aca6e
@@ -478,6 +538,18 @@ static int flower_print_opt(struct filter_util *qu, FILE *f,
4aca6e
 		fprintf(f, "\n  indev %s", rta_getattr_str(attr));
4aca6e
 	}
4aca6e
 
4aca6e
+	if (tb[TCA_FLOWER_KEY_VLAN_ID]) {
4aca6e
+		struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_ID];
4aca6e
+
4aca6e
+		fprintf(f, "\n  vlan_id %d", rta_getattr_u16(attr));
4aca6e
+	}
4aca6e
+
4aca6e
+	if (tb[TCA_FLOWER_KEY_VLAN_PRIO]) {
4aca6e
+		struct rtattr *attr = tb[TCA_FLOWER_KEY_VLAN_PRIO];
4aca6e
+
4aca6e
+		fprintf(f, "\n  vlan_prio %d", rta_getattr_u8(attr));
4aca6e
+	}
4aca6e
+
4aca6e
 	flower_print_eth_addr(f, "dst_mac", tb[TCA_FLOWER_KEY_ETH_DST],
4aca6e
 			      tb[TCA_FLOWER_KEY_ETH_DST_MASK]);
4aca6e
 	flower_print_eth_addr(f, "src_mac", tb[TCA_FLOWER_KEY_ETH_SRC],
4aca6e
-- 
4aca6e
1.8.3.1
4aca6e