diff mbox series

[ovs-dev,v4,2/2] Datapath: New MPLS actions for layer 2 tunnelling.

Message ID 20210326062146.56336-1-martinvarghesenokia@gmail.com
State Rejected
Headers show
Series Encap & Decap actions for MPLS packet type | expand

Commit Message

Martin Varghese March 26, 2021, 6:21 a.m. UTC
From: Martin Varghese <martin.varghese@nokia.com>

Upstream commit:

commit f66b53fdbb22ced1a323b22b9de84a61aacd8d18
Author: Martin Varghese <martin.varghese@nokia.com>
Date:   Sat Dec 21 08:50:46 2019 +0530

    openvswitch: New MPLS actions for layer 2 tunnelling
    The existing PUSH MPLS action inserts MPLS header between ethernet
    header and the IP header. Though this behaviour is fine for L3 VPN
    where an IP  packet is encapsulated inside a MPLS tunnel, it does not
    suffice the L2 VPN (l2 tunnelling) requirements. In L2 VPN the MPLS
    header should encapsulate the ethernet packet.

    The new mpls action ADD_MPLS inserts MPLS header at the start of the
    packet or at the start of the l3 header depending on the value of l3
    tunnel flag in the ADD_MPLS arguments.

    POP_MPLS action is extended to support ethertype 0x6558.

    Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
    Acked-by: Pravin B Shelar <pshelar@ovn.org>
    Signed-off-by: David S. Miller <davem@davemloft.net>

Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
---
 datapath/actions.c      | 42 ++++++++++++++++++++++++++++++++---------
 datapath/flow_netlink.c | 33 ++++++++++++++++++++++++++++++++
 2 files changed, 66 insertions(+), 9 deletions(-)

Comments

Ilya Maximets April 1, 2021, 6:32 p.m. UTC | #1
On 3/26/21 7:21 AM, Martin Varghese wrote:
> From: Martin Varghese <martin.varghese@nokia.com>
> 
> Upstream commit:
> 
> commit f66b53fdbb22ced1a323b22b9de84a61aacd8d18
> Author: Martin Varghese <martin.varghese@nokia.com>
> Date:   Sat Dec 21 08:50:46 2019 +0530
> 
>     openvswitch: New MPLS actions for layer 2 tunnelling
>     The existing PUSH MPLS action inserts MPLS header between ethernet
>     header and the IP header. Though this behaviour is fine for L3 VPN
>     where an IP  packet is encapsulated inside a MPLS tunnel, it does not
>     suffice the L2 VPN (l2 tunnelling) requirements. In L2 VPN the MPLS
>     header should encapsulate the ethernet packet.
> 
>     The new mpls action ADD_MPLS inserts MPLS header at the start of the
>     packet or at the start of the l3 header depending on the value of l3
>     tunnel flag in the ADD_MPLS arguments.
> 
>     POP_MPLS action is extended to support ethertype 0x6558.
> 
>     Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
>     Acked-by: Pravin B Shelar <pshelar@ovn.org>
>     Signed-off-by: David S. Miller <davem@davemloft.net>
> 
> Signed-off-by: Martin Varghese <martin.varghese@nokia.com>
> ---
>  datapath/actions.c      | 42 ++++++++++++++++++++++++++++++++---------
>  datapath/flow_netlink.c | 33 ++++++++++++++++++++++++++++++++
>  2 files changed, 66 insertions(+), 9 deletions(-)
> 

The kernel module that is in OVS source tree is deprecated
and we're not accepting new features there.  So, you may
drop this path from the set.

Best regards, Ilya Maximets.
diff mbox series

Patch

diff --git a/datapath/actions.c b/datapath/actions.c
index fbf445703..65266e403 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -185,7 +185,7 @@  static void update_ethertype(struct sk_buff *skb, struct ethhdr *hdr,
 }
 
 static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
-		     const struct ovs_action_push_mpls *mpls)
+		      __be32 mpls_lse, __be16 mpls_ethertype, __u16 mac_len)
 {
 	struct mpls_shim_hdr *new_mpls_lse;
 
@@ -197,26 +197,30 @@  static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
 		return -ENOMEM;
 
 	if (!ovs_skb_get_inner_protocol(skb)) {
-		skb_set_inner_network_header(skb, skb->mac_len);
+		skb_set_inner_network_header(skb, skb_network_offset(skb));
 		ovs_skb_set_inner_protocol(skb, skb->protocol);
 	}
 
 	skb_push(skb, MPLS_HLEN);
 	memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
-		skb->mac_len);
+		mac_len);
 	skb_reset_mac_header(skb);
 #ifdef MPLS_HEADER_IS_L3
-	skb_set_network_header(skb, skb->mac_len);
+	skb_set_network_header(skb, mac_len);
 #endif
+	skb_reset_mac_len(skb);
 
 	new_mpls_lse = mpls_hdr(skb);
-	new_mpls_lse->label_stack_entry = mpls->mpls_lse;
+	new_mpls_lse->label_stack_entry = mpls_lse;
 
 	skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
 
+	if (!mac_len)
+		key->mac_proto = MAC_PROTO_NONE;
+
 	if (ovs_key_mac_proto(key) == MAC_PROTO_ETHERNET)
-		update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
-	skb->protocol = mpls->mpls_ethertype;
+		update_ethertype(skb, eth_hdr(skb), mpls_ethertype);
+	skb->protocol = mpls_ethertype;
 
 	invalidate_flow_key(key);
 	return 0;
@@ -252,6 +256,9 @@  static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
 	if (eth_p_mpls(skb->protocol))
 		skb->protocol = ethertype;
 
+	if (ethertype == htons(ETH_P_TEB))
+		key->mac_proto = MAC_PROTO_ETHERNET;
+
 	invalidate_flow_key(key);
 	return 0;
 }
@@ -1309,9 +1316,26 @@  static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			execute_hash(skb, key, a);
 			break;
 
-		case OVS_ACTION_ATTR_PUSH_MPLS:
-			err = push_mpls(skb, key, nla_data(a));
+		case OVS_ACTION_ATTR_PUSH_MPLS: {
+			struct ovs_action_push_mpls *mpls = nla_data(a);
+
+			err = push_mpls(skb, key, mpls->mpls_lse,
+					mpls->mpls_ethertype, skb->mac_len);
 			break;
+		}
+
+		case OVS_ACTION_ATTR_ADD_MPLS: {
+		       struct ovs_action_add_mpls *mpls = nla_data(a);
+		       __u16 mac_len = 0;
+
+		       if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK)
+			       mac_len = skb->mac_len;
+
+		       err = push_mpls(skb, key, mpls->mpls_lse,
+				       mpls->mpls_ethertype, mac_len);
+		       break;
+	       }
+
 
 		case OVS_ACTION_ATTR_POP_MPLS:
 			err = pop_mpls(skb, key, nla_get_be16(a));
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
index 996041602..51687e52c 100644
--- a/datapath/flow_netlink.c
+++ b/datapath/flow_netlink.c
@@ -94,6 +94,7 @@  static bool actions_may_change_flow(const struct nlattr *actions)
 		case OVS_ACTION_ATTR_SET_MASKED:
 		case OVS_ACTION_ATTR_METER:
 		case OVS_ACTION_ATTR_CHECK_PKT_LEN:
+		case OVS_ACTION_ATTR_ADD_MPLS:
 		default:
 			return true;
 		}
@@ -3004,6 +3005,7 @@  static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			[OVS_ACTION_ATTR_METER] = sizeof(u32),
 			[OVS_ACTION_ATTR_CLONE] = (u32)-1,
 			[OVS_ACTION_ATTR_CHECK_PKT_LEN] = (u32)-1,
+			[OVS_ACTION_ATTR_ADD_MPLS] = sizeof(struct ovs_action_add_mpls),
 		};
 		const struct ovs_action_push_vlan *vlan;
 		int type = nla_type(a);
@@ -3071,6 +3073,33 @@  static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 		case OVS_ACTION_ATTR_RECIRC:
 			break;
 
+		case OVS_ACTION_ATTR_ADD_MPLS: {
+			const struct ovs_action_add_mpls *mpls = nla_data(a);
+
+			if (!eth_p_mpls(mpls->mpls_ethertype))
+				return -EINVAL;
+
+			if (mpls->tun_flags & OVS_MPLS_L3_TUNNEL_FLAG_MASK) {
+				if (vlan_tci & htons(VLAN_CFI_MASK) ||
+				    (eth_type != htons(ETH_P_IP) &&
+				     eth_type != htons(ETH_P_IPV6) &&
+				     eth_type != htons(ETH_P_ARP) &&
+				     eth_type != htons(ETH_P_RARP) &&
+				     !eth_p_mpls(eth_type)))
+					return -EINVAL;
+				mpls_label_count++;
+			} else {
+				if (mac_proto == MAC_PROTO_ETHERNET) {
+					mpls_label_count = 1;
+					mac_proto = MAC_PROTO_NONE;
+				} else {
+					mpls_label_count++;
+				}
+		       }
+		       eth_type = mpls->mpls_ethertype;
+		       break;
+		}
+
 		case OVS_ACTION_ATTR_PUSH_MPLS: {
 			const struct ovs_action_push_mpls *mpls = nla_data(a);
 
@@ -3110,6 +3139,10 @@  static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			proto = nla_get_be16(a);
 			mpls_label_count--;
 
+			if (proto == htons(ETH_P_TEB) &&
+			    mac_proto != MAC_PROTO_NONE)
+				return -EINVAL;
+
 			if (!eth_p_mpls(proto) || !mpls_label_count)
 				eth_type = htons(0);
 			else