This helps reduce calls to ksize(). Also add support for statically alloced actions, which will be used by a subsequent patch.
Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> --- datapath/datapath.c | 2 +- datapath/flow.h | 2 ++ datapath/flow_netlink.c | 20 +++++++++++++++----- datapath/flow_netlink.h | 2 +- 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/datapath/datapath.c b/datapath/datapath.c index 1599d70..a46ceb0 100644 --- a/datapath/datapath.c +++ b/datapath/datapath.c @@ -882,7 +882,7 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info *info) /* Update actions. */ old_acts = ovsl_dereference(flow->sf_acts); rcu_assign_pointer(flow->sf_acts, acts); - ovs_nla_free_flow_actions(old_acts); + ovs_nla_free_flow_actions(old_acts, true); /* Clear stats. */ if (a[OVS_FLOW_ATTR_CLEAR]) diff --git a/datapath/flow.h b/datapath/flow.h index f6cce35..441fdee 100644 --- a/datapath/flow.h +++ b/datapath/flow.h @@ -146,6 +146,8 @@ struct sw_flow_match { struct sw_flow_actions { struct rcu_head rcu; u32 actions_len; + u32 alloc_size; + bool alloced; struct nlattr actions[]; }; diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c index 3024a61..5bcf258 100644 --- a/datapath/flow_netlink.c +++ b/datapath/flow_netlink.c @@ -1127,6 +1127,9 @@ struct sw_flow_actions *ovs_nla_alloc_flow_actions(int size) return ERR_PTR(-ENOMEM); sfa->actions_len = 0; + sfa->alloc_size = ksize(sfa); + sfa->alloced = true; + return sfa; } @@ -1140,11 +1143,17 @@ static void rcu_free_acts_callback(struct rcu_head *rcu) /* Schedules 'sf_acts' to be freed after the next RCU grace period. * The caller must hold rcu_read_lock for this to be sensible. */ -void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts) +void ovs_nla_free_flow_actions(struct sw_flow_actions *sf_acts, bool deferred) { - call_rcu(&sf_acts->rcu, rcu_free_acts_callback); + if (sf_acts->alloced) { + if (deferred) + call_rcu(&sf_acts->rcu, rcu_free_acts_callback); + else + kfree(sf_acts); + } } +/* May only be called before actions are placed in to the flow table. */ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, int attr_len) { @@ -1155,10 +1164,10 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, int next_offset = offsetof(struct sw_flow_actions, actions) + (*sfa)->actions_len; - if (req_size <= (ksize(*sfa) - next_offset)) + if (req_size <= ((*sfa)->alloc_size - next_offset)) goto out; - new_acts_size = ksize(*sfa) * 2; + new_acts_size = (*sfa)->alloc_size * 2; if (new_acts_size > MAX_ACTIONS_BUFSIZE) { if ((MAX_ACTIONS_BUFSIZE - next_offset) < req_size) @@ -1172,7 +1181,8 @@ static struct nlattr *reserve_sfa_size(struct sw_flow_actions **sfa, memcpy(acts->actions, (*sfa)->actions, (*sfa)->actions_len); acts->actions_len = (*sfa)->actions_len; - kfree(*sfa); + + ovs_nla_free_flow_actions(*sfa, false); *sfa = acts; out: diff --git a/datapath/flow_netlink.h b/datapath/flow_netlink.h index 4401510..786f93f 100644 --- a/datapath/flow_netlink.h +++ b/datapath/flow_netlink.h @@ -55,6 +55,6 @@ int ovs_nla_put_actions(const struct nlattr *attr, int len, struct sk_buff *skb); struct sw_flow_actions *ovs_nla_alloc_flow_actions(int actions_len); -void ovs_nla_free_flow_actions(struct sw_flow_actions *); +void ovs_nla_free_flow_actions(struct sw_flow_actions *, bool deferred); #endif /* flow_netlink.h */ -- 1.7.10.4 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev