lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
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