On Tue, Mar 25, 2014 at 2:35 PM, Jarno Rajahalme <[email protected]> wrote:
> Signed-off-by: Jarno Rajahalme <[email protected]>
> ---
> v5: Make functionality after ovs_unlock() case specific to make the common
> case more optimal.
>
> datapath/datapath.c | 135
> ++++++++++++++++++++++++++++++---------------------
> 1 file changed, 81 insertions(+), 54 deletions(-)
>
> diff --git a/datapath/datapath.c b/datapath/datapath.c
> index 0de00ad..aa3f789 100644
> --- a/datapath/datapath.c
> +++ b/datapath/datapath.c
> @@ -808,7 +808,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct
> genl_info *info)
> struct nlattr **a = info->attrs;
> struct ovs_header *ovs_header = info->userhdr;
> struct sw_flow_key key, masked_key;
> - struct sw_flow *flow;
> + struct sw_flow *flow, *new_flow;
> struct sw_flow_mask mask;
> struct sk_buff *reply;
> struct datapath *dp;
> @@ -842,35 +842,52 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct
> genl_info *info)
> &masked_key, 0, &acts);
> if (error) {
> OVS_NLERR("Flow actions may not be safe on all matching
> packets.\n");
> - goto err_kfree;
> + goto err_kfree_acts;
> + }
> +
> + reply = ovs_flow_cmd_alloc_info(acts, info, false);
> + if (IS_ERR(reply)) {
> + error = PTR_ERR(reply);
> + goto err_kfree_acts;
> }
>
> + /* Most of the time we need to allocate a new flow, do it before
> + * locking. */
> + new_flow = ovs_flow_alloc();
> + if (IS_ERR(new_flow)) {
> + error = PTR_ERR(new_flow);
> + goto err_kfree_reply;
> + }
> + new_flow->key = masked_key;
> + new_flow->unmasked_key = key;
> +
If flow alloc is done at start, we can directly use flow->key and
flow->unmasked_key rather than using local key and unmasked_key.
> ovs_lock();
> dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
> error = -ENODEV;
> - if (!dp)
> + if (unlikely(!dp))
> goto err_unlock_ovs;
>
> /* Check if this is a duplicate flow */
> flow = ovs_flow_tbl_lookup(&dp->table, &key);
> - if (!flow) {
> - /* Allocate flow. */
> - flow = ovs_flow_alloc();
> - if (IS_ERR(flow)) {
> - error = PTR_ERR(flow);
> - goto err_unlock_ovs;
> - }
> -
> - flow->key = masked_key;
> - flow->unmasked_key = key;
> - rcu_assign_pointer(flow->sf_acts, acts);
> + if (likely(!flow)) {
> + rcu_assign_pointer(new_flow->sf_acts, acts);
>
> /* Put flow in bucket. */
> - error = ovs_flow_tbl_insert(&dp->table, flow, &mask);
> - if (error) {
> + error = ovs_flow_tbl_insert(&dp->table, new_flow, &mask);
> + if (unlikely(error)) {
> acts = NULL;
> - goto err_flow_free;
> + goto err_unlock_ovs;
> }
> +
> + if (unlikely(reply)) {
> + error = ovs_flow_cmd_fill_info(new_flow,
> + ovs_header->dp_ifindex,
> + reply,
> info->snd_portid,
> + info->snd_seq, 0,
> + OVS_FLOW_CMD_NEW);
> + BUG_ON(error < 0);
> + }
> + ovs_unlock();
> } else {
> struct sw_flow_actions *old_acts;
>
> @@ -881,38 +898,42 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct
> genl_info *info)
> * gets fixed.
> */
> error = -EEXIST;
> - if (info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL))
> + if (unlikely(info->nlhdr->nlmsg_flags & (NLM_F_CREATE
> + | NLM_F_EXCL)))
> goto err_unlock_ovs;
>
> /* The unmasked key has to be the same for flow updates. */
> - if (!ovs_flow_cmp_unmasked_key(flow, &match))
> + if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match)))
> goto err_unlock_ovs;
>
> /* Update actions. */
> old_acts = ovsl_dereference(flow->sf_acts);
> rcu_assign_pointer(flow->sf_acts, acts);
> - ovs_nla_free_flow_actions(old_acts);
> - }
>
> - reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
> - info, OVS_FLOW_CMD_NEW, false);
> - ovs_unlock();
> + if (unlikely(reply)) {
> + error = ovs_flow_cmd_fill_info(flow,
> + ovs_header->dp_ifindex,
> + reply,
> info->snd_portid,
> + info->snd_seq, 0,
> + OVS_FLOW_CMD_NEW);
> + BUG_ON(error < 0);
> + }
> + ovs_unlock();
>
> - if (reply) {
> - if (!IS_ERR(reply))
> - ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> - else
> - netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
> - ovs_dp_flow_multicast_group.id,
> - PTR_ERR(reply));
> + ovs_nla_free_flow_actions(old_acts);
> + ovs_flow_free(new_flow, false);
> }
> +
> + if (reply)
> + ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> return 0;
>
> -err_flow_free:
> - ovs_flow_free(flow, false);
> err_unlock_ovs:
> ovs_unlock();
> -err_kfree:
> + ovs_flow_free(new_flow, false);
> +err_kfree_reply:
> + kfree_skb(reply);
> +err_kfree_acts:
> kfree(acts);
> error:
> return error;
> @@ -927,7 +948,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct
> genl_info *info)
> struct sw_flow_mask mask;
> struct sk_buff *reply = NULL;
> struct datapath *dp;
> - struct sw_flow_actions *acts = NULL;
> + struct sw_flow_actions *old_acts = NULL, *acts = NULL;
> struct sw_flow_match match;
> int error;
>
> @@ -954,55 +975,61 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct
> genl_info *info)
> &masked_key, 0, &acts);
> if (error) {
> OVS_NLERR("Flow actions may not be safe on all
> matching packets.\n");
> - goto err_kfree;
> + goto err_kfree_acts;
> }
> }
>
> + reply = ovs_flow_cmd_alloc_info(acts, info, false);
> + if (IS_ERR(reply)) {
> + error = PTR_ERR(reply);
> + goto err_kfree_acts;
> + }
> +
> ovs_lock();
> dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
> error = -ENODEV;
> - if (!dp)
> + if (unlikely(!dp))
> goto err_unlock_ovs;
>
> - /* Check if this is a duplicate flow */
> + /* Check if the flow exists. */
> flow = ovs_flow_tbl_lookup(&dp->table, &key);
> error = -ENOENT;
> - if (!flow)
> + if (unlikely(!flow))
> goto err_unlock_ovs;
>
> /* The unmasked key has to be the same for flow updates. */
> - if (!ovs_flow_cmp_unmasked_key(flow, &match))
> + if (unlikely(!ovs_flow_cmp_unmasked_key(flow, &match)))
> goto err_unlock_ovs;
>
> /* Update actions, if present. */
> if (acts) {
> - struct sw_flow_actions *old_acts;
> -
> old_acts = ovsl_dereference(flow->sf_acts);
> rcu_assign_pointer(flow->sf_acts, acts);
> - ovs_nla_free_flow_actions(old_acts);
> }
>
> - reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
> - info, OVS_FLOW_CMD_NEW, false);
> + if (reply) {
> + error = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
> + reply, info->snd_portid,
> + info->snd_seq, 0,
> + OVS_FLOW_CMD_NEW);
> + BUG_ON(error < 0);
> + }
> +
> /* Clear stats. */
> if (a[OVS_FLOW_ATTR_CLEAR])
> ovs_flow_stats_clear(flow);
> ovs_unlock();
>
> - if (reply) {
> - if (!IS_ERR(reply))
> - ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> - else
> - netlink_set_err(sock_net(skb->sk)->genl_sock, 0,
> - ovs_dp_flow_multicast_group.id,
> - PTR_ERR(reply));
> - }
> + if (reply)
> + ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
> + if (old_acts)
> + ovs_nla_free_flow_actions(old_acts);
> return 0;
>
> err_unlock_ovs:
> ovs_unlock();
> -err_kfree:
> + kfree_skb(reply);
> +err_kfree_acts:
> kfree(acts);
> error:
> return error;
> --
> 1.7.10.4
>
> _______________________________________________
> dev mailing list
> [email protected]
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
[email protected]
http://openvswitch.org/mailman/listinfo/dev