[ovs-dev] [PATCH] datapath: Make OVS_ACTION_ATTR_USERSPACE action to send packet key

Andy Zhou azhou at nicira.com
Tue Jun 25 15:22:35 UTC 2013


OVS_ACTION_ATTR_USERSPACE action was sending the key from the matching
flow. This works for exact match flows because flow keys are the
same as packet keys. However, it does not work with wildcarded flows as
the packet keys may be different than the flow keys. This patch preserves
the packet keys and send it when calling output_userspace().

Bug #18163

Signed-off-by: Andy Zhou <azhou at nicira.com>
---
 datapath/actions.c  |   26 +++++++++++++++-----------
 datapath/datapath.c |    4 ++--
 datapath/datapath.h |    3 ++-
 3 files changed, 19 insertions(+), 14 deletions(-)

diff --git a/datapath/actions.c b/datapath/actions.c
index 09d0c3f..643e667 100644
--- a/datapath/actions.c
+++ b/datapath/actions.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007-2012 Nicira, Inc.
+ * Copyright (c) 2007-2013 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of version 2 of the GNU General Public
@@ -38,7 +38,8 @@
 #include "vport.h"
 
 static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
-			      const struct nlattr *attr, int len, bool keep_skb);
+			      const struct nlattr *attr, int len,
+			      bool keep_skb, const struct sw_flow_key *pkt_key);
 
 static int make_writable(struct sk_buff *skb, int write_len)
 {
@@ -378,14 +379,15 @@ static int do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
 }
 
 static int output_userspace(struct datapath *dp, struct sk_buff *skb,
-			    const struct nlattr *attr)
+			    const struct nlattr *attr,
+			    const struct sw_flow_key *pkt_key)
 {
 	struct dp_upcall_info upcall;
 	const struct nlattr *a;
 	int rem;
 
 	upcall.cmd = OVS_PACKET_CMD_ACTION;
-	upcall.key = &OVS_CB(skb)->flow->key;
+	upcall.key = pkt_key;
 	upcall.userdata = NULL;
 	upcall.portid = 0;
 
@@ -406,7 +408,7 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb,
 }
 
 static int sample(struct datapath *dp, struct sk_buff *skb,
-		  const struct nlattr *attr)
+		  const struct nlattr *attr, const struct sw_flow_key *pkt_key)
 {
 	const struct nlattr *acts_list = NULL;
 	const struct nlattr *a;
@@ -427,7 +429,7 @@ static int sample(struct datapath *dp, struct sk_buff *skb,
 	}
 
 	return do_execute_actions(dp, skb, nla_data(acts_list),
-				  nla_len(acts_list), true);
+				  nla_len(acts_list), true, pkt_key);
 }
 
 static int execute_set_action(struct sk_buff *skb,
@@ -474,7 +476,8 @@ static int execute_set_action(struct sk_buff *skb,
 
 /* Execute a list of actions against 'skb'. */
 static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
-			const struct nlattr *attr, int len, bool keep_skb)
+			const struct nlattr *attr, int len,
+			bool keep_skb, const struct sw_flow_key *pkt_key)
 {
 	/* Every output action needs a separate clone of 'skb', but the common
 	 * case is just a single output action, so that doing a clone and
@@ -499,7 +502,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			break;
 
 		case OVS_ACTION_ATTR_USERSPACE:
-			output_userspace(dp, skb, a);
+			output_userspace(dp, skb, a, pkt_key);
 			break;
 
 		case OVS_ACTION_ATTR_PUSH_VLAN:
@@ -517,7 +520,7 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb,
 			break;
 
 		case OVS_ACTION_ATTR_SAMPLE:
-			err = sample(dp, skb, a);
+			err = sample(dp, skb, a, pkt_key);
 			break;
 		}
 
@@ -559,7 +562,8 @@ static int loop_suppress(struct datapath *dp, struct sw_flow_actions *actions)
 }
 
 /* Execute a list of actions against 'skb'. */
-int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
+int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
+		const struct sw_flow_key *pkt_key)
 {
 	struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts);
 	struct loop_counter *loop;
@@ -577,7 +581,7 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb)
 
 	OVS_CB(skb)->tun_key = NULL;
 	error = do_execute_actions(dp, skb, acts->actions,
-					 acts->actions_len, false);
+					 acts->actions_len, false, pkt_key);
 
 	/* Check whether sub-actions looped too much. */
 	if (unlikely(loop->looping))
diff --git a/datapath/datapath.c b/datapath/datapath.c
index a514e74..a58451c 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -263,7 +263,7 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 
 	stats_counter = &stats->n_hit;
 	ovs_flow_used(OVS_CB(skb)->flow, skb);
-	ovs_execute_actions(dp, skb);
+	ovs_execute_actions(dp, skb, &key);
 
 out:
 	/* Update datapath statistics. */
@@ -933,7 +933,7 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 		goto err_unlock;
 
 	local_bh_disable();
-	err = ovs_execute_actions(dp, packet);
+	err = ovs_execute_actions(dp, packet, &flow->key);
 	local_bh_enable();
 	rcu_read_unlock();
 
diff --git a/datapath/datapath.h b/datapath/datapath.h
index ad59a3a..722ab2c 100644
--- a/datapath/datapath.h
+++ b/datapath/datapath.h
@@ -200,6 +200,7 @@ const char *ovs_dp_name(const struct datapath *dp);
 struct sk_buff *ovs_vport_cmd_build_info(struct vport *, u32 portid, u32 seq,
 					 u8 cmd);
 
-int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb);
+int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb,
+			const struct sw_flow_key *pkt_key);
 void ovs_dp_notify_wq(struct work_struct *work);
 #endif /* datapath.h */
-- 
1.7.9.5




More information about the dev mailing list