On Tue, Mar 25, 2014 at 2:35 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote:
> Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
> ---
> 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
> dev@openvswitch.org
> http://openvswitch.org/mailman/listinfo/dev
_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to