On Tue, Mar 25, 2014 at 2:35 PM, Jarno Rajahalme <jrajaha...@nicira.com> wrote: > Following patch will be easier to reason about with separate > ovs_flow_cmd_new() and ovs_flow_cmd_set() functions. > > Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com> > --- > datapath/datapath.c | 160 > +++++++++++++++++++++++++++++++++++++-------------- > 1 file changed, 116 insertions(+), 44 deletions(-) > > diff --git a/datapath/datapath.c b/datapath/datapath.c > index a13208c..2901d69 100644 > --- a/datapath/datapath.c > +++ b/datapath/datapath.c > @@ -805,16 +805,16 @@ static struct sk_buff *ovs_flow_cmd_build_info(const > struct sw_flow *flow, > return skb; > } > > -static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, struct genl_info > *info) > +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 = NULL; > + struct sw_flow *flow; > struct sw_flow_mask mask; > struct sk_buff *reply; > struct datapath *dp; > - struct sw_flow_actions *acts = NULL; > + struct sw_flow_actions *acts; > struct sw_flow_match match; > int error; > > @@ -830,23 +830,21 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, > struct genl_info *info) > goto error; > > /* Validate actions. */ > - if (a[OVS_FLOW_ATTR_ACTIONS]) { > - acts = > ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); > - error = PTR_ERR(acts); > - if (IS_ERR(acts)) > - goto error; > + error = -EINVAL; > + if (!a[OVS_FLOW_ATTR_ACTIONS]) > + goto error; > > - ovs_flow_mask_key(&masked_key, &key, &mask); > - error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], > - &masked_key, 0, &acts); > - if (error) { > - OVS_NLERR("Flow actions may not be safe on all > matching packets.\n"); > - goto err_kfree; > - } > - } else if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW) { > - /* OVS_FLOW_CMD_NEW must have actions. */ > - error = -EINVAL; > + acts = ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); > + error = PTR_ERR(acts); > + if (IS_ERR(acts)) > goto error; > + > + ovs_flow_mask_key(&masked_key, &key, &mask); > + error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], > + &masked_key, 0, &acts); > + if (error) { > + OVS_NLERR("Flow actions may not be safe on all matching > packets.\n"); > + goto err_kfree; > } > > ovs_lock(); > @@ -858,11 +856,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, > struct genl_info *info) > /* Check if this is a duplicate flow */ > flow = ovs_flow_tbl_lookup(&dp->table, &key); > if (!flow) { > - /* Bail out if we're not allowed to create a new flow. */ > - error = -ENOENT; > - if (info->genlhdr->cmd == OVS_FLOW_CMD_SET) > - goto err_unlock_ovs; > - > /* Allocate flow. */ > flow = ovs_flow_alloc(); > if (IS_ERR(flow)) { > @@ -880,11 +873,9 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, > struct genl_info *info) > acts = NULL; > goto err_flow_free; > } > - > - reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, > - info, OVS_FLOW_CMD_NEW, > false); > } else { > - /* We found a matching flow. */ > + struct sw_flow_actions *old_acts; > + > /* Bail out if we're not allowed to modify an existing flow. > * We accept NLM_F_CREATE in place of the intended NLM_F_EXCL > * because Generic Netlink treats the latter as a dump > @@ -892,30 +883,113 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff > *skb, struct genl_info *info) > * gets fixed. > */ > error = -EEXIST; > - if (info->genlhdr->cmd == OVS_FLOW_CMD_NEW && > - info->nlhdr->nlmsg_flags & (NLM_F_CREATE | NLM_F_EXCL)) > + if (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)) > goto err_unlock_ovs; > > - /* Update actions, if present. */ > - if (acts) { > - struct sw_flow_actions *old_acts; > + /* Update actions. */ > + old_acts = ovsl_dereference(flow->sf_acts); > + rcu_assign_pointer(flow->sf_acts, acts); > + ovs_nla_free_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); > + 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)); > + } > + return 0; > + > +err_flow_free: > + ovs_flow_free(flow, false); > +err_unlock_ovs: > + ovs_unlock(); > +err_kfree: > + kfree(acts); > +error: > + return error; > +} > + > +static int ovs_flow_cmd_set(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_mask mask; > + struct sk_buff *reply = NULL; > + struct datapath *dp; > + struct sw_flow_actions *acts = NULL; > + struct sw_flow_match match; > + int error; > + > + /* Extract key. */ > + error = -EINVAL; > + if (!a[OVS_FLOW_ATTR_KEY]) > + goto error; > + > + ovs_match_init(&match, &key, &mask); > + error = ovs_nla_get_match(&match, > + a[OVS_FLOW_ATTR_KEY], > a[OVS_FLOW_ATTR_MASK]); > + if (error) > + goto error; > + > + /* Validate actions. */ > + if (a[OVS_FLOW_ATTR_ACTIONS]) { > + acts = > ovs_nla_alloc_flow_actions(nla_len(a[OVS_FLOW_ATTR_ACTIONS])); > + error = PTR_ERR(acts); > + if (IS_ERR(acts)) > + goto error; > + > + ovs_flow_mask_key(&masked_key, &key, &mask); > + error = ovs_nla_copy_actions(a[OVS_FLOW_ATTR_ACTIONS], > + &masked_key, 0, &acts); > + if (error) { > + OVS_NLERR("Flow actions may not be safe on all > matching packets.\n"); > + goto err_kfree; > } > + } > > - reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, > - info, OVS_FLOW_CMD_NEW, > false); > + ovs_lock(); > + dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex); > + error = -ENODEV; > + if (!dp) > + goto err_unlock_ovs; > > - /* Clear stats. */ > - if (a[OVS_FLOW_ATTR_CLEAR]) > - ovs_flow_stats_clear(flow); > + /* Check if this is a duplicate flow */ This is not clear comment for cmd_set.
> + flow = ovs_flow_tbl_lookup(&dp->table, &key); > + error = -ENOENT; > + if (!flow) > + goto err_unlock_ovs; > + > + /* The unmasked key has to be the same for flow updates. */ > + if (!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); hy not use OVS_FLOW_CMD_SET, to build reply? > + /* Clear stats. */ > + if (a[OVS_FLOW_ATTR_CLEAR]) > + ovs_flow_stats_clear(flow); > ovs_unlock(); > > if (reply) { > @@ -928,8 +1002,6 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, > struct genl_info *info) > } > return 0; > > -err_flow_free: > - ovs_flow_free(flow, false); > err_unlock_ovs: > ovs_unlock(); > err_kfree: > @@ -1081,7 +1153,7 @@ static struct genl_ops dp_flow_genl_ops[] = { > { .cmd = OVS_FLOW_CMD_NEW, > .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ > .policy = flow_policy, > - .doit = ovs_flow_cmd_new_or_set > + .doit = ovs_flow_cmd_new > }, > { .cmd = OVS_FLOW_CMD_DEL, > .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ > @@ -1097,7 +1169,7 @@ static struct genl_ops dp_flow_genl_ops[] = { > { .cmd = OVS_FLOW_CMD_SET, > .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ > .policy = flow_policy, > - .doit = ovs_flow_cmd_new_or_set, > + .doit = ovs_flow_cmd_set, > }, > }; > otherwise looks good. Acked-by: Pravin B Shelar <pshe...@nicira.com> > -- > 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