All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jiri Benc <jbenc@redhat.com>
To: netdev@vger.kernel.org
Cc: dev@openvswitch.org, Pravin Shelar <pshelar@ovn.org>,
	Lorand Jakab <lojakab@cisco.com>,
	Simon Horman <simon.horman@netronome.com>
Subject: [PATCH net-next v12 7/9] openvswitch: add Ethernet push and pop actions
Date: Mon, 17 Oct 2016 15:02:43 +0200	[thread overview]
Message-ID: <bf8e49c178a2f8ed9adb02e30470be5163d46296.1476708213.git.jbenc@redhat.com> (raw)
In-Reply-To: <cover.1476708212.git.jbenc@redhat.com>

It's not allowed to push Ethernet header in front of another Ethernet
header.

It's not allowed to pop Ethernet header if there's a vlan tag. This
preserves the invariant that L3 packet never has a vlan tag.

Based on previous versions by Lorand Jakab and Simon Horman.

Signed-off-by: Lorand Jakab <lojakab@cisco.com>
Signed-off-by: Simon Horman <simon.horman@netronome.com>
Signed-off-by: Jiri Benc <jbenc@redhat.com>
---
 include/uapi/linux/openvswitch.h | 15 ++++++++++++
 net/openvswitch/actions.c        | 49 ++++++++++++++++++++++++++++++++++++++++
 net/openvswitch/flow_netlink.c   | 18 +++++++++++++++
 3 files changed, 82 insertions(+)

diff --git a/include/uapi/linux/openvswitch.h b/include/uapi/linux/openvswitch.h
index 59ed3992c760..375d812fea36 100644
--- a/include/uapi/linux/openvswitch.h
+++ b/include/uapi/linux/openvswitch.h
@@ -705,6 +705,15 @@ enum ovs_nat_attr {
 
 #define OVS_NAT_ATTR_MAX (__OVS_NAT_ATTR_MAX - 1)
 
+/*
+ * struct ovs_action_push_eth - %OVS_ACTION_ATTR_PUSH_ETH action argument.
+ * @addresses: Source and destination MAC addresses.
+ * @eth_type: Ethernet type
+ */
+struct ovs_action_push_eth {
+	struct ovs_key_ethernet addresses;
+};
+
 /**
  * enum ovs_action_attr - Action types.
  *
@@ -738,6 +747,10 @@ 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
@@ -765,6 +778,8 @@ enum ovs_action_attr {
 				       * bits. */
 	OVS_ACTION_ATTR_CT,           /* Nested OVS_CT_ATTR_* . */
 	OVS_ACTION_ATTR_TRUNC,        /* u32 struct ovs_action_trunc. */
+	OVS_ACTION_ATTR_PUSH_ETH,     /* struct ovs_action_push_eth. */
+	OVS_ACTION_ATTR_POP_ETH,      /* No argument. */
 
 	__OVS_ACTION_ATTR_MAX,	      /* Nothing past this will be accepted
 				       * from userspace. */
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c
index 064cbcb7b0c5..a63572fb878e 100644
--- a/net/openvswitch/actions.c
+++ b/net/openvswitch/actions.c
@@ -317,6 +317,47 @@ static int set_eth_addr(struct sk_buff *skb, struct sw_flow_key *flow_key,
 	return 0;
 }
 
+/* pop_eth does not support VLAN packets as this action is never called
+ * for them.
+ */
+static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
+{
+	skb_pull_rcsum(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);
+	skb->mac_len -= ETH_HLEN;
+
+	/* safe right before invalidate_flow_key */
+	key->mac_proto = MAC_PROTO_NONE;
+	invalidate_flow_key(key);
+	return 0;
+}
+
+static int push_eth(struct sk_buff *skb, struct sw_flow_key *key,
+		    const struct ovs_action_push_eth *ethh)
+{
+	struct ethhdr *hdr;
+
+	/* Add the new Ethernet header */
+	if (skb_cow_head(skb, ETH_HLEN) < 0)
+		return -ENOMEM;
+
+	skb_push(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);
+	skb->mac_len = ETH_HLEN;
+
+	hdr = eth_hdr(skb);
+	ether_addr_copy(hdr->h_source, ethh->addresses.eth_src);
+	ether_addr_copy(hdr->h_dest, ethh->addresses.eth_dst);
+	hdr->h_proto = skb->protocol;
+
+	skb_postpush_rcsum(skb, hdr, ETH_HLEN);
+
+	/* safe right before invalidate_flow_key */
+	key->mac_proto = MAC_PROTO_ETHERNET;
+	invalidate_flow_key(key);
+	return 0;
+}
+
 static void update_ip_l4_checksum(struct sk_buff *skb, struct iphdr *nh,
 				  __be32 addr, __be32 new_addr)
 {
@@ -1200,6 +1241,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			if (err)
 				return err == -EINPROGRESS ? 0 : err;
 			break;
+
+		case OVS_ACTION_ATTR_PUSH_ETH:
+			err = push_eth(skb, key, nla_data(a));
+			break;
+
+		case OVS_ACTION_ATTR_POP_ETH:
+			err = pop_eth(skb, key);
+			break;
 		}
 
 		if (unlikely(err)) {
diff --git a/net/openvswitch/flow_netlink.c b/net/openvswitch/flow_netlink.c
index c3d0cc4321c3..d19044f2b1f4 100644
--- a/net/openvswitch/flow_netlink.c
+++ b/net/openvswitch/flow_netlink.c
@@ -2383,6 +2383,8 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			[OVS_ACTION_ATTR_HASH] = sizeof(struct ovs_action_hash),
 			[OVS_ACTION_ATTR_CT] = (u32)-1,
 			[OVS_ACTION_ATTR_TRUNC] = sizeof(struct ovs_action_trunc),
+			[OVS_ACTION_ATTR_PUSH_ETH] = sizeof(struct ovs_action_push_eth),
+			[OVS_ACTION_ATTR_POP_ETH] = 0,
 		};
 		const struct ovs_action_push_vlan *vlan;
 		int type = nla_type(a);
@@ -2517,6 +2519,22 @@ static int __ovs_nla_copy_actions(struct net *net, const struct nlattr *attr,
 			skip_copy = true;
 			break;
 
+		case OVS_ACTION_ATTR_PUSH_ETH:
+			/* Disallow pushing an Ethernet header if one
+			 * is already present */
+			if (mac_proto != MAC_PROTO_NONE)
+				return -EINVAL;
+			mac_proto = MAC_PROTO_NONE;
+			break;
+
+		case OVS_ACTION_ATTR_POP_ETH:
+			if (mac_proto != MAC_PROTO_ETHERNET)
+				return -EINVAL;
+			if (vlan_tci & htons(VLAN_TAG_PRESENT))
+				return -EINVAL;
+			mac_proto = MAC_PROTO_ETHERNET;
+			break;
+
 		default:
 			OVS_NLERR(log, "Unknown Action type %d", type);
 			return -EINVAL;
-- 
1.8.3.1

  parent reply	other threads:[~2016-10-17 13:03 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-17 13:02 [PATCH net-next v12 0/9] openvswitch: support for layer 3 encapsulated packets Jiri Benc
     [not found] ` <cover.1476708212.git.jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-17 13:02   ` [PATCH net-next v12 1/9] openvswitch: use hard_header_len instead of hardcoded ETH_HLEN Jiri Benc
2016-10-19  5:13     ` Pravin Shelar
2016-10-17 13:02   ` [PATCH net-next v12 2/9] openvswitch: add mac_proto field to the flow key Jiri Benc
     [not found]     ` <098a6ab19e26cf7b1cc16f57f5fc0cc019ca44d6.1476708212.git.jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-19  5:11       ` Pravin Shelar
2016-10-19  5:11   ` [PATCH net-next v12 0/9] openvswitch: support for layer 3 encapsulated packets Pravin Shelar
2016-10-19 16:59     ` Jiri Benc
2016-10-17 13:02 ` [PATCH net-next v12 3/9] openvswitch: pass mac_proto to ovs_vport_send Jiri Benc
2016-10-19  5:11   ` Pravin Shelar
2016-10-17 13:02 ` [PATCH net-next v12 4/9] openvswitch: support MPLS push and pop for L3 packets Jiri Benc
     [not found]   ` <004e53f40443698cffdaf8f9839649cc4b9101cc.1476708213.git.jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-19  5:11     ` Pravin Shelar
2016-10-17 13:02 ` [PATCH net-next v12 5/9] openvswitch: add processing of " Jiri Benc
2016-10-19  5:13   ` Pravin Shelar
2016-10-19 16:52     ` Jiri Benc
2016-10-20 18:48       ` Pravin Shelar
2016-10-21  4:19   ` Pravin Shelar
2016-10-21 11:59     ` Jiri Benc
2016-10-17 13:02 ` [PATCH net-next v12 6/9] openvswitch: netlink: support " Jiri Benc
2016-10-21  4:20   ` Pravin Shelar
2016-10-17 13:02 ` Jiri Benc [this message]
2016-10-21  4:22   ` [PATCH net-next v12 7/9] openvswitch: add Ethernet push and pop actions Pravin Shelar
2016-10-21 12:21     ` Jiri Benc
2016-10-17 13:02 ` [PATCH net-next v12 8/9] openvswitch: allow L3 netdev ports Jiri Benc
2016-10-21  4:22   ` Pravin Shelar
2016-10-17 13:02 ` [PATCH net-next v12 9/9] openvswitch: use ipgre tunnel rather than gretap tunnel Jiri Benc
     [not found]   ` <4e5bfb307ee1e419f973a100e8acc7556311b64a.1476708213.git.jbenc-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2016-10-19  5:14     ` Pravin Shelar
2016-10-19 16:58       ` Jiri Benc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bf8e49c178a2f8ed9adb02e30470be5163d46296.1476708213.git.jbenc@redhat.com \
    --to=jbenc@redhat.com \
    --cc=dev@openvswitch.org \
    --cc=lojakab@cisco.com \
    --cc=netdev@vger.kernel.org \
    --cc=pshelar@ovn.org \
    --cc=simon.horman@netronome.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.