Fixed according to comments from Jesse. --8<--------------------------cut here-------------------------->8--
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 <pshe...@nicira.com> --- net/openvswitch/datapath.c | 66 ++++++++++++++++------------------ net/openvswitch/flow.c | 36 +++++------------- net/openvswitch/flow.h | 7 +--- net/openvswitch/vport-internal_dev.c | 2 - net/openvswitch/vport.c | 2 - 5 files changed, 42 insertions(+), 71 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 bab1336..77c16c7 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..b98596f 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. */ @@ -130,13 +127,11 @@ void flow_exit(void); struct sw_flow *flow_alloc(void); void flow_deferred_free(struct sw_flow *); +void flow_free(struct sw_flow *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 *); - 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 *); diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 7b8e1e9..89f7be4 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c @@ -74,8 +74,6 @@ static int internal_dev_mac_addr(struct net_device *dev, void *p) /* Called with rcu_read_lock_bh. */ static int internal_dev_xmit(struct sk_buff *skb, struct net_device *netdev) { - OVS_CB(skb)->flow = NULL; - rcu_read_lock(); vport_receive(internal_dev_priv(netdev)->vport, skb); rcu_read_unlock(); diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index c9488e0..25c311c 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c @@ -332,8 +332,6 @@ void vport_receive(struct vport *vport, struct sk_buff *skb) stats->rx_bytes += skb->len; write_seqcount_end(&stats->seqlock); - OVS_CB(skb)->flow = NULL; - dp_process_received_packet(vport, skb); } -- 1.7.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev