[ovs-dev] [PATCH 09/11] datapath: Pass more packet metadata to userspace.

Jarno Rajahalme jarno.rajahalme at nsn.com
Mon Feb 11 14:46:25 UTC 2013


Signed-off-by: Jarno Rajahalme <jarno.rajahalme at nsn.com>
---
 datapath/datapath.c |   19 ++++++++++++++++++-
 datapath/flow.c     |   15 +++++++++++++--
 datapath/flow.h     |    5 +++--
 3 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 2e01740..81b1d53 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -374,8 +374,9 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
 	len = sizeof(struct ovs_header);
 	len += nla_total_size(skb->len);
 	len += nla_total_size(FLOW_BUFSIZE);
+	len += 3 * nla_total_size(4); /* packet offsets */
 	if (upcall_info->cmd == OVS_PACKET_CMD_ACTION)
-		len += nla_total_size(8);
+		len += nla_total_size(8); /* possible USERDATA */
 
 	user_skb = genlmsg_new(len, GFP_ATOMIC);
 	if (!user_skb) {
@@ -391,6 +392,22 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
 	ovs_flow_key_to_nlattrs(upcall_info->key, user_skb);
 	nla_nest_end(user_skb, nla);
 
+	{
+		u32 l3_offset = skb_network_offset(skb);
+		u32 l4_offset = skb_transport_offset(skb);
+
+		nla_put_u32(user_skb, OVS_PACKET_ATTR_L2_SIZE, l3_offset);
+		nla_put_u32(user_skb, OVS_PACKET_ATTR_L3_OFFSET, l3_offset);
+
+		/* Set the L4 offset attribute only if transport offset is
+		 * valid. */
+		if ((upcall_info->key->eth.type == htons(ETH_P_IP)
+		     || upcall_info->key->eth.type == htons(ETH_P_IPV6))
+		    && l4_offset > l3_offset)
+			nla_put_u32(user_skb, OVS_PACKET_ATTR_L4_OFFSET,
+				    l4_offset);
+	}
+
 	if (upcall_info->userdata)
 		nla_put_u64(user_skb, OVS_PACKET_ATTR_USERDATA,
 			    nla_get_u64(upcall_info->userdata));
diff --git a/datapath/flow.c b/datapath/flow.c
index 4c85e81..e3185aa 100644
--- a/datapath/flow.c
+++ b/datapath/flow.c
@@ -856,6 +856,7 @@ const int ovs_key_lens[OVS_KEY_ATTR_MAX + 1] = {
 
 	/* Not upstream. */
 	[OVS_KEY_ATTR_TUN_ID] = sizeof(__be64),
+	[OVS_KEY_ATTR_HASH] = sizeof(u32),
 };
 
 static int ipv4_flow_from_nlattrs(struct sw_flow_key *swkey,
@@ -1279,11 +1280,17 @@ int ovs_flow_key_from_nlattrs(struct sw_flow_key *swkey,
 		memcpy(swkey->ipv4.arp.tha, arp_key->arp_tha, ETH_ALEN);
 	}
 
+	/* Userspace provides the hash back to us only when the key
+	 * has been unmodified. */
+	if (attrs & (1ULL << OVS_KEY_ATTR_HASH)) {
+		swkey->hash = nla_get_u32(a[OVS_KEY_ATTR_HASH]);
+		attrs &= ~(1ULL << OVS_KEY_ATTR_HASH);
+	} else
+		swkey->hash = ovs_flow_hash(swkey, flow_key_start(swkey));
+
 	if (attrs)
 		return -EINVAL;
 
-	swkey->hash = ovs_flow_hash(swkey, flow_key_start(swkey));
-
 	return 0;
 }
 
@@ -1389,6 +1396,10 @@ int ovs_flow_key_to_nlattrs(const struct sw_flow_key *swkey, struct sk_buff *skb
 	struct ovs_key_ethernet *eth_key;
 	struct nlattr *nla, *encap;
 
+	/* Put hash first so that it is easy to find or ignore */
+	if (nla_put_u32(skb, OVS_KEY_ATTR_HASH, swkey->hash))
+		goto nla_put_failure;
+
 	if (swkey->phy.priority &&
 	    nla_put_u32(skb, OVS_KEY_ATTR_PRIORITY, swkey->phy.priority))
 		goto nla_put_failure;
diff --git a/datapath/flow.h b/datapath/flow.h
index dc9c000..5491fd0 100644
--- a/datapath/flow.h
+++ b/datapath/flow.h
@@ -187,10 +187,11 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_IPV6                   40    --     4     44
  *  OVS_KEY_ATTR_ICMPV6                  2     2     4      8
  *  OVS_KEY_ATTR_ND                     28    --     4     32
+ *  OVS_KEY_ATTR_HASH                    4    --     4      8
  *  ----------------------------------------------------------
- *  total                                                 220
+ *  total                                                 228
  */
-#define FLOW_BUFSIZE 220
+#define FLOW_BUFSIZE 228
 
 int ovs_flow_key_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int ovs_flow_key_from_nlattrs(struct sw_flow_key *,
-- 
1.7.10.4




More information about the dev mailing list