Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e05b2d14 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller
Browse files

netdevsim: move netdev creation/destruction to dev probe



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: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 794b2c05
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -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;
+9 −16
Original line number Diff line number Diff line
@@ -153,6 +153,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)
{
@@ -188,6 +191,8 @@ new_device_store(struct bus_type *bus, const char *buf, size_t count)
}
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)
{
@@ -261,7 +266,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;
@@ -270,8 +276,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;
@@ -291,19 +296,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);
+12 −1
Original line number Diff line number Diff line
@@ -278,7 +278,7 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count)
	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);

@@ -317,10 +317,19 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev,
	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);
	list_add(&nsim_dev_port->list, &nsim_dev->port_list);

	return 0;

err_port_debugfs_exit:
	nsim_dev_port_debugfs_exit(nsim_dev_port);
err_dl_port_unregister:
	devlink_port_unregister(devlink_port);
err_port_free:
@@ -333,6 +342,8 @@ 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);
	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);
	kfree(nsim_dev_port);
+2 −1
Original line number Diff line number Diff line
@@ -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);
}

+49 −89
Original line number Diff line number Diff line
@@ -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)
Loading