From: Jiri Pirko <j...@mellanox.com>

Remove the existing way to create netdevsim over rtnetlink and move the
netdev creation/destruction to dev probe, so for every probed port,
a netdevsim-netdev instance is created.

Adjust selftests to work with new interface.

Signed-off-by: Jiri Pirko <j...@mellanox.com>
---
 drivers/net/netdevsim/bpf.c              |  13 ++-
 drivers/net/netdevsim/bus.c              |  25 ++--
 drivers/net/netdevsim/dev.c              |  14 ++-
 drivers/net/netdevsim/ipsec.c            |   3 +-
 drivers/net/netdevsim/netdev.c           | 138 ++++++++---------------
 drivers/net/netdevsim/netdevsim.h        |  11 +-
 tools/testing/selftests/net/rtnetlink.sh |   6 +-
 7 files changed, 89 insertions(+), 121 deletions(-)

diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c
index 89980b223adc..2b74425822ab 100644
--- a/drivers/net/netdevsim/bpf.c
+++ b/drivers/net/netdevsim/bpf.c
@@ -612,6 +612,7 @@ void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev)
 
 int nsim_bpf_init(struct netdevsim *ns)
 {
+       struct dentry *ddir = ns->nsim_dev_port->ddir;
        int err;
 
        err = bpf_offload_dev_netdev_register(ns->nsim_dev->bpf_dev,
@@ -619,23 +620,23 @@ int nsim_bpf_init(struct netdevsim *ns)
        if (err)
                return err;
 
-       debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir,
+       debugfs_create_u32("bpf_offloaded_id", 0400, ddir,
                           &ns->bpf_offloaded_id);
 
        ns->bpf_tc_accept = true;
-       debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir,
+       debugfs_create_bool("bpf_tc_accept", 0600, ddir,
                            &ns->bpf_tc_accept);
-       debugfs_create_bool("bpf_tc_non_bound_accept", 0600, ns->ddir,
+       debugfs_create_bool("bpf_tc_non_bound_accept", 0600, ddir,
                            &ns->bpf_tc_non_bound_accept);
        ns->bpf_xdpdrv_accept = true;
-       debugfs_create_bool("bpf_xdpdrv_accept", 0600, ns->ddir,
+       debugfs_create_bool("bpf_xdpdrv_accept", 0600, ddir,
                            &ns->bpf_xdpdrv_accept);
        ns->bpf_xdpoffload_accept = true;
-       debugfs_create_bool("bpf_xdpoffload_accept", 0600, ns->ddir,
+       debugfs_create_bool("bpf_xdpoffload_accept", 0600, ddir,
                            &ns->bpf_xdpoffload_accept);
 
        ns->bpf_map_accept = true;
-       debugfs_create_bool("bpf_map_accept", 0600, ns->ddir,
+       debugfs_create_bool("bpf_map_accept", 0600, ddir,
                            &ns->bpf_map_accept);
 
        return 0;
diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c
index 46108a926890..a8e0b1f60a6f 100644
--- a/drivers/net/netdevsim/bus.c
+++ b/drivers/net/netdevsim/bus.c
@@ -117,6 +117,9 @@ static struct device_type nsim_bus_dev_type = {
        .release = nsim_bus_dev_release,
 };
 
+static struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id,
+                                            unsigned int port_count);
+
 static ssize_t new_device_store(struct bus_type *bus, const char *buf,
                                size_t count)
 {
@@ -152,6 +155,8 @@ static ssize_t new_device_store(struct bus_type *bus, const 
char *buf,
 }
 static BUS_ATTR_WO(new_device);
 
+static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev);
+
 static ssize_t del_device_store(struct bus_type *bus, const char *buf,
                                size_t count)
 {
@@ -225,7 +230,8 @@ static struct bus_type nsim_bus = {
        .num_vf         = nsim_num_vf,
 };
 
-struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count)
+static struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id,
+                                            unsigned int port_count)
 {
        struct nsim_bus_dev *nsim_bus_dev;
        int err;
@@ -234,8 +240,7 @@ struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, 
unsigned int port_count)
        if (!nsim_bus_dev)
                return ERR_PTR(-ENOMEM);
 
-       err = ida_alloc_range(&nsim_bus_dev_ids,
-                             id == ~0 ? 0 : id, id, GFP_KERNEL);
+       err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL);
        if (err < 0)
                goto err_nsim_bus_dev_free;
        nsim_bus_dev->dev.id = err;
@@ -255,19 +260,7 @@ 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)
+static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev)
 {
        device_unregister(&nsim_bus_dev->dev);
        ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id);
diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c
index 43d87c457ad9..7bd33989f484 100644
--- a/drivers/net/netdevsim/dev.c
+++ b/drivers/net/netdevsim/dev.c
@@ -275,7 +275,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev 
*nsim_bus_dev,
        return ERR_PTR(err);
 }
 
-void nsim_dev_destroy(struct nsim_dev *nsim_dev)
+static void nsim_dev_destroy(struct nsim_dev *nsim_dev)
 {
        struct devlink *devlink = priv_to_devlink(nsim_dev);
 
@@ -307,8 +307,18 @@ static int nsim_dev_port_init(struct nsim_dev *nsim_dev,
        err = nsim_dev_port_debugfs_init(nsim_dev, nsim_dev_port);
        if (err)
                goto err_dl_port_unregister;
+
+       nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
+       if (IS_ERR(nsim_dev_port->ns)) {
+               err = PTR_ERR(nsim_dev_port->ns);
+               goto err_port_debugfs_exit;
+       }
+
+       devlink_port_type_eth_set(devlink_port, nsim_dev_port->ns->netdev);
        return 0;
 
+err_port_debugfs_exit:
+       nsim_dev_port_debugfs_exit(nsim_dev_port);
 err_dl_port_unregister:
        devlink_port_unregister(devlink_port);
        return err;
@@ -320,6 +330,8 @@ static void nsim_dev_port_exit(struct nsim_dev *nsim_dev,
        struct nsim_dev_port *nsim_dev_port = &nsim_dev->ports[port_index];
        struct devlink_port *devlink_port = &nsim_dev_port->devlink_port;
 
+       devlink_port_type_clear(devlink_port);
+       nsim_destroy(nsim_dev_port->ns);
        nsim_dev_port_debugfs_exit(nsim_dev_port);
        devlink_port_unregister(devlink_port);
 }
diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c
index 76e11d889bb6..e27fc1a4516d 100644
--- a/drivers/net/netdevsim/ipsec.c
+++ b/drivers/net/netdevsim/ipsec.c
@@ -283,7 +283,8 @@ void nsim_ipsec_init(struct netdevsim *ns)
        ns->netdev->features |= NSIM_ESP_FEATURES;
        ns->netdev->hw_enc_features |= NSIM_ESP_FEATURES;
 
-       ns->ipsec.pfile = debugfs_create_file("ipsec", 0400, ns->ddir, ns,
+       ns->ipsec.pfile = debugfs_create_file("ipsec", 0400,
+                                             ns->nsim_dev_port->ddir, ns,
                                              &ipsec_dbg_fops);
 }
 
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 99169fe521f2..38ebf846ed49 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -25,59 +25,6 @@
 
 #include "netdevsim.h"
 
-static int nsim_get_port_parent_id(struct net_device *dev,
-                                  struct netdev_phys_item_id *ppid)
-{
-       struct netdevsim *ns = netdev_priv(dev);
-
-       memcpy(ppid, &ns->nsim_dev->switch_id, sizeof(*ppid));
-       return 0;
-}
-
-static int nsim_init(struct net_device *dev)
-{
-       struct netdevsim *ns = netdev_priv(dev);
-       char dev_link_name[32];
-       int err;
-
-       ns->ddir = debugfs_create_dir("0", ns->nsim_dev->ports_ddir);
-       if (IS_ERR_OR_NULL(ns->ddir))
-               return -ENOMEM;
-
-       sprintf(dev_link_name, "../../../" DRV_NAME "%u",
-               ns->nsim_dev->nsim_bus_dev->dev.id);
-       debugfs_create_symlink("dev", ns->ddir, dev_link_name);
-
-       err = nsim_bpf_init(ns);
-       if (err)
-               goto err_debugfs_destroy;
-
-       nsim_ipsec_init(ns);
-
-       return 0;
-
-err_debugfs_destroy:
-       debugfs_remove_recursive(ns->ddir);
-       return err;
-}
-
-static void nsim_uninit(struct net_device *dev)
-{
-       struct netdevsim *ns = netdev_priv(dev);
-
-       nsim_ipsec_teardown(ns);
-       debugfs_remove_recursive(ns->ddir);
-       nsim_bpf_uninit(ns);
-}
-
-static void nsim_free(struct net_device *dev)
-{
-       struct netdevsim *ns = netdev_priv(dev);
-
-       nsim_bus_dev_del(ns->nsim_bus_dev);
-       /* netdev and vf state will be freed out of device_release() */
-}
-
 static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct netdevsim *ns = netdev_priv(dev);
@@ -299,8 +246,6 @@ nsim_set_features(struct net_device *dev, netdev_features_t 
features)
 }
 
 static const struct net_device_ops nsim_netdev_ops = {
-       .ndo_init               = nsim_init,
-       .ndo_uninit             = nsim_uninit,
        .ndo_start_xmit         = nsim_start_xmit,
        .ndo_set_rx_mode        = nsim_set_rx_mode,
        .ndo_set_mac_address    = eth_mac_addr,
@@ -318,7 +263,6 @@ static const struct net_device_ops nsim_netdev_ops = {
        .ndo_setup_tc           = nsim_setup_tc,
        .ndo_set_features       = nsim_set_features,
        .ndo_bpf                = nsim_bpf,
-       .ndo_get_port_parent_id = nsim_get_port_parent_id,
 };
 
 static void nsim_setup(struct net_device *dev)
@@ -326,10 +270,6 @@ static void nsim_setup(struct net_device *dev)
        ether_setup(dev);
        eth_hw_addr_random(dev);
 
-       dev->netdev_ops = &nsim_netdev_ops;
-       dev->needs_free_netdev = true;
-       dev->priv_destructor = nsim_free;
-
        dev->tx_queue_len = 0;
        dev->flags |= IFF_NOARP;
        dev->flags &= ~IFF_MULTICAST;
@@ -344,50 +284,70 @@ static void nsim_setup(struct net_device *dev)
        dev->max_mtu = ETH_MAX_MTU;
 }
 
-static int nsim_validate(struct nlattr *tb[], struct nlattr *data[],
-                        struct netlink_ext_ack *extack)
-{
-       if (tb[IFLA_ADDRESS]) {
-               if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN)
-                       return -EINVAL;
-               if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS])))
-                       return -EADDRNOTAVAIL;
-       }
-       return 0;
-}
-
-static int nsim_newlink(struct net *src_net, struct net_device *dev,
-                       struct nlattr *tb[], struct nlattr *data[],
-                       struct netlink_ext_ack *extack)
+struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
+                             struct nsim_dev_port *nsim_dev_port)
 {
-       struct netdevsim *ns = netdev_priv(dev);
+       struct net_device *dev;
+       struct netdevsim *ns;
        int err;
 
-       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);
+       dev = alloc_netdev(sizeof(*ns), "eth%d", NET_NAME_UNKNOWN, nsim_setup);
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
 
+       ns = netdev_priv(dev);
+       ns->netdev = dev;
+       ns->nsim_dev = nsim_dev;
+       ns->nsim_dev_port = nsim_dev_port;
+       ns->nsim_bus_dev = nsim_dev->nsim_bus_dev;
        SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev);
+       dev->netdev_ops = &nsim_netdev_ops;
 
-       ns->nsim_dev = dev_get_drvdata(&ns->nsim_bus_dev->dev);
+       rtnl_lock();
+       err = nsim_bpf_init(ns);
+       if (err)
+               goto err_free_netdev;
+
+       nsim_ipsec_init(ns);
 
        err = register_netdevice(dev);
        if (err)
-               goto err_dev_del;
-       return 0;
+               goto err_ipsec_teardown;
+       rtnl_unlock();
 
-err_dev_del:
-       nsim_bus_dev_del(ns->nsim_bus_dev);
-       return err;
+       return ns;
+
+err_ipsec_teardown:
+       nsim_ipsec_teardown(ns);
+       nsim_bpf_uninit(ns);
+       rtnl_unlock();
+err_free_netdev:
+       free_netdev(dev);
+       return ERR_PTR(err);
+}
+
+void nsim_destroy(struct netdevsim *ns)
+{
+       struct net_device *dev = ns->netdev;
+
+       rtnl_lock();
+       unregister_netdevice(dev);
+       nsim_ipsec_teardown(ns);
+       nsim_bpf_uninit(ns);
+       rtnl_unlock();
+       free_netdev(dev);
+}
+
+static int nsim_validate(struct nlattr *tb[], struct nlattr *data[],
+                        struct netlink_ext_ack *extack)
+{
+       NL_SET_ERR_MSG_MOD(extack, "Please use: echo \"[ID] [PORT_COUNT]\" > 
/sys/bus/netdevsim/new_device");
+       return -EOPNOTSUPP;
 }
 
 static struct rtnl_link_ops nsim_link_ops __read_mostly = {
        .kind           = DRV_NAME,
-       .priv_size      = sizeof(struct netdevsim),
-       .setup          = nsim_setup,
        .validate       = nsim_validate,
-       .newlink        = nsim_newlink,
 };
 
 static int __init nsim_module_init(void)
diff --git a/drivers/net/netdevsim/netdevsim.h 
b/drivers/net/netdevsim/netdevsim.h
index c0a08af5e724..a91e2118dd0e 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -51,6 +51,7 @@ struct nsim_ipsec {
 struct netdevsim {
        struct net_device *netdev;
        struct nsim_dev *nsim_dev;
+       struct nsim_dev_port *nsim_dev_port;
 
        u64 tx_packets;
        u64 tx_bytes;
@@ -58,8 +59,6 @@ struct netdevsim {
 
        struct nsim_bus_dev *nsim_bus_dev;
 
-       struct dentry *ddir;
-
        struct bpf_prog *bpf_offloaded;
        u32 bpf_offloaded_id;
 
@@ -75,6 +74,10 @@ struct netdevsim {
        struct nsim_ipsec ipsec;
 };
 
+struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
+                             struct nsim_dev_port *nsim_dev_port);
+void nsim_destroy(struct netdevsim *ns);
+
 #ifdef CONFIG_BPF_SYSCALL
 int nsim_bpf_dev_init(struct nsim_dev *nsim_dev);
 void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev);
@@ -135,6 +138,7 @@ struct nsim_dev_port {
        struct devlink_port devlink_port;
        unsigned int port_index;
        struct dentry *ddir;
+       struct netdevsim *ns;
 };
 
 struct nsim_dev {
@@ -206,8 +210,5 @@ struct nsim_bus_dev {
        struct nsim_vf_config *vfconfigs;
 };
 
-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);
diff --git a/tools/testing/selftests/net/rtnetlink.sh 
b/tools/testing/selftests/net/rtnetlink.sh
index 311f82bcbe8d..710d73ceb9c3 100755
--- a/tools/testing/selftests/net/rtnetlink.sh
+++ b/tools/testing/selftests/net/rtnetlink.sh
@@ -696,7 +696,7 @@ kci_test_ipsec_offload()
        algo="aead rfc4106(gcm(aes)) 0x3132333435363738393031323334353664636261 
128"
        srcip=192.168.123.3
        dstip=192.168.123.4
-       dev=simx1
+       dev=netdevsim0p1
        sysfsd=/sys/kernel/debug/netdevsim/netdevsim0/ports/0/
        sysfsf=$sysfsd/ipsec
 
@@ -708,7 +708,8 @@ kci_test_ipsec_offload()
                return 1
        fi
 
-       ip link add $dev type netdevsim
+       echo "0" > /sys/bus/netdevsim/new_device
+       sleep 0.2
        ip addr add $srcip dev $dev
        ip link set $dev up
        if [ ! -d $sysfsd ] ; then
@@ -781,7 +782,6 @@ EOF
        fi
 
        # clean up any leftovers
-       ip link del $dev
        rmmod netdevsim
 
        if [ $ret -ne 0 ]; then
-- 
2.17.2

Reply via email to