naccyde / rpms / iproute

Forked from rpms/iproute 7 months ago
Clone

Blame SOURCES/0003-m_vlan-add-pop_eth-and-push_eth-actions.patch

2f28bf
From cac52dd831b6982f6b27b02c26243edbe0b7d747 Mon Sep 17 00:00:00 2001
2f28bf
Message-Id: <cac52dd831b6982f6b27b02c26243edbe0b7d747.1611877215.git.aclaudi@redhat.com>
2f28bf
In-Reply-To: <cb7ce51cc1abd7b98370b903ec96205ebfe48661.1611877215.git.aclaudi@redhat.com>
2f28bf
References: <cb7ce51cc1abd7b98370b903ec96205ebfe48661.1611877215.git.aclaudi@redhat.com>
2f28bf
From: Andrea Claudi <aclaudi@redhat.com>
2f28bf
Date: Fri, 29 Jan 2021 00:35:03 +0100
2f28bf
Subject: [PATCH] m_vlan: add pop_eth and push_eth actions
2f28bf
2f28bf
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1885770
2f28bf
Upstream Status: unknown commit d61167dd
2f28bf
2f28bf
commit d61167dd88b45832843b1458cd156f3b85c8ff16
2f28bf
Author: Guillaume Nault <gnault@redhat.com>
2f28bf
Date:   Mon Oct 19 17:23:01 2020 +0200
2f28bf
2f28bf
    m_vlan: add pop_eth and push_eth actions
2f28bf
2f28bf
    Add support for the new TCA_VLAN_ACT_POP_ETH and TCA_VLAN_ACT_PUSH_ETH
2f28bf
    actions (kernel commit 19fbcb36a39e ("net/sched: act_vlan:
2f28bf
    Add {POP,PUSH}_ETH actions"). These action let TC remove or add the
2f28bf
    Ethernet at the head of a frame.
2f28bf
2f28bf
    Drop an Ethernet header:
2f28bf
     # tc filter add dev ethX matchall action vlan pop_eth
2f28bf
2f28bf
    Push an Ethernet header (the original frame must have no MAC header):
2f28bf
     # tc filter add dev ethX matchall action vlan \
2f28bf
           push_eth dst_mac 0a:00:00:00:00:02 src_mac 0a:00:00:00:00:01
2f28bf
2f28bf
    Also add a test suite for m_vlan, which covers these new actions and
2f28bf
    the pre-existing ones.
2f28bf
2f28bf
    Signed-off-by: Guillaume Nault <gnault@redhat.com>
2f28bf
    Signed-off-by: David Ahern <dsahern@gmail.com>
2f28bf
---
2f28bf
 man/man8/tc-vlan.8        | 39 +++++++++++++++++-
2f28bf
 tc/m_vlan.c               | 69 +++++++++++++++++++++++++++++++
2f28bf
 testsuite/tests/tc/vlan.t | 86 +++++++++++++++++++++++++++++++++++++++
2f28bf
 3 files changed, 192 insertions(+), 2 deletions(-)
2f28bf
 create mode 100755 testsuite/tests/tc/vlan.t
2f28bf
2f28bf
diff --git a/man/man8/tc-vlan.8 b/man/man8/tc-vlan.8
2f28bf
index f5ffc25f..5c2808b1 100644
2f28bf
--- a/man/man8/tc-vlan.8
2f28bf
+++ b/man/man8/tc-vlan.8
2f28bf
@@ -5,8 +5,8 @@ vlan - vlan manipulation module
2f28bf
 .SH SYNOPSIS
2f28bf
 .in +8
2f28bf
 .ti -8
2f28bf
-.BR tc " ... " "action vlan" " { " pop " |"
2f28bf
-.IR PUSH " | " MODIFY " } [ " CONTROL " ]"
2f28bf
+.BR tc " ... " "action vlan" " { " pop " | " pop_eth " |"
2f28bf
+.IR PUSH " | " MODIFY " | " PUSH_ETH " } [ " CONTROL " ]"
2f28bf
 
2f28bf
 .ti -8
2f28bf
 .IR PUSH " := "
2f28bf
@@ -24,6 +24,11 @@ vlan - vlan manipulation module
2f28bf
 .IR VLANPRIO " ] "
2f28bf
 .BI id " VLANID"
2f28bf
 
2f28bf
+.ti -8
2f28bf
+.IR PUSH_ETH " := "
2f28bf
+.B push_eth
2f28bf
+.BI dst_mac " LLADDR " src_mac " LLADDR "
2f28bf
+
2f28bf
 .ti -8
2f28bf
 .IR CONTROL " := { "
2f28bf
 .BR reclassify " | " pipe " | " drop " | " continue " | " pass " | " goto " " chain " " CHAIN_INDEX " }"
2f28bf
@@ -43,6 +48,20 @@ modes require at least a
2f28bf
 and allow to optionally choose the
2f28bf
 .I VLANPROTO
2f28bf
 to use.
2f28bf
+
2f28bf
+The
2f28bf
+.B vlan
2f28bf
+action can also be used to add or remove the base Ethernet header. The
2f28bf
+.B pop_eth
2f28bf
+mode, which takes no argument, is used to remove the base Ethernet header. All
2f28bf
+existing VLANs must have been previously dropped. The opposite operation,
2f28bf
+adding a base Ethernet header, is done with the
2f28bf
+.B push_eth
2f28bf
+mode. In that case, the packet must have no MAC header (stacking MAC headers is
2f28bf
+not permitted). This mode is mostly useful when a previous action has
2f28bf
+encapsulated the whole original frame behind a network header and one needs
2f28bf
+to prepend an Ethernet header before forwarding the resulting packet.
2f28bf
+
2f28bf
 .SH OPTIONS
2f28bf
 .TP
2f28bf
 .B pop
2f28bf
@@ -58,6 +77,16 @@ Replace mode. Existing 802.1Q tag is replaced. Requires at least
2f28bf
 .B id
2f28bf
 option.
2f28bf
 .TP
2f28bf
+.B pop_eth
2f28bf
+Ethernet header decapsulation mode. Only works on a plain Ethernet header:
2f28bf
+VLANs, if any, must be removed first.
2f28bf
+.TP
2f28bf
+.B push_eth
2f28bf
+Ethernet header encapsulation mode. The Ethertype is automatically set
2f28bf
+using the network header type. Chaining Ethernet headers is not allowed: the
2f28bf
+packet must have no MAC header when using this mode. Requires the
2f28bf
+.BR "dst_mac " and " src_mac " options.
2f28bf
+.TP
2f28bf
 .BI id " VLANID"
2f28bf
 Specify the VLAN ID to encapsulate into.
2f28bf
 .I VLANID
2f28bf
@@ -73,6 +102,12 @@ Choose the VLAN protocol to use. At the time of writing, the kernel accepts only
2f28bf
 .BI priority " VLANPRIO"
2f28bf
 Choose the VLAN priority to use. Decimal number in range of 0-7.
2f28bf
 .TP
2f28bf
+.BI dst_mac " LLADDR"
2f28bf
+Choose the destination MAC address to use.
2f28bf
+.TP
2f28bf
+.BI src_mac " LLADDR"
2f28bf
+Choose the source MAC address to use.
2f28bf
+.TP
2f28bf
 .I CONTROL
2f28bf
 How to continue after executing this action.
2f28bf
 .RS
2f28bf
diff --git a/tc/m_vlan.c b/tc/m_vlan.c
2f28bf
index 1096ba0f..e6b21330 100644
2f28bf
--- a/tc/m_vlan.c
2f28bf
+++ b/tc/m_vlan.c
2f28bf
@@ -23,6 +23,8 @@ static const char * const action_names[] = {
2f28bf
 	[TCA_VLAN_ACT_POP] = "pop",
2f28bf
 	[TCA_VLAN_ACT_PUSH] = "push",
2f28bf
 	[TCA_VLAN_ACT_MODIFY] = "modify",
2f28bf
+	[TCA_VLAN_ACT_POP_ETH] = "pop_eth",
2f28bf
+	[TCA_VLAN_ACT_PUSH_ETH] = "push_eth",
2f28bf
 };
2f28bf
 
2f28bf
 static void explain(void)
2f28bf
@@ -31,6 +33,8 @@ static void explain(void)
2f28bf
 		"Usage: vlan pop\n"
2f28bf
 		"       vlan push [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
2f28bf
 		"       vlan modify [ protocol VLANPROTO ] id VLANID [ priority VLANPRIO ] [CONTROL]\n"
2f28bf
+		"       vlan pop_eth [CONTROL]\n"
2f28bf
+		"       vlan push_eth dst_mac LLADDR src_mac LLADDR [CONTROL]\n"
2f28bf
 		"       VLANPROTO is one of 802.1Q or 802.1AD\n"
2f28bf
 		"            with default: 802.1Q\n"
2f28bf
 		"       CONTROL := reclassify | pipe | drop | continue | pass |\n"
2f28bf
@@ -63,6 +67,10 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 	char **argv = *argv_p;
2f28bf
 	struct rtattr *tail;
2f28bf
 	int action = 0;
2f28bf
+	char dst_mac[ETH_ALEN] = {};
2f28bf
+	int dst_mac_set = 0;
2f28bf
+	char src_mac[ETH_ALEN] = {};
2f28bf
+	int src_mac_set = 0;
2f28bf
 	__u16 id;
2f28bf
 	int id_set = 0;
2f28bf
 	__u16 proto;
2f28bf
@@ -95,6 +103,18 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 				return -1;
2f28bf
 			}
2f28bf
 			action = TCA_VLAN_ACT_MODIFY;
2f28bf
+		} else if (matches(*argv, "pop_eth") == 0) {
2f28bf
+			if (action) {
2f28bf
+				unexpected(*argv);
2f28bf
+				return -1;
2f28bf
+			}
2f28bf
+			action = TCA_VLAN_ACT_POP_ETH;
2f28bf
+		} else if (matches(*argv, "push_eth") == 0) {
2f28bf
+			if (action) {
2f28bf
+				unexpected(*argv);
2f28bf
+				return -1;
2f28bf
+			}
2f28bf
+			action = TCA_VLAN_ACT_PUSH_ETH;
2f28bf
 		} else if (matches(*argv, "id") == 0) {
2f28bf
 			if (!has_push_attribs(action))
2f28bf
 				invarg("only valid for push/modify", *argv);
2f28bf
@@ -119,6 +139,22 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 			if (get_u8(&prio, *argv, 0) || (prio & ~0x7))
2f28bf
 				invarg("prio is invalid", *argv);
2f28bf
 			prio_set = 1;
2f28bf
+		} else if (matches(*argv, "dst_mac") == 0) {
2f28bf
+			if (action != TCA_VLAN_ACT_PUSH_ETH)
2f28bf
+				invarg("only valid for push_eth", *argv);
2f28bf
+
2f28bf
+			NEXT_ARG();
2f28bf
+			if (ll_addr_a2n(dst_mac, sizeof(dst_mac), *argv) < 0)
2f28bf
+				invarg("dst_mac is invalid", *argv);
2f28bf
+			dst_mac_set = 1;
2f28bf
+		} else if (matches(*argv, "src_mac") == 0) {
2f28bf
+			if (action != TCA_VLAN_ACT_PUSH_ETH)
2f28bf
+				invarg("only valid for push_eth", *argv);
2f28bf
+
2f28bf
+			NEXT_ARG();
2f28bf
+			if (ll_addr_a2n(src_mac, sizeof(src_mac), *argv) < 0)
2f28bf
+				invarg("src_mac is invalid", *argv);
2f28bf
+			src_mac_set = 1;
2f28bf
 		} else if (matches(*argv, "help") == 0) {
2f28bf
 			usage();
2f28bf
 		} else {
2f28bf
@@ -150,6 +186,20 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 		return -1;
2f28bf
 	}
2f28bf
 
2f28bf
+	if (action == TCA_VLAN_ACT_PUSH_ETH) {
2f28bf
+		if (!dst_mac_set) {
2f28bf
+			fprintf(stderr, "dst_mac needs to be set for %s\n",
2f28bf
+				action_names[action]);
2f28bf
+			explain();
2f28bf
+			return -1;
2f28bf
+		} else if (!src_mac_set) {
2f28bf
+			fprintf(stderr, "src_mac needs to be set for %s\n",
2f28bf
+				action_names[action]);
2f28bf
+			explain();
2f28bf
+			return -1;
2f28bf
+		}
2f28bf
+	}
2f28bf
+
2f28bf
 	parm.v_action = action;
2f28bf
 	tail = addattr_nest(n, MAX_MSG, tca_id);
2f28bf
 	addattr_l(n, MAX_MSG, TCA_VLAN_PARMS, &parm, sizeof(parm));
2f28bf
@@ -167,6 +217,12 @@ static int parse_vlan(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 	}
2f28bf
 	if (prio_set)
2f28bf
 		addattr8(n, MAX_MSG, TCA_VLAN_PUSH_VLAN_PRIORITY, prio);
2f28bf
+	if (dst_mac_set)
2f28bf
+		addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_ETH_DST, dst_mac,
2f28bf
+			  sizeof(dst_mac));
2f28bf
+	if (src_mac_set)
2f28bf
+		addattr_l(n, MAX_MSG, TCA_VLAN_PUSH_ETH_SRC, src_mac,
2f28bf
+			  sizeof(src_mac));
2f28bf
 
2f28bf
 	addattr_nest_end(n, tail);
2f28bf
 
2f28bf
@@ -216,6 +272,19 @@ static int print_vlan(struct action_util *au, FILE *f, struct rtattr *arg)
2f28bf
 			print_uint(PRINT_ANY, "priority", " priority %u", val);
2f28bf
 		}
2f28bf
 		break;
2f28bf
+	case TCA_VLAN_ACT_PUSH_ETH:
2f28bf
+		if (tb[TCA_VLAN_PUSH_ETH_DST] &&
2f28bf
+		    RTA_PAYLOAD(tb[TCA_VLAN_PUSH_ETH_DST]) == ETH_ALEN) {
2f28bf
+			ll_addr_n2a(RTA_DATA(tb[TCA_VLAN_PUSH_ETH_DST]),
2f28bf
+				    ETH_ALEN, 0, b1, sizeof(b1));
2f28bf
+			print_string(PRINT_ANY, "dst_mac", " dst_mac %s", b1);
2f28bf
+		}
2f28bf
+		if (tb[TCA_VLAN_PUSH_ETH_SRC &&
2f28bf
+		       RTA_PAYLOAD(tb[TCA_VLAN_PUSH_ETH_SRC]) == ETH_ALEN]) {
2f28bf
+			ll_addr_n2a(RTA_DATA(tb[TCA_VLAN_PUSH_ETH_SRC]),
2f28bf
+				    ETH_ALEN, 0, b1, sizeof(b1));
2f28bf
+			print_string(PRINT_ANY, "src_mac", " src_mac %s", b1);
2f28bf
+		}
2f28bf
 	}
2f28bf
 	print_action_control(f, " ", parm->action, "");
2f28bf
 
2f28bf
diff --git a/testsuite/tests/tc/vlan.t b/testsuite/tests/tc/vlan.t
2f28bf
new file mode 100755
2f28bf
index 00000000..b86dc364
2f28bf
--- /dev/null
2f28bf
+++ b/testsuite/tests/tc/vlan.t
2f28bf
@@ -0,0 +1,86 @@
2f28bf
+#!/bin/sh
2f28bf
+
2f28bf
+. lib/generic.sh
2f28bf
+
2f28bf
+DEV="$(rand_dev)"
2f28bf
+ts_ip "$0" "Add $DEV dummy interface" link add dev $DEV up type dummy
2f28bf
+ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress
2f28bf
+
2f28bf
+reset_qdisc()
2f28bf
+{
2f28bf
+	ts_tc "$0" "Remove ingress qdisc" qdisc del dev $DEV ingress
2f28bf
+	ts_tc "$0" "Add ingress qdisc" qdisc add dev $DEV ingress
2f28bf
+}
2f28bf
+
2f28bf
+ts_tc "$0" "Add vlan action pop" \
2f28bf
+	filter add dev $DEV ingress matchall action vlan pop
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "pop"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action push (default parameters)" \
2f28bf
+	filter add dev $DEV ingress matchall action vlan push id 5
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "push"
2f28bf
+test_on "id 5"
2f28bf
+test_on "protocol 802.1Q"
2f28bf
+test_on "priority 0"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action push (explicit parameters)" \
2f28bf
+	filter add dev $DEV ingress matchall            \
2f28bf
+	action vlan push id 5 protocol 802.1ad priority 2
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "push"
2f28bf
+test_on "id 5"
2f28bf
+test_on "protocol 802.1ad"
2f28bf
+test_on "priority 2"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action modify (default parameters)" \
2f28bf
+	filter add dev $DEV ingress matchall action vlan modify id 5
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "modify"
2f28bf
+test_on "id 5"
2f28bf
+test_on "protocol 802.1Q"
2f28bf
+test_on "priority 0"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action modify (explicit parameters)" \
2f28bf
+	filter add dev $DEV ingress matchall              \
2f28bf
+	action vlan modify id 5 protocol 802.1ad priority 2
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "modify"
2f28bf
+test_on "id 5"
2f28bf
+test_on "protocol 802.1ad"
2f28bf
+test_on "priority 2"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action pop_eth" \
2f28bf
+	filter add dev $DEV ingress matchall action vlan pop_eth
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "pop_eth"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add vlan action push_eth"                  \
2f28bf
+	filter add dev $DEV ingress matchall           \
2f28bf
+	action vlan push_eth dst_mac 02:00:00:00:00:02 \
2f28bf
+	src_mac 02:00:00:00:00:01
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "vlan"
2f28bf
+test_on "push_eth"
2f28bf
+test_on "dst_mac 02:00:00:00:00:02"
2f28bf
+test_on "src_mac 02:00:00:00:00:01"
2f28bf
+test_on "pipe"
2f28bf
-- 
2f28bf
2.29.2
2f28bf