[ovs-dev] [PATCH upstream] net-ovs: Remove flow refcnt.

Pravin B Shelar pshelar at nicira.com
Thu Nov 17 22:17:29 UTC 2011


Only tunneling code needs to keep ref to flow structure cached.
But upstream OVS does not have tunneling code. So we can safely
remove flow ref-counting.

Signed-off-by: Pravin B Shelar <pshelar at nicira.com>
---
 net/openvswitch/datapath.c |   66 ++++++++++++++++++++-----------------------
 net/openvswitch/flow.c     |   36 ++++++-----------------
 net/openvswitch/flow.h     |    7 +----
 3 files changed, 42 insertions(+), 67 deletions(-)

diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index bb095f8..04c4c71 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -182,41 +182,37 @@ void dp_process_received_packet(struct vport *p, struct sk_buff *skb)
 	struct datapath *dp = p->dp;
 	struct sw_flow *flow;
 	struct dp_stats_percpu *stats;
+	struct sw_flow_key key;
 	u64 *stats_counter;
 	int error;
+	int key_len;
 
 	stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id());
 
-	if (!OVS_CB(skb)->flow) {
-		struct sw_flow_key key;
-		int key_len;
-
-		/* Extract flow from 'skb' into 'key'. */
-		error = flow_extract(skb, p->port_no, &key, &key_len);
-		if (unlikely(error)) {
-			kfree_skb(skb);
-			return;
-		}
-
-		/* Look up flow. */
-		flow = flow_tbl_lookup(rcu_dereference(dp->table),
-				       &key, key_len);
-		if (unlikely(!flow)) {
-			struct dp_upcall_info upcall;
-
-			upcall.cmd = OVS_PACKET_CMD_MISS;
-			upcall.key = &key;
-			upcall.userdata = NULL;
-			upcall.pid = p->upcall_pid;
-			dp_upcall(dp, skb, &upcall);
-			consume_skb(skb);
-			stats_counter = &stats->n_missed;
-			goto out;
-		}
+	/* Extract flow from 'skb' into 'key'. */
+	error = flow_extract(skb, p->port_no, &key, &key_len);
+	if (unlikely(error)) {
+		kfree_skb(skb);
+		return;
+	}
 
-		OVS_CB(skb)->flow = flow;
+	/* Look up flow. */
+	flow = flow_tbl_lookup(rcu_dereference(dp->table), &key, key_len);
+	if (unlikely(!flow)) {
+		struct dp_upcall_info upcall;
+
+		upcall.cmd = OVS_PACKET_CMD_MISS;
+		upcall.key = &key;
+		upcall.userdata = NULL;
+		upcall.pid = p->upcall_pid;
+		dp_upcall(dp, skb, &upcall);
+		consume_skb(skb);
+		stats_counter = &stats->n_missed;
+		goto out;
 	}
 
+	OVS_CB(skb)->flow = flow;
+
 	stats_counter = &stats->n_hit;
 	flow_used(OVS_CB(skb)->flow, skb);
 	execute_actions(dp, skb);
@@ -644,24 +640,24 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 
 	err = flow_extract(packet, -1, &flow->key, &key_len);
 	if (err)
-		goto err_flow_put;
+		goto err_flow_free;
 
 	err = flow_metadata_from_nlattrs(&flow->key.phy.priority,
 					 &flow->key.phy.in_port,
 					 a[OVS_PACKET_ATTR_KEY]);
 	if (err)
-		goto err_flow_put;
+		goto err_flow_free;
 
 	err = validate_actions(a[OVS_PACKET_ATTR_ACTIONS], &flow->key, 0);
 	if (err)
-		goto err_flow_put;
+		goto err_flow_free;
 
 	flow->hash = flow_hash(&flow->key, key_len);
 
 	acts = flow_actions_alloc(a[OVS_PACKET_ATTR_ACTIONS]);
 	err = PTR_ERR(acts);
 	if (IS_ERR(acts))
-		goto err_flow_put;
+		goto err_flow_free;
 	rcu_assign_pointer(flow->sf_acts, acts);
 
 	OVS_CB(packet)->flow = flow;
@@ -678,13 +674,13 @@ static int ovs_packet_cmd_execute(struct sk_buff *skb, struct genl_info *info)
 	local_bh_enable();
 	rcu_read_unlock();
 
-	flow_put(flow);
+	flow_free(flow);
 	return err;
 
 err_unlock:
 	rcu_read_unlock();
-err_flow_put:
-	flow_put(flow);
+err_flow_free:
+	flow_free(flow);
 err_kfree_skb:
 	kfree_skb(packet);
 err:
@@ -996,7 +992,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info)
 	return 0;
 
 error_free_flow:
-	flow_put(flow);
+	flow_free(flow);
 error:
 	return error;
 }
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c
index 5893198..835da1a 100644
--- a/net/openvswitch/flow.c
+++ b/net/openvswitch/flow.c
@@ -279,9 +279,7 @@ struct sw_flow *flow_alloc(void)
 		return ERR_PTR(-ENOMEM);
 
 	spin_lock_init(&flow->lock);
-	atomic_set(&flow->refcnt, 1);
 	flow->sf_acts = NULL;
-	flow->dead = false;
 
 	return flow;
 }
@@ -339,12 +337,6 @@ struct flow_table *flow_tbl_alloc(int new_size)
 	return table;
 }
 
-static void flow_free(struct sw_flow *flow)
-{
-	flow->dead = true;
-	flow_put(flow);
-}
-
 void flow_tbl_destroy(struct flow_table *table)
 {
 	int i;
@@ -433,13 +425,21 @@ struct flow_table *flow_tbl_expand(struct flow_table *table)
 	return new_table;
 }
 
+void flow_free(struct sw_flow *flow)
+{
+	if (unlikely(!flow))
+		return;
+
+	kfree((struct sf_flow_acts __force *)flow->sf_acts);
+	kmem_cache_free(flow_cache, flow);
+}
+
 /* RCU callback used by flow_deferred_free. */
 static void rcu_free_flow_callback(struct rcu_head *rcu)
 {
 	struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
 
-	flow->dead = true;
-	flow_put(flow);
+	flow_free(flow);
 }
 
 /* Schedules 'flow' to be freed after the next RCU grace period.
@@ -449,22 +449,6 @@ void flow_deferred_free(struct sw_flow *flow)
 	call_rcu(&flow->rcu, rcu_free_flow_callback);
 }
 
-void flow_hold(struct sw_flow *flow)
-{
-	atomic_inc(&flow->refcnt);
-}
-
-void flow_put(struct sw_flow *flow)
-{
-	if (unlikely(!flow))
-		return;
-
-	if (atomic_dec_and_test(&flow->refcnt)) {
-		kfree((struct sf_flow_acts __force *)flow->sf_acts);
-		kmem_cache_free(flow_cache, flow);
-	}
-}
-
 /* RCU callback used by flow_deferred_free_acts. */
 static void rcu_free_acts_callback(struct rcu_head *rcu)
 {
diff --git a/net/openvswitch/flow.h b/net/openvswitch/flow.h
index 7d6abc0..8012ac9 100644
--- a/net/openvswitch/flow.h
+++ b/net/openvswitch/flow.h
@@ -101,9 +101,6 @@ struct sw_flow {
 	struct sw_flow_key key;
 	struct sw_flow_actions __rcu *sf_acts;
 
-	atomic_t refcnt;
-	bool dead;
-
 	spinlock_t lock;	/* Lock for values below. */
 	unsigned long used;	/* Last used time (in jiffies). */
 	u64 packet_count;	/* Number of packets matched. */
@@ -134,9 +131,7 @@ void flow_deferred_free(struct sw_flow *);
 struct sw_flow_actions *flow_actions_alloc(const struct nlattr *);
 void flow_deferred_free_acts(struct sw_flow_actions *);
 
-void flow_hold(struct sw_flow *);
-void flow_put(struct sw_flow *);
-
+void flow_free(struct sw_flow *flow);
 int flow_extract(struct sk_buff *, u16 in_port, struct sw_flow_key *,
 		 int *key_lenp);
 void flow_used(struct sw_flow *, struct sk_buff *);
-- 
1.7.1




More information about the dev mailing list