[ovs-dev] [RFC PATCH v2 5/5] Add push_eth/pop_eth flow actions for kernel data path

Johnson Li johnson.li at intel.com
Tue Jul 12 17:36:46 UTC 2016


Ethernet header could be pushed to/stripped from packets with
flow action push_eth/pop_eth, origin packets will be treated as
payload even the packets are Ethernet packets.

Derived from work by Lorand Jakub and Simon Horman.
Cc: Lorand Jakab <lojakab at cisco.com>
Cc: Simon Horman <simon.horman at netronome.com>
---
This is extracted from l3 flow support paches currently
being targeted at net-next by Simon Horman.

Signed-off-by: Simon Horman <simon.horman at netronome.com>
Signed-off-by: Johnson Li <johnson.li at intel.com>

diff --git a/datapath/actions.c b/datapath/actions.c
index 0c2927e..eda9106 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -312,6 +312,48 @@ static int push_nsh(struct sk_buff *skb, struct sw_flow_key *key,
 	return 0;
 }
 
+static int pop_eth(struct sk_buff *skb, struct sw_flow_key *key)
+{
+	if ((skb->protocol == htons(ETH_P_8021Q) ||
+	     skb->protocol == htons(ETH_P_8021AD)) &&
+	    !skb_vlan_tag_present(skb)) {
+		int err = skb_vlan_pop(skb);
+		if (unlikely(err))
+			return err;
+	}
+
+	skb_pull_rcsum(skb, ETH_HLEN);
+	skb_reset_mac_header(skb);
+	skb->mac_len -= ETH_HLEN;
+
+	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_reset_mac_len(skb);
+
+	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, skb->data, ETH_HLEN);
+
+	invalidate_flow_key(key);
+	return 0;
+}
+
 /* 'src' is already properly masked. */
 static void ether_addr_copy_masked(u8 *dst_, const u8 *src_, const u8 *mask_)
 {
@@ -1218,6 +1260,14 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 		case OVS_ACTION_ATTR_POP_NSH:
 			err = pop_nsh(skb, key);
 			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/datapath/linux/compat/include/linux/skbuff.h b/datapath/linux/compat/include/linux/skbuff.h
index 376dfda..03ac37c 100644
--- a/datapath/linux/compat/include/linux/skbuff.h
+++ b/datapath/linux/compat/include/linux/skbuff.h
@@ -310,6 +310,14 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
 		skb->ip_summed = CHECKSUM_NONE;
 }
 
+#define skb_postpush_rcsum rpl_skb_postpush_rcsum
+static inline void skb_postpush_rcsum(struct sk_buff *skb,
+				      const void *start, unsigned int len)
+{
+	if (skb->ip_summed == CHECKSUM_COMPLETE)
+		skb->csum = csum_partial(start, len, skb->csum);
+}
+
 #define skb_pull_rcsum rpl_skb_pull_rcsum
 static inline unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
 {
-- 
1.8.4.2

--------------------------------------------------------------
Intel Research and Development Ireland Limited
Registered in Ireland
Registered Office: Collinstown Industrial Park, Leixlip, County Kildare
Registered Number: 308263


This e-mail and any attachments may contain confidential material for the sole
use of the intended recipient(s). Any review or distribution by others is
strictly prohibited. If you are not the intended recipient, please contact the
sender and delete all copies.




More information about the dev mailing list