[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <2b77b94f043dbed36a08dcc0a876830d6ad1a97a.1385137618.git.tgraf@suug.ch>
Date: Fri, 22 Nov 2013 17:56:09 +0100
From: Thomas Graf <tgraf@...g.ch>
To: jesse@...ira.com, davem@...emloft.net
Cc: dev@...nvswitch.org, netdev@...r.kernel.org, dborkman@...hat.com,
ffusco@...hat.com, fleitner@...hat.com, eric.dumazet@...il.com,
bhutchings@...arflare.com
Subject: [PATCH net-next 6/8] openvswitch: Allow update of dp with OVS_DP_CMD_NEW if NLM_F_REPLACE is set
Consolidates ovs_dp_cmd_new() and ovs_dp_cmd_set() to simplify
handling and avoid code duplication.
Allows user space to specify NLM_F_REPLACE with OVS_DP_CMD_NEW and
overwrite the settings such as the user features of an existing
datapath.
Signed-off-by: Thomas Graf <tgraf@...g.ch>
Reviewed-by: Daniel Borkmann <dborkman@...hat.com>
---
net/openvswitch/datapath.c | 83 +++++++++++++++++++++++-----------------------
1 file changed, 42 insertions(+), 41 deletions(-)
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 95d4424..3f1fb87 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -1175,13 +1175,8 @@ static struct datapath *lookup_datapath(struct net *net,
return dp ? dp : ERR_PTR(-ENODEV);
}
-static void ovs_dp_change(struct datapath *dp, struct nlattr **a)
-{
- if (a[OVS_DP_ATTR_USER_FEATURES])
- dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
-}
-
-static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
+static int ovs_dp_create_or_update(struct sk_buff *skb, struct genl_info *info,
+ bool create)
{
struct nlattr **a = info->attrs;
struct vport_parms parms;
@@ -1190,6 +1185,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
struct vport *vport;
struct ovs_net *ovs_net;
int err, i;
+ bool allocated = false;
err = -EINVAL;
if (!a[OVS_DP_ATTR_NAME] || !a[OVS_DP_ATTR_UPCALL_PID])
@@ -1197,11 +1193,26 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
ovs_lock();
+ dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
+ if (!IS_ERR(dp)) {
+ if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
+ goto update;
+
+ err = -EEXIST;
+ goto err_unlock_ovs;
+ }
+
+ if (!create) {
+ err = PTR_ERR(dp);
+ goto err_unlock_ovs;
+ }
+
err = -ENOMEM;
dp = kzalloc(sizeof(*dp), GFP_KERNEL);
if (dp == NULL)
goto err_unlock_ovs;
+ allocated = true;
ovs_dp_set_net(dp, hold_net(sock_net(skb->sk)));
/* Allocate table. */
@@ -1239,8 +1250,6 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
parms.port_no = OVSP_LOCAL;
parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]);
- ovs_dp_change(dp, a);
-
vport = new_vport(&parms);
if (IS_ERR(vport)) {
err = PTR_ERR(vport);
@@ -1250,13 +1259,27 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
goto err_destroy_ports_array;
}
+update:
+ if (a[OVS_DP_ATTR_USER_FEATURES])
+ dp->user_features = nla_get_u32(a[OVS_DP_ATTR_USER_FEATURES]);
+
reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
err = PTR_ERR(reply);
- if (IS_ERR(reply))
- goto err_destroy_local_port;
+ if (IS_ERR(reply)) {
+ if (allocated)
+ goto err_destroy_local_port;
+ else {
+ err = 0;
+ genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
+ 0, err);
+ goto err_unlock_ovs;
+ }
+ }
- ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
- list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
+ if (allocated) {
+ ovs_net = net_generic(ovs_dp_get_net(dp), ovs_net_id);
+ list_add_tail_rcu(&dp->list_node, &ovs_net->dps);
+ }
ovs_unlock();
@@ -1280,6 +1303,11 @@ err:
return err;
}
+static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info)
+{
+ return ovs_dp_create_or_update(skb, info, true);
+}
+
/* Called with ovs_mutex. */
static void __dp_destroy(struct datapath *dp)
{
@@ -1334,34 +1362,7 @@ unlock:
static int ovs_dp_cmd_set(struct sk_buff *skb, struct genl_info *info)
{
- struct sk_buff *reply;
- struct datapath *dp;
- int err;
-
- ovs_lock();
- dp = lookup_datapath(sock_net(skb->sk), info->userhdr, info->attrs);
- err = PTR_ERR(dp);
- if (IS_ERR(dp))
- goto unlock;
-
- ovs_dp_change(dp, info->attrs);
-
- reply = ovs_dp_cmd_build_info(dp, info, OVS_DP_CMD_NEW);
- if (IS_ERR(reply)) {
- err = PTR_ERR(reply);
- genl_set_err(&dp_datapath_genl_family, sock_net(skb->sk), 0,
- 0, err);
- err = 0;
- goto unlock;
- }
-
- ovs_unlock();
- ovs_notify(&dp_datapath_genl_family, reply, info);
-
- return 0;
-unlock:
- ovs_unlock();
- return err;
+ return ovs_dp_create_or_update(skb, info, false);
}
static int ovs_dp_cmd_get(struct sk_buff *skb, struct genl_info *info)
--
1.8.3.1
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists