naccyde / rpms / iproute

Forked from rpms/iproute 9 months ago
Clone

Blame SOURCES/0004-m_mpls-add-mac_push-action.patch

2f28bf
From 0afe12a4a9471ed1343693338ec6350dc66ba295 Mon Sep 17 00:00:00 2001
2f28bf
Message-Id: <0afe12a4a9471ed1343693338ec6350dc66ba295.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_mpls: add mac_push action
2f28bf
2f28bf
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1885770
2f28bf
Upstream Status: unknown commit 02a261b5
2f28bf
2f28bf
commit 02a261b5ba1c8580ac2a35bc6c87faa2ec9f5c96
2f28bf
Author: Guillaume Nault <gnault@redhat.com>
2f28bf
Date:   Mon Oct 19 17:23:08 2020 +0200
2f28bf
2f28bf
    m_mpls: add mac_push action
2f28bf
2f28bf
    Add support for the new TCA_MPLS_ACT_MAC_PUSH action (kernel commit
2f28bf
    a45294af9e96 ("net/sched: act_mpls: Add action to push MPLS LSE before
2f28bf
    Ethernet header")). This action let TC push an MPLS header before the
2f28bf
    MAC header of a frame.
2f28bf
2f28bf
    Example (encapsulate all outgoing frames with label 20, then add an
2f28bf
    outer Ethernet header):
2f28bf
     # tc filter add dev ethX matchall \
2f28bf
           action mpls mac_push label 20 ttl 64 \
2f28bf
           action vlan push_eth dst_mac 0a:00:00:00:00:02 \
2f28bf
                                src_mac 0a:00:00:00:00:01
2f28bf
2f28bf
    This patch also adds an alias for ETH_P_TEB, since it is useful when
2f28bf
    decapsulating MPLS packets that contain an Ethernet frame.
2f28bf
2f28bf
    With MAC_PUSH, there's no previous Ethertype to modify. However, the
2f28bf
    "protocol" option is still needed, because the kernel uses it to set
2f28bf
    skb->protocol. So rename can_modify_ethtype() to can_set_ethtype().
2f28bf
2f28bf
    Also add a test suite for m_mpls, which covers the new action and the
2f28bf
    pre-existing ones.
2f28bf
2f28bf
    Signed-off-by: Guillaume Nault <gnault@redhat.com>
2f28bf
    Signed-off-by: David Ahern <dsahern@gmail.com>
2f28bf
---
2f28bf
 lib/ll_proto.c            |  1 +
2f28bf
 man/man8/tc-mpls.8        | 44 +++++++++++++++++++++++--
2f28bf
 man/man8/tc-vlan.8        |  5 ++-
2f28bf
 tc/m_mpls.c               | 43 ++++++++++++++++--------
2f28bf
 testsuite/tests/tc/mpls.t | 69 +++++++++++++++++++++++++++++++++++++++
2f28bf
 5 files changed, 145 insertions(+), 17 deletions(-)
2f28bf
 create mode 100755 testsuite/tests/tc/mpls.t
2f28bf
2f28bf
diff --git a/lib/ll_proto.c b/lib/ll_proto.c
2f28bf
index 2a0c1cb3..78179311 100644
2f28bf
--- a/lib/ll_proto.c
2f28bf
+++ b/lib/ll_proto.c
2f28bf
@@ -80,6 +80,7 @@ __PF(8021Q,802.1Q)
2f28bf
 __PF(8021AD,802.1ad)
2f28bf
 __PF(MPLS_UC,mpls_uc)
2f28bf
 __PF(MPLS_MC,mpls_mc)
2f28bf
+__PF(TEB,teb)
2f28bf
 
2f28bf
 { 0x8100, "802.1Q" },
2f28bf
 { 0x88cc, "LLDP" },
2f28bf
diff --git a/man/man8/tc-mpls.8 b/man/man8/tc-mpls.8
2f28bf
index 84ef2ef1..9e563e98 100644
2f28bf
--- a/man/man8/tc-mpls.8
2f28bf
+++ b/man/man8/tc-mpls.8
2f28bf
@@ -17,7 +17,7 @@ mpls - mpls manipulation module
2f28bf
 
2f28bf
 .ti -8
2f28bf
 .IR PUSH " := "
2f28bf
-.BR push " [ " protocol
2f28bf
+.RB "{ " push " | " mac_push " } [ " protocol
2f28bf
 .IR MPLS_PROTO " ]"
2f28bf
 .RB " [ " tc
2f28bf
 .IR MPLS_TC " ] "
2f28bf
@@ -64,7 +64,14 @@ requires no arguments and simply subtracts 1 from the MPLS header TTL field.
2f28bf
 Decapsulation mode. Requires the protocol of the next header.
2f28bf
 .TP
2f28bf
 .B push
2f28bf
-Encapsulation mode. Requires at least the
2f28bf
+Encapsulation mode. Adds the MPLS header between the MAC and the network
2f28bf
+headers. Requires at least the
2f28bf
+.B label
2f28bf
+option.
2f28bf
+.TP
2f28bf
+.B mac_push
2f28bf
+Encapsulation mode. Adds the MPLS header before the MAC header. Requires at
2f28bf
+least the
2f28bf
 .B label
2f28bf
 option.
2f28bf
 .TP
2f28bf
@@ -152,5 +159,36 @@ ip packets and output to eth1:
2f28bf
 .EE
2f28bf
 .RE
2f28bf
 
2f28bf
+Here is another example, where incoming Ethernet frames are encapsulated into
2f28bf
+MPLS with label 123 and TTL 64. Then, an outer Ethernet header is added and the
2f28bf
+resulting frame is finally sent on eth1:
2f28bf
+
2f28bf
+.RS
2f28bf
+.EX
2f28bf
+#tc qdisc add dev eth0 ingress
2f28bf
+#tc filter add dev eth0 ingress matchall \\
2f28bf
+	action mpls mac_push label 123 ttl 64 \\
2f28bf
+	action vlan push_eth \\
2f28bf
+		dst_mac 02:00:00:00:00:02 \\
2f28bf
+		src_mac 02:00:00:00:00:01 \\
2f28bf
+	action mirred egress redirect dev eth1
2f28bf
+.EE
2f28bf
+.RE
2f28bf
+
2f28bf
+The following example assumes that incoming MPLS packets with label 123
2f28bf
+transport Ethernet frames. The outer Ethernet and the MPLS headers are
2f28bf
+stripped, then the inner Ethernet frame is sent on eth1:
2f28bf
+
2f28bf
+.RS
2f28bf
+.EX
2f28bf
+#tc qdisc add dev eth0 ingress
2f28bf
+#tc filter add dev eth0 ingress protocol mpls_uc \\
2f28bf
+	flower mpls_label 123 mpls_bos 1 \\
2f28bf
+	action vlan pop_eth \\
2f28bf
+	action mpls pop protocol teb \\
2f28bf
+	action mirred egress redirect dev eth1
2f28bf
+.EE
2f28bf
+.RE
2f28bf
+
2f28bf
 .SH SEE ALSO
2f28bf
-.BR tc (8)
2f28bf
+.BR tc "(8), " tc-mirred "(8), " tc-vlan (8)
2f28bf
diff --git a/man/man8/tc-vlan.8 b/man/man8/tc-vlan.8
2f28bf
index 5c2808b1..264053d3 100644
2f28bf
--- a/man/man8/tc-vlan.8
2f28bf
+++ b/man/man8/tc-vlan.8
2f28bf
@@ -157,5 +157,8 @@ process then restarted for the plain packet:
2f28bf
 .EE
2f28bf
 .RE
2f28bf
 
2f28bf
+For an example of the
2f28bf
+.BR pop_eth " and " push_eth " modes, see " tc-mpls (8).
2f28bf
+
2f28bf
 .SH SEE ALSO
2f28bf
-.BR tc (8)
2f28bf
+.BR tc "(8), " tc-mpls (8)
2f28bf
diff --git a/tc/m_mpls.c b/tc/m_mpls.c
2f28bf
index 3d5d9b25..cb8019b1 100644
2f28bf
--- a/tc/m_mpls.c
2f28bf
+++ b/tc/m_mpls.c
2f28bf
@@ -17,6 +17,7 @@ static const char * const action_names[] = {
2f28bf
 	[TCA_MPLS_ACT_PUSH] = "push",
2f28bf
 	[TCA_MPLS_ACT_MODIFY] = "modify",
2f28bf
 	[TCA_MPLS_ACT_DEC_TTL] = "dec_ttl",
2f28bf
+	[TCA_MPLS_ACT_MAC_PUSH] = "mac_push",
2f28bf
 };
2f28bf
 
2f28bf
 static void explain(void)
2f28bf
@@ -25,9 +26,11 @@ static void explain(void)
2f28bf
 		"Usage: mpls pop [ protocol MPLS_PROTO ]\n"
2f28bf
 		"       mpls push [ protocol MPLS_PROTO ] [ label MPLS_LABEL ] [ tc MPLS_TC ]\n"
2f28bf
 		"                 [ ttl MPLS_TTL ] [ bos MPLS_BOS ] [CONTROL]\n"
2f28bf
+		"       mpls mac_push [ protocol MPLS_PROTO ] [ label MPLS_LABEL ] [ tc MPLS_TC ]\n"
2f28bf
+		"                     [ ttl MPLS_TTL ] [ bos MPLS_BOS ] [CONTROL]\n"
2f28bf
 		"       mpls modify [ label MPLS_LABEL ] [ tc MPLS_TC ] [ ttl MPLS_TTL ] [CONTROL]\n"
2f28bf
-		"           for pop MPLS_PROTO is next header of packet - e.g. ip or mpls_uc\n"
2f28bf
-		"           for push MPLS_PROTO is one of mpls_uc or mpls_mc\n"
2f28bf
+		"           for pop, MPLS_PROTO is next header of packet - e.g. ip or mpls_uc\n"
2f28bf
+		"           for push and mac_push, MPLS_PROTO is one of mpls_uc or mpls_mc\n"
2f28bf
 		"               with default: mpls_uc\n"
2f28bf
 		"       CONTROL := reclassify | pipe | drop | continue | pass |\n"
2f28bf
 		"                  goto chain <CHAIN_INDEX>\n");
2f28bf
@@ -41,12 +44,14 @@ static void usage(void)
2f28bf
 
2f28bf
 static bool can_modify_mpls_fields(unsigned int action)
2f28bf
 {
2f28bf
-	return action == TCA_MPLS_ACT_PUSH || action == TCA_MPLS_ACT_MODIFY;
2f28bf
+	return action == TCA_MPLS_ACT_PUSH || action == TCA_MPLS_ACT_MAC_PUSH ||
2f28bf
+		action == TCA_MPLS_ACT_MODIFY;
2f28bf
 }
2f28bf
 
2f28bf
-static bool can_modify_ethtype(unsigned int action)
2f28bf
+static bool can_set_ethtype(unsigned int action)
2f28bf
 {
2f28bf
-	return action == TCA_MPLS_ACT_PUSH || action == TCA_MPLS_ACT_POP;
2f28bf
+	return action == TCA_MPLS_ACT_PUSH || action == TCA_MPLS_ACT_MAC_PUSH ||
2f28bf
+		action == TCA_MPLS_ACT_POP;
2f28bf
 }
2f28bf
 
2f28bf
 static bool is_valid_label(__u32 label)
2f28bf
@@ -94,6 +99,10 @@ static int parse_mpls(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 			if (check_double_action(action, *argv))
2f28bf
 				return -1;
2f28bf
 			action = TCA_MPLS_ACT_PUSH;
2f28bf
+		} else if (matches(*argv, "mac_push") == 0) {
2f28bf
+			if (check_double_action(action, *argv))
2f28bf
+				return -1;
2f28bf
+			action = TCA_MPLS_ACT_MAC_PUSH;
2f28bf
 		} else if (matches(*argv, "modify") == 0) {
2f28bf
 			if (check_double_action(action, *argv))
2f28bf
 				return -1;
2f28bf
@@ -104,31 +113,36 @@ static int parse_mpls(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 			action = TCA_MPLS_ACT_DEC_TTL;
2f28bf
 		} else if (matches(*argv, "label") == 0) {
2f28bf
 			if (!can_modify_mpls_fields(action))
2f28bf
-				invarg("only valid for push/modify", *argv);
2f28bf
+				invarg("only valid for push, mac_push and modify",
2f28bf
+				       *argv);
2f28bf
 			NEXT_ARG();
2f28bf
 			if (get_u32(&label, *argv, 0) || !is_valid_label(label))
2f28bf
 				invarg("label must be <=0xFFFFF", *argv);
2f28bf
 		} else if (matches(*argv, "tc") == 0) {
2f28bf
 			if (!can_modify_mpls_fields(action))
2f28bf
-				invarg("only valid for push/modify", *argv);
2f28bf
+				invarg("only valid for push, mac_push and modify",
2f28bf
+				       *argv);
2f28bf
 			NEXT_ARG();
2f28bf
 			if (get_u8(&tc, *argv, 0) || (tc & ~0x7))
2f28bf
 				invarg("tc field is 3 bits max", *argv);
2f28bf
 		} else if (matches(*argv, "ttl") == 0) {
2f28bf
 			if (!can_modify_mpls_fields(action))
2f28bf
-				invarg("only valid for push/modify", *argv);
2f28bf
+				invarg("only valid for push, mac_push and modify",
2f28bf
+				       *argv);
2f28bf
 			NEXT_ARG();
2f28bf
 			if (get_u8(&ttl, *argv, 0) || !ttl)
2f28bf
 				invarg("ttl must be >0 and <=255", *argv);
2f28bf
 		} else if (matches(*argv, "bos") == 0) {
2f28bf
 			if (!can_modify_mpls_fields(action))
2f28bf
-				invarg("only valid for push/modify", *argv);
2f28bf
+				invarg("only valid for push, mac_push and modify",
2f28bf
+				       *argv);
2f28bf
 			NEXT_ARG();
2f28bf
 			if (get_u8(&bos, *argv, 0) || (bos & ~0x1))
2f28bf
 				invarg("bos must be 0 or 1", *argv);
2f28bf
 		} else if (matches(*argv, "protocol") == 0) {
2f28bf
-			if (!can_modify_ethtype(action))
2f28bf
-				invarg("only valid for push/pop", *argv);
2f28bf
+			if (!can_set_ethtype(action))
2f28bf
+				invarg("only valid for push, mac_push and pop",
2f28bf
+				       *argv);
2f28bf
 			NEXT_ARG();
2f28bf
 			if (ll_proto_a2n(&proto, *argv))
2f28bf
 				invarg("protocol is invalid", *argv);
2f28bf
@@ -159,10 +173,12 @@ static int parse_mpls(struct action_util *a, int *argc_p, char ***argv_p,
2f28bf
 	if (action == TCA_MPLS_ACT_PUSH && label == 0xffffffff)
2f28bf
 		missarg("label");
2f28bf
 
2f28bf
-	if (action == TCA_MPLS_ACT_PUSH && proto &&
2f28bf
+	if ((action == TCA_MPLS_ACT_PUSH || action == TCA_MPLS_ACT_MAC_PUSH) &&
2f28bf
+	    proto &&
2f28bf
 	    proto != htons(ETH_P_MPLS_UC) && proto != htons(ETH_P_MPLS_MC)) {
2f28bf
 		fprintf(stderr,
2f28bf
-			"invalid push protocol \"0x%04x\" - use mpls_(uc|mc)\n",
2f28bf
+			"invalid %spush protocol \"0x%04x\" - use mpls_(uc|mc)\n",
2f28bf
+			action == TCA_MPLS_ACT_MAC_PUSH ? "mac_" : "",
2f28bf
 			ntohs(proto));
2f28bf
 		return -1;
2f28bf
 	}
2f28bf
@@ -223,6 +239,7 @@ static int print_mpls(struct action_util *au, FILE *f, struct rtattr *arg)
2f28bf
 		}
2f28bf
 		break;
2f28bf
 	case TCA_MPLS_ACT_PUSH:
2f28bf
+	case TCA_MPLS_ACT_MAC_PUSH:
2f28bf
 		if (tb[TCA_MPLS_PROTO]) {
2f28bf
 			__u16 proto;
2f28bf
 
2f28bf
diff --git a/testsuite/tests/tc/mpls.t b/testsuite/tests/tc/mpls.t
2f28bf
new file mode 100755
2f28bf
index 00000000..cb25f361
2f28bf
--- /dev/null
2f28bf
+++ b/testsuite/tests/tc/mpls.t
2f28bf
@@ -0,0 +1,69 @@
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 mpls action pop"                              \
2f28bf
+	filter add dev $DEV ingress protocol mpls_uc matchall \
2f28bf
+	action mpls pop protocol ip
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "mpls"
2f28bf
+test_on "pop protocol ip pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add mpls action push"                        \
2f28bf
+	filter add dev $DEV ingress protocol ip matchall \
2f28bf
+	action mpls push protocol mpls_uc label 20 tc 3 bos 1 ttl 64
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "mpls"
2f28bf
+test_on "push"
2f28bf
+test_on "protocol mpls_uc"
2f28bf
+test_on "label 20"
2f28bf
+test_on "tc 3"
2f28bf
+test_on "bos 1"
2f28bf
+test_on "ttl 64"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add mpls action mac_push"        \
2f28bf
+	filter add dev $DEV ingress matchall \
2f28bf
+	action mpls mac_push protocol mpls_uc label 20 tc 3 bos 1 ttl 64
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "mpls"
2f28bf
+test_on "mac_push"
2f28bf
+test_on "protocol mpls_uc"
2f28bf
+test_on "label 20"
2f28bf
+test_on "tc 3"
2f28bf
+test_on "bos 1"
2f28bf
+test_on "ttl 64"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add mpls action modify"                           \
2f28bf
+	filter add dev $DEV ingress protocol mpls_uc matchall \
2f28bf
+	action mpls modify label 20 tc 3 ttl 64
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "mpls"
2f28bf
+test_on "modify"
2f28bf
+test_on "label 20"
2f28bf
+test_on "tc 3"
2f28bf
+test_on "ttl 64"
2f28bf
+test_on "pipe"
2f28bf
+
2f28bf
+reset_qdisc
2f28bf
+ts_tc "$0" "Add mpls action dec_ttl"                          \
2f28bf
+	filter add dev $DEV ingress protocol mpls_uc matchall \
2f28bf
+	action mpls dec_ttl
2f28bf
+ts_tc "$0" "Show ingress filters" filter show dev $DEV ingress
2f28bf
+test_on "mpls"
2f28bf
+test_on "dec_ttl"
2f28bf
+test_on "pipe"
2f28bf
-- 
2f28bf
2.29.2
2f28bf