Signed-off-by: Jarno Rajahalme <jrajaha...@nicira.com>
---
 datapath/datapath.c |   75 ++++++++++++++++++++++++++-------------------------
 1 file changed, 39 insertions(+), 36 deletions(-)

diff --git a/datapath/datapath.c b/datapath/datapath.c
index 452b889..cbdd68f 100644
--- a/datapath/datapath.c
+++ b/datapath/datapath.c
@@ -655,7 +655,7 @@ static size_t ovs_flow_cmd_msg_size(const struct 
sw_flow_actions *acts)
 }
 
 /* Called with ovs_mutex or RCU read lock. */
-static int ovs_flow_cmd_fill_info(struct sw_flow *flow, struct datapath *dp,
+static int ovs_flow_cmd_fill_info(struct sw_flow *flow, int dp_ifindex,
                                  struct sk_buff *skb, u32 portid,
                                  u32 seq, u32 flags, u8 cmd)
 {
@@ -672,7 +672,7 @@ static int ovs_flow_cmd_fill_info(struct sw_flow *flow, 
struct datapath *dp,
        if (!ovs_header)
                return -EMSGSIZE;
 
-       ovs_header->dp_ifindex = get_dpifindex(dp);
+       ovs_header->dp_ifindex = dp_ifindex;
 
        /* Fill flow key. */
        nla = nla_nest_start(skb, OVS_FLOW_ATTR_KEY);
@@ -758,9 +758,8 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(struct 
sw_flow *flow,
 
 /* Must be called with ovs_mutex. */
 static struct sk_buff *ovs_flow_cmd_build_info(struct sw_flow *flow,
-                                              struct datapath *dp,
-                                              struct genl_info *info,
-                                              u8 cmd)
+                                              int dp_ifindex,
+                                              struct genl_info *info, u8 cmd)
 {
        struct sk_buff *skb;
        int retval;
@@ -769,8 +768,9 @@ static struct sk_buff *ovs_flow_cmd_build_info(struct 
sw_flow *flow,
        if (!skb)
                return ERR_PTR(-ENOMEM);
 
-       retval = ovs_flow_cmd_fill_info(flow, dp, skb, info->snd_portid,
-                                       info->snd_seq, 0, cmd);
+       retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb,
+                                       info->snd_portid, info->snd_seq, 0,
+                                       cmd);
        BUG_ON(retval < 0);
        return skb;
 }
@@ -857,7 +857,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
                        goto err_flow_free;
                }
 
-               reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
+               reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
+                                               info, OVS_FLOW_CMD_NEW);
        } else {
                /* We found a matching flow. */
                struct sw_flow_actions *old_acts;
@@ -882,8 +883,8 @@ static int ovs_flow_cmd_new_or_set(struct sk_buff *skb, 
struct genl_info *info)
                rcu_assign_pointer(flow->sf_acts, acts);
                ovs_nla_free_flow_actions(old_acts);
 
-               reply = ovs_flow_cmd_build_info(flow, dp, info, 
OVS_FLOW_CMD_NEW);
-
+               reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex,
+                                               info, OVS_FLOW_CMD_NEW);
                /* Clear stats. */
                if (a[OVS_FLOW_ATTR_CLEAR])
                        ovs_flow_stats_clear(flow);
@@ -941,7 +942,8 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct 
genl_info *info)
                goto unlock;
        }
 
-       reply = ovs_flow_cmd_build_info(flow, dp, info, OVS_FLOW_CMD_NEW);
+       reply = ovs_flow_cmd_build_info(flow, ovs_header->dp_ifindex, info,
+                                       OVS_FLOW_CMD_NEW);
        if (IS_ERR(reply)) {
                err = PTR_ERR(reply);
                goto unlock;
@@ -965,47 +967,48 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct 
genl_info *info)
        struct sw_flow_match match;
        int err;
 
+       if (a[OVS_FLOW_ATTR_KEY]) {
+               ovs_match_init(&match, &key, NULL);
+               err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
+               if (err)
+                       return err;
+       }
+
        ovs_lock();
        dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
        if (!dp) {
                err = -ENODEV;
-               goto unlock;
+               goto ovs_unlock;
        }
-
        if (!a[OVS_FLOW_ATTR_KEY]) {
                err = ovs_flow_tbl_flush(&dp->table);
-               goto unlock;
+               /* No reply in this case, so any existing stats are lost. */
+               goto ovs_unlock;
        }
-
-       ovs_match_init(&match, &key, NULL);
-       err = ovs_nla_get_match(&match, a[OVS_FLOW_ATTR_KEY], NULL);
-       if (err)
-               goto unlock;
-
        flow = ovs_flow_tbl_lookup(&dp->table, &key);
        if (!flow || !ovs_flow_cmp_unmasked_key(flow, &match)) {
                err = -ENOENT;
-               goto unlock;
+               goto ovs_unlock;
        }
+       ovs_flow_tbl_remove(&dp->table, flow);
+       ovs_unlock();
 
        reply = ovs_flow_cmd_alloc_info(flow, info);
-       if (!reply) {
-               err = -ENOMEM;
-               goto unlock;
+       /* XXX: We may skip sending a response if kernel is out of memory.
+        * We could do the allocation before locking if we did not need
+        * to return the actions (which are useless in this case anyway). */
+       if (reply) {
+               err = ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex,
+                                            reply, info->snd_portid,
+                                            info->snd_seq, 0,
+                                            OVS_FLOW_CMD_DEL);
+               BUG_ON(err < 0);
+               ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
        }
-
-       ovs_flow_tbl_remove(&dp->table, flow);
-
-       err = ovs_flow_cmd_fill_info(flow, dp, reply, info->snd_portid,
-                                    info->snd_seq, 0, OVS_FLOW_CMD_DEL);
-       BUG_ON(err < 0);
-
        ovs_flow_free(flow, true);
-       ovs_unlock();
-
-       ovs_notify(reply, info, &ovs_dp_flow_multicast_group);
        return 0;
-unlock:
+
+ovs_unlock:
        ovs_unlock();
        return err;
 }
@@ -1034,7 +1037,7 @@ static int ovs_flow_cmd_dump(struct sk_buff *skb, struct 
netlink_callback *cb)
                if (!flow)
                        break;
 
-               if (ovs_flow_cmd_fill_info(flow, dp, skb,
+               if (ovs_flow_cmd_fill_info(flow, ovs_header->dp_ifindex, skb,
                                           NETLINK_CB(cb->skb).portid,
                                           cb->nlh->nlmsg_seq, NLM_F_MULTI,
                                           OVS_FLOW_CMD_NEW) < 0)
-- 
1.7.10.4

_______________________________________________
dev mailing list
dev@openvswitch.org
http://openvswitch.org/mailman/listinfo/dev

Reply via email to