[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1467827996-32547-5-git-send-email-simon.horman@netronome.com>
Date: Wed, 6 Jul 2016 19:59:54 +0200
From: Simon Horman <simon.horman@...ronome.com>
To: netdev@...r.kernel.org
Cc: dev@...nvswitch.org
Subject: [PATCH net-next v11 4/6] openvswitch: add support to push and pop mpls for layer3 packets
Allow push and pop mpls actions to act on layer 3 packets by teaching
them not to access non-existent L2 headers of such packets.
Signed-off-by: Simon Horman <simon.horman@...ronome.com>
---
v11
* group l2 code in pop_mpls()
v10
* Limit scope of hdr in {push,pop}_mpls()
v9
* New Patch
---
include/uapi/linux/openvswitch.h | 2 ++
net/openvswitch/actions.c | 24 +++++++++++++++---------
2 files changed, 17 insertions(+), 9 deletions(-)
diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index d95a3018f6a1..5cde501433eb 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -737,6 +737,8 @@ enum ovs_nat_attr {
* is no MPLS label stack, as determined by ethertype, no action is taken.
* @OVS_ACTION_ATTR_CT: Track the connection. Populate the conntrack-related
* entries in the flow key.
+ * @OVS_ACTION_ATTR_PUSH_ETH: Push a new outermost Ethernet header onto the * packet.
+ * @OVS_ACTION_ATTR_POP_ETH: Pop the outermost Ethernet header off the packet.
*
* Only a single header can be set with a single %OVS_ACTION_ATTR_SET. Not all
* fields within a header are modifiable, e.g. the IPv4 protocol and fragment
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 1ecbd7715f6d..12e8a8942a42 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -163,8 +163,6 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
return -ENOMEM;
skb_push(skb, MPLS_HLEN);
- memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
- skb->mac_len);
skb_reset_mac_header(skb);
new_mpls_lse = (__be32 *)skb_mpls_header(skb);
@@ -172,7 +170,11 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
skb_postpush_rcsum(skb, new_mpls_lse, MPLS_HLEN);
- update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
+ if (skb->mac_len) {
+ update_ethertype(skb, eth_hdr(skb), mpls->mpls_ethertype);
+ memmove(skb_mac_header(skb) - MPLS_HLEN, skb_mac_header(skb),
+ skb->mac_len);
+ }
if (!skb->inner_protocol)
skb_set_inner_protocol(skb, skb->protocol);
skb->protocol = mpls->mpls_ethertype;
@@ -184,7 +186,6 @@ static int push_mpls(struct sk_buff *skb, struct sw_flow_key *key,
static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
const __be16 ethertype)
{
- struct ethhdr *hdr;
int err;
err = skb_ensure_writable(skb, skb->mac_len + MPLS_HLEN);
@@ -199,11 +200,16 @@ static int pop_mpls(struct sk_buff *skb, struct sw_flow_key *key,
__skb_pull(skb, MPLS_HLEN);
skb_reset_mac_header(skb);
- /* skb_mpls_header() is used to locate the ethertype
- * field correctly in the presence of VLAN tags.
- */
- hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
- update_ethertype(skb, hdr, ethertype);
+ if (skb->mac_len) {
+ struct ethhdr *hdr;
+
+ /* skb_mpls_header() is used to locate the ethertype
+ * field correctly in the presence of VLAN tags.
+ */
+ hdr = (struct ethhdr *)(skb_mpls_header(skb) - ETH_HLEN);
+ update_ethertype(skb, hdr, ethertype);
+ }
+
if (eth_p_mpls(skb->protocol))
skb->protocol = ethertype;
--
2.7.0.rc3.207.g0ac5344
Powered by blists - more mailing lists