[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