[ovs-dev] [PATCH v7 5/5] datapath: add layer 3 support to ovs_packet_cmd_execute()

Lorand Jakab lojakab at cisco.com
Fri Nov 14 13:51:49 UTC 2014


The presence of a layer 3 packet is signaled by the absence of
OVS_KEY_ATTR_ETHERNET in the packet metadata passed from user space.

Signed-off-by: Lorand Jakab <lojakab at cisco.com>
---
 datapath/datapath.c | 29 +++++++++++++++++------------
 datapath/flow.c     | 19 +++++++++++++++++--
 2 files changed, 34 insertions(+), 14 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 3607170..3ecb3cc 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -547,18 +547,6 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 
 	nla_memcpy(__skb_put(packet, len), a[OVS_PACKET_ATTR_PACKET], len);
 
-	skb_reset_mac_header(packet);
-	eth = eth_hdr(packet);
-
-	/* Normally, setting the skb 'protocol' field would be handled by a
-	 * call to eth_type_trans(), but it assumes there's a sending
-	 * device, which we may not have.
-	 */
-	if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
-		packet->protocol = eth->h_proto;
-	else
-		packet->protocol = htons(ETH_P_802_2);
-
 	/* Build an sw_flow for sending this packet. */
 	flow = ovs_flow_alloc();
 	err = PTR_ERR(flow);
@@ -570,6 +558,23 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 	if (err)
 		goto err_flow_free;
 
+	skb_reset_mac_header(packet);
+
+	if (flow->key.phy.is_layer3) {
+		skb_reset_network_header(packet);
+	} else {
+		eth = eth_hdr(packet);
+
+		/* Normally, setting the skb 'protocol' field would be handled
+		 * by a call to eth_type_trans(), but it assumes there's a
+		 * sending device, which we may not have.
+		 */
+		if (ntohs(eth->h_proto) >= ETH_P_802_3_MIN)
+			packet->protocol = eth->h_proto;
+		else
+			packet->protocol = htons(ETH_P_802_2);
+	}
+
 	err = ovs_nla_copy_actions(a[OVS_PACKET_ATTR_ACTIONS],
 				   &flow->key, &acts, log);
 	if (err)
diff --git a/datapath/flow.c b/datapath/flow.c
index b01f7bd..1dd3ac8 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -353,6 +353,18 @@ static __be16 parse_ethertype(struct sk_buff *skb)
 	return htons(ETH_P_802_2);
 }
 
+static __be16 ethertype_from_ip_version(struct sk_buff *skb)
+{
+	struct iphdr *iphdr = ip_hdr(skb);
+
+	if (iphdr->version == 4)
+		return htons(ETH_P_IP);
+	else if (iphdr->version == 6)
+		return htons(ETH_P_IPV6);
+
+	return 0;
+}
+
 static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
 			int nh_len)
 {
@@ -461,8 +473,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 
 	/* Link layer. */
 	if (key->phy.is_layer3) {
+		skb_reset_network_header(skb);
+
 		key->eth.tci = 0;
-		key->eth.type = skb->protocol;
+		key->eth.type = ethertype_from_ip_version(skb);
 	} else {
 		eth = eth_hdr(skb);
 		ether_addr_copy(key->eth.src, eth->h_source);
@@ -483,9 +497,10 @@ static int key_extract(struct sk_buff *skb, struct sw_flow_key *key)
 		key->eth.type = parse_ethertype(skb);
 		if (unlikely(key->eth.type == htons(0)))
 			return -ENOMEM;
+
+		skb_reset_network_header(skb);
 	}
 
-	skb_reset_network_header(skb);
 	skb_reset_mac_len(skb);
 	__skb_push(skb, skb->data - skb_mac_header(skb));
 
-- 
1.9.3 (Apple Git-50)




More information about the dev mailing list