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  linux-hardening  linux-cve-announce  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:   Sat, 20 Apr 2019 12:29:19 +0200
From:   Jiri Pirko <jiri@...nulli.us>
To:     netdev@...r.kernel.org
Cc:     davem@...emloft.net, mlxsw@...lanox.com,
        jakub.kicinski@...ronome.com, dsahern@...il.com
Subject: [patch net-next v2 13/16] netdevsim: implement dev probe/remove skeleton with port initialization

From: Jiri Pirko <jiri@...lanox.com>

Implement netdevsim bus probing of netdevsim devices. For every probed
device create a devlink instance. According to the user-passed value,
create a number of ports represented by devlink port instances.

Signed-off-by: Jiri Pirko <jiri@...lanox.com>
---
v1->v2:
- changed port array to port list
- port struct are allocated separately
---
 drivers/net/netdevsim/bus.c       |  29 +++++++
 drivers/net/netdevsim/dev.c       | 129 ++++++++++++++++++++++++++----
 drivers/net/netdevsim/netdev.c    |  15 +---
 drivers/net/netdevsim/netdevsim.h |  15 +++-
 4 files changed, 160 insertions(+), 28 deletions(-)

diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 4471f5db50ee..46108a926890 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -194,6 +194,21 @@ static struct attribute *nsim_bus_attrs[] = {
 };
 ATTRIBUTE_GROUPS(nsim_bus);
 
+static int nsim_bus_probe(struct device *dev)
+{
+	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+
+	return nsim_dev_probe(nsim_bus_dev);
+}
+
+static int nsim_bus_remove(struct device *dev)
+{
+	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+
+	nsim_dev_remove(nsim_bus_dev);
+	return 0;
+}
+
 int nsim_num_vf(struct device *dev)
 {
 	struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
@@ -205,6 +220,8 @@ static struct bus_type nsim_bus = {
 	.name		= DRV_NAME,
 	.dev_name	= DRV_NAME,
 	.bus_groups	= nsim_bus_groups,
+	.probe		= nsim_bus_probe,
+	.remove		= nsim_bus_remove,
 	.num_vf		= nsim_num_vf,
 };
 
@@ -238,6 +255,18 @@ struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count)
 	return ERR_PTR(err);
 }
 
+struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns)
+{
+	struct nsim_bus_dev *nsim_bus_dev;
+
+	dev_hold(ns->netdev);
+	rtnl_unlock();
+	nsim_bus_dev = nsim_bus_dev_new(~0, 0);
+	rtnl_lock();
+	dev_put(ns->netdev);
+	return nsim_bus_dev;
+}
+
 void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
 {
 	device_unregister(&nsim_bus_dev->dev);
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index ef518d59afba..d2c030efba4a 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -17,6 +17,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/device.h>
+#include <linux/list.h>
 #include <linux/random.h>
 #include <linux/rtnetlink.h>
 #include <net/devlink.h>
@@ -45,6 +46,30 @@ static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
 	debugfs_remove_recursive(nsim_dev->ddir);
 }
 
+static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev,
+				      struct nsim_dev_port *nsim_dev_port)
+{
+	char port_ddir_name[16];
+	char dev_link_name[32];
+
+	sprintf(port_ddir_name, "%u", nsim_dev_port->port_index);
+	nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name,
+						 nsim_dev->ports_ddir);
+	if (IS_ERR_OR_NULL(nsim_dev_port->ddir))
+		return -ENOMEM;
+
+	sprintf(dev_link_name, "../../../" DRV_NAME "%u",
+		nsim_dev->nsim_bus_dev->dev.id);
+	debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name);
+
+	return 0;
+}
+
+static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
+{
+	debugfs_remove_recursive(nsim_dev_port->ddir);
+}
+
 static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv)
 {
 	struct nsim_dev *nsim_dev = priv;
@@ -198,7 +223,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
 	.reload = nsim_dev_reload,
 };
 
-static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
+static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev,
+					unsigned int port_count)
 {
 	struct nsim_dev *nsim_dev;
 	struct devlink *devlink;
@@ -211,6 +237,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
 	nsim_dev->nsim_bus_dev = nsim_bus_dev;
 	nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id);
 	get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len);
+	INIT_LIST_HEAD(&nsim_dev->port_list);
 
 	nsim_dev->fib_data = nsim_fib_create();
 	if (IS_ERR(nsim_dev->fib_data)) {
@@ -249,19 +276,6 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev)
 	return ERR_PTR(err);
 }
 
-struct nsim_dev *nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev,
-					 struct netdevsim *ns)
-{
-	struct nsim_dev *nsim_dev;
-
-	dev_hold(ns->netdev);
-	rtnl_unlock();
-	nsim_dev = nsim_dev_create(nsim_bus_dev);
-	rtnl_lock();
-	dev_put(ns->netdev);
-	return nsim_dev;
-}
-
 void nsim_dev_destroy(struct nsim_dev *nsim_dev)
 {
 	struct devlink *devlink = priv_to_devlink(nsim_dev);
@@ -274,6 +288,93 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev)
 	devlink_free(devlink);
 }
 
+static int nsim_dev_port_add(struct nsim_dev *nsim_dev, unsigned int port_index)
+{
+	struct nsim_dev_port *nsim_dev_port;
+	struct devlink_port *devlink_port;
+	int err;
+
+	nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL);
+	if (!nsim_dev_port)
+		return -ENOMEM;
+	nsim_dev_port->port_index = port_index;
+
+	devlink_port = &nsim_dev_port->devlink_port;
+	devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL,
+			       port_index + 1, 0, 0,
+			       nsim_dev->switch_id.id,
+			       nsim_dev->switch_id.id_len);
+	err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port,
+				    port_index);
+	if (err)
+		goto err_port_free;
+
+	err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
+	if (err)
+		goto err_dl_port_unregister;
+
+	list_add(&nsim_dev_port->list, &nsim_dev->port_list);
+
+	return 0;
+
+err_dl_port_unregister:
+	devlink_port_unregister(devlink_port);
+err_port_free:
+	kfree(nsim_dev_port);
+	return err;
+}
+
+static void nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
+{
+	struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
+
+	list_del(&nsim_dev_port->list);
+	nsim_dev_port_debugfs_exit(nsim_dev_port);
+	devlink_port_unregister(devlink_port);
+	kfree(nsim_dev_port);
+}
+
+static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
+{
+	struct nsim_dev_port *nsim_dev_port, *tmp;
+
+	list_for_each_entry_safe(nsim_dev_port, tmp,
+				 &nsim_dev->port_list, list)
+		nsim_dev_port_del(nsim_dev_port);
+}
+
+int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
+{
+	struct nsim_dev *nsim_dev;
+	int i;
+	int err;
+
+	nsim_dev = nsim_dev_create(nsim_bus_dev, nsim_bus_dev->port_count);
+	if (IS_ERR(nsim_dev))
+		return PTR_ERR(nsim_dev);
+	dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev);
+
+	for (i = 0; i < nsim_bus_dev->port_count; i++) {
+		err = nsim_dev_port_add(nsim_dev, i);
+		if (err)
+			goto err_port_del_all;
+	}
+	return 0;
+
+err_port_del_all:
+	nsim_dev_port_del_all(nsim_dev);
+	nsim_dev_destroy(nsim_dev);
+	return err;
+}
+
+void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
+{
+	struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+
+	nsim_dev_port_del_all(nsim_dev);
+	nsim_dev_destroy(nsim_dev);
+}
+
 int nsim_dev_init(void)
 {
 	nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index eb823bd0dc39..99169fe521f2 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -74,7 +74,6 @@ static void nsim_free(struct net_device *dev)
 {
 	struct netdevsim *ns = netdev_priv(dev);
 
-	nsim_dev_destroy(ns->nsim_dev);
 	nsim_bus_dev_del(ns->nsim_bus_dev);
 	/* netdev and vf state will be freed out of device_release() */
 }
@@ -364,26 +363,20 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev,
 	struct netdevsim *ns = netdev_priv(dev);
 	int err;
 
-	ns->nsim_bus_dev = nsim_bus_dev_new(~0, 0);
+	ns->netdev = dev;
+	ns->nsim_bus_dev = nsim_bus_dev_new_with_ns(ns);
 	if (IS_ERR(ns->nsim_bus_dev))
 		return PTR_ERR(ns->nsim_bus_dev);
 
 	SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev);
-	ns->netdev = dev;
 
-	ns->nsim_dev = nsim_dev_create_with_ns(ns->nsim_bus_dev, ns);
-	if (IS_ERR(ns->nsim_dev)) {
-		err = PTR_ERR(ns->nsim_dev);
-		goto err_dev_del;
-	}
+	ns->nsim_dev = dev_get_drvdata(&ns->nsim_bus_dev->dev);
 
 	err = register_netdevice(dev);
 	if (err)
-		goto err_dev_destroy;
+		goto err_dev_del;
 	return 0;
 
-err_dev_destroy:
-	nsim_dev_destroy(ns->nsim_dev);
 err_dev_del:
 	nsim_bus_dev_del(ns->nsim_bus_dev);
 	return err;
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index ec678371865f..0e6ca85e5487 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -18,6 +18,7 @@
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/u64_stats_sync.h>
+#include <net/devlink.h>
 #include <net/xdp.h>
 
 #define DRV_NAME	"netdevsim"
@@ -130,6 +131,13 @@ enum nsim_resource_id {
 	NSIM_RESOURCE_IPV6_FIB_RULES,
 };
 
+struct nsim_dev_port {
+	struct list_head list;
+	struct devlink_port devlink_port;
+	unsigned int port_index;
+	struct dentry *ddir;
+};
+
 struct nsim_dev {
 	struct nsim_bus_dev *nsim_bus_dev;
 	struct nsim_fib_data *fib_data;
@@ -143,13 +151,13 @@ struct nsim_dev {
 	struct list_head bpf_bound_progs;
 	struct list_head bpf_bound_maps;
 	struct netdev_phys_item_id switch_id;
+	struct list_head port_list;
 };
 
-struct nsim_dev *nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev,
-					 struct netdevsim *ns);
-void nsim_dev_destroy(struct nsim_dev *nsim_dev);
 int nsim_dev_init(void);
 void nsim_dev_exit(void);
+int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev);
+void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev);
 
 struct nsim_fib_data *nsim_fib_create(void);
 void nsim_fib_destroy(struct nsim_fib_data *fib_data);
@@ -200,6 +208,7 @@ struct nsim_bus_dev {
 };
 
 struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count);
+struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns);
 void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
 int nsim_bus_init(void);
 void nsim_bus_exit(void);
-- 
2.17.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ