netdevsim: extend device attrs to support port addition and deletion
authorJiri Pirko <jiri@mellanox.com>
Thu, 25 Apr 2019 13:59:54 +0000 (15:59 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 26 Apr 2019 05:52:03 +0000 (01:52 -0400)
In order to test flows in core, it is beneficial to maintain previously
supported possibility to add and delete ports during netdevsim lifetime.
Do it by extending device sysfs attrs by "new_port" and "del_port".

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/netdevsim/bus.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/netdevsim.h

index 1ee14e1bb12ddeb4b00d5c6993100b7fdd5e70d1..549c399f29da8914cdfde5c6e643e76fdb2009ea 100644 (file)
@@ -91,8 +91,44 @@ static struct device_attribute nsim_bus_dev_numvfs_attr =
        __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show,
               nsim_bus_dev_numvfs_store);
 
+static ssize_t
+new_port_store(struct device *dev, struct device_attribute *attr,
+              const char *buf, size_t count)
+{
+       struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+       unsigned int port_index;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &port_index);
+       if (ret)
+               return ret;
+       ret = nsim_dev_port_add(nsim_bus_dev, port_index);
+       return ret ? ret : count;
+}
+
+static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port);
+
+static ssize_t
+del_port_store(struct device *dev, struct device_attribute *attr,
+              const char *buf, size_t count)
+{
+       struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev);
+       unsigned int port_index;
+       int ret;
+
+       ret = kstrtouint(buf, 0, &port_index);
+       if (ret)
+               return ret;
+       ret = nsim_dev_port_del(nsim_bus_dev, port_index);
+       return ret ? ret : count;
+}
+
+static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port);
+
 static struct attribute *nsim_bus_dev_attrs[] = {
        &nsim_bus_dev_numvfs_attr.attr,
+       &nsim_bus_dev_new_port_attr.attr,
+       &nsim_bus_dev_del_port_attr.attr,
        NULL,
 };
 
index 6ee9d43ae252b010d2f2e0504ad698e3c9489153..2fa1b20613701eaa4b5baa4d85e86d24b57f7a56 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/debugfs.h>
 #include <linux/device.h>
 #include <linux/list.h>
+#include <linux/mutex.h>
 #include <linux/random.h>
 #include <linux/rtnetlink.h>
 #include <net/devlink.h>
@@ -238,6 +239,7 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
        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);
+       mutex_init(&nsim_dev->port_list_lock);
 
        nsim_dev->fib_data = nsim_fib_create();
        if (IS_ERR(nsim_dev->fib_data)) {
@@ -285,10 +287,12 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev)
        devlink_unregister(devlink);
        devlink_resources_unregister(devlink, NULL);
        nsim_fib_destroy(nsim_dev->fib_data);
+       mutex_destroy(&nsim_dev->port_list_lock);
        devlink_free(devlink);
 }
 
-static int nsim_dev_port_add(struct nsim_dev *nsim_dev, unsigned int port_index)
+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;
@@ -324,7 +328,7 @@ err_port_free:
        return err;
 }
 
-static void nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
+static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port)
 {
        struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
 
@@ -340,7 +344,7 @@ static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev)
 
        list_for_each_entry_safe(nsim_dev_port, tmp,
                                 &nsim_dev->port_list, list)
-               nsim_dev_port_del(nsim_dev_port);
+               __nsim_dev_port_del(nsim_dev_port);
 }
 
 int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev)
@@ -355,7 +359,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_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);
+               err = __nsim_dev_port_add(nsim_dev, i);
                if (err)
                        goto err_port_del_all;
        }
@@ -375,6 +379,49 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev)
        nsim_dev_destroy(nsim_dev);
 }
 
+static struct nsim_dev_port *
+__nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index)
+{
+       struct nsim_dev_port *nsim_dev_port;
+
+       list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list)
+               if (nsim_dev_port->port_index == port_index)
+                       return nsim_dev_port;
+       return NULL;
+}
+
+int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index)
+{
+       struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+       int err;
+
+       mutex_lock(&nsim_dev->port_list_lock);
+       if (__nsim_dev_port_lookup(nsim_dev, port_index))
+               err = -EEXIST;
+       else
+               err = __nsim_dev_port_add(nsim_dev, port_index);
+       mutex_unlock(&nsim_dev->port_list_lock);
+       return err;
+}
+
+int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index)
+{
+       struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
+       struct nsim_dev_port *nsim_dev_port;
+       int err = 0;
+
+       mutex_lock(&nsim_dev->port_list_lock);
+       nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index);
+       if (!nsim_dev_port)
+               err = -ENOENT;
+       else
+               __nsim_dev_port_del(nsim_dev_port);
+       mutex_unlock(&nsim_dev->port_list_lock);
+       return err;
+}
+
 int nsim_dev_init(void)
 {
        nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL);
index 0e6ca85e548772f529aca754f87fd4f5d050706e..6b60589cab912cc81827b721f07d79824ba6563b 100644 (file)
@@ -152,12 +152,17 @@ struct nsim_dev {
        struct list_head bpf_bound_maps;
        struct netdev_phys_item_id switch_id;
        struct list_head port_list;
+       struct mutex port_list_lock; /* protects port list */
 };
 
 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);
+int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index);
+int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev,
+                     unsigned int port_index);
 
 struct nsim_fib_data *nsim_fib_create(void);
 void nsim_fib_destroy(struct nsim_fib_data *fib_data);