Skip to content

Commit

Permalink
netdevsim: introduce line card support
Browse files Browse the repository at this point in the history
Add support for line card objects. Expose them over debugfs and allow
user to specify number of line cards to be created for a new device.
Similar to ports, the number of line cards is fixed.

Extend "new_device" sysfs file write by third number to allow to specify
number line cards like this:
$ echo "10 4 2" >/sys/bus/netdevsim/new_device

This command asks to create two line cards. By default, if this number
is not preset, no line card is created.

Signed-off-by: Jiri Pirko <jiri@nvidia.com>
---
RFCv2->RFCv3:
- rebased
  • Loading branch information
Jiri Pirko committed Apr 11, 2022
1 parent eba696c commit 505d891
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 8 deletions.
20 changes: 14 additions & 6 deletions drivers/net/netdevsim/bus.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,16 +143,18 @@ static struct device_type nsim_bus_dev_type = {
};

static struct nsim_bus_dev *
nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues);
nsim_bus_dev_new(unsigned int id, unsigned int port_count,
unsigned int num_queues, unsigned int linecard_count);

static ssize_t
new_device_store(struct bus_type *bus, const char *buf, size_t count)
{
unsigned int id, port_count, num_queues;
unsigned int id, port_count, num_queues, linecard_count;
struct nsim_bus_dev *nsim_bus_dev;
int err;

err = sscanf(buf, "%u %u %u", &id, &port_count, &num_queues);
err = sscanf(buf, "%u %u %u %u", &id, &port_count, &num_queues,
&linecard_count);
switch (err) {
case 1:
port_count = 1;
Expand All @@ -161,13 +163,16 @@ new_device_store(struct bus_type *bus, const char *buf, size_t count)
num_queues = 1;
fallthrough;
case 3:
linecard_count = 0;
fallthrough;
case 4:
if (id > INT_MAX) {
pr_err("Value of \"id\" is too big.\n");
return -EINVAL;
}
break;
default:
pr_err("Format for adding new device is \"id port_count num_queues\" (uint uint unit).\n");
pr_err("Format for adding new device is \"id port_count num_queues linecard_count\" (uint uint unit uint).\n");
return -EINVAL;
}

Expand All @@ -178,7 +183,8 @@ new_device_store(struct bus_type *bus, const char *buf, size_t count)
goto err;
}

nsim_bus_dev = nsim_bus_dev_new(id, port_count, num_queues);
nsim_bus_dev = nsim_bus_dev_new(id, port_count,
num_queues, linecard_count);
if (IS_ERR(nsim_bus_dev)) {
err = PTR_ERR(nsim_bus_dev);
goto err;
Expand Down Expand Up @@ -279,7 +285,8 @@ static struct bus_type nsim_bus = {
#define NSIM_BUS_DEV_MAX_VFS 4

static struct nsim_bus_dev *
nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queues)
nsim_bus_dev_new(unsigned int id, unsigned int port_count,
unsigned int num_queues, unsigned int linecard_count)
{
struct nsim_bus_dev *nsim_bus_dev;
int err;
Expand All @@ -296,6 +303,7 @@ nsim_bus_dev_new(unsigned int id, unsigned int port_count, unsigned int num_queu
nsim_bus_dev->dev.type = &nsim_bus_dev_type;
nsim_bus_dev->port_count = port_count;
nsim_bus_dev->num_queues = num_queues;
nsim_bus_dev->linecard_count = linecard_count;
nsim_bus_dev->initial_net = current->nsproxy->net_ns;
nsim_bus_dev->max_vfs = NSIM_BUS_DEV_MAX_VFS;
mutex_init(&nsim_bus_dev->nsim_bus_reload_lock);
Expand Down
108 changes: 106 additions & 2 deletions drivers/net/netdevsim/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir);
if (IS_ERR(nsim_dev->ports_ddir))
return PTR_ERR(nsim_dev->ports_ddir);
nsim_dev->linecards_ddir = debugfs_create_dir("linecards",
nsim_dev->ddir);
if (IS_ERR(nsim_dev->linecards_ddir))
return PTR_ERR(nsim_dev->linecards_ddir);
debugfs_create_bool("fw_update_status", 0600, nsim_dev->ddir,
&nsim_dev->fw_update_status);
debugfs_create_u32("fw_update_overwrite_mask", 0600, nsim_dev->ddir,
Expand Down Expand Up @@ -363,6 +367,7 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev)
static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev)
{
debugfs_remove_recursive(nsim_dev->nodes_ddir);
debugfs_remove_recursive(nsim_dev->linecards_ddir);
debugfs_remove_recursive(nsim_dev->ports_ddir);
debugfs_remove_recursive(nsim_dev->ddir);
}
Expand Down Expand Up @@ -426,6 +431,32 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port)
debugfs_remove_recursive(nsim_dev_port->ddir);
}

static int
nsim_dev_linecard_debugfs_init(struct nsim_dev *nsim_dev,
struct nsim_dev_linecard *nsim_dev_linecard)
{
char linecard_ddir_name[16];
char dev_link_name[32];

sprintf(linecard_ddir_name, "%u", nsim_dev_linecard->linecard_index);
nsim_dev_linecard->ddir = debugfs_create_dir(linecard_ddir_name,
nsim_dev->linecards_ddir);
if (IS_ERR(nsim_dev_linecard->ddir))
return PTR_ERR(nsim_dev_linecard->ddir);

sprintf(dev_link_name, "../../../" DRV_NAME "%u",
nsim_dev->nsim_bus_dev->dev.id);
debugfs_create_symlink("dev", nsim_dev_linecard->ddir, dev_link_name);

return 0;
}

static void
nsim_dev_linecard_debugfs_exit(struct nsim_dev_linecard *nsim_dev_linecard)
{
debugfs_remove_recursive(nsim_dev_linecard->ddir);
}

static int nsim_dev_resources_register(struct devlink *devlink)
{
struct devlink_resource_size_params params = {
Expand Down Expand Up @@ -1460,6 +1491,64 @@ static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
return err;
}

static int __nsim_dev_linecard_add(struct nsim_dev *nsim_dev,
unsigned int linecard_index)
{
struct nsim_dev_linecard *nsim_dev_linecard;
int err;

nsim_dev_linecard = kzalloc(sizeof(*nsim_dev_linecard), GFP_KERNEL);
if (!nsim_dev_linecard)
return -ENOMEM;
nsim_dev_linecard->nsim_dev = nsim_dev;
nsim_dev_linecard->linecard_index = linecard_index;

err = nsim_dev_linecard_debugfs_init(nsim_dev, nsim_dev_linecard);
if (err)
goto err_linecard_free;

list_add(&nsim_dev_linecard->list, &nsim_dev->linecard_list);

return 0;

err_linecard_free:
kfree(nsim_dev_linecard);
return err;
}

static void __nsim_dev_linecard_del(struct nsim_dev_linecard *nsim_dev_linecard)
{
list_del(&nsim_dev_linecard->list);
nsim_dev_linecard_debugfs_exit(nsim_dev_linecard);
kfree(nsim_dev_linecard);
}

static void nsim_dev_linecard_del_all(struct nsim_dev *nsim_dev)
{
struct nsim_dev_linecard *nsim_dev_linecard, *tmp;

list_for_each_entry_safe(nsim_dev_linecard, tmp,
&nsim_dev->linecard_list, list)
__nsim_dev_linecard_del(nsim_dev_linecard);
}

static int nsim_dev_linecard_add_all(struct nsim_dev *nsim_dev,
unsigned int linecard_count)
{
int i, err;

for (i = 0; i < linecard_count; i++) {
err = __nsim_dev_linecard_add(nsim_dev, i);
if (err)
goto err_linecard_del_all;
}
return 0;

err_linecard_del_all:
nsim_dev_linecard_del_all(nsim_dev);
return err;
}

static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
struct netlink_ext_ack *extack)
{
Expand All @@ -1470,6 +1559,7 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
devlink = priv_to_devlink(nsim_dev);
nsim_dev = devlink_priv(devlink);
INIT_LIST_HEAD(&nsim_dev->port_list);
INIT_LIST_HEAD(&nsim_dev->linecard_list);
nsim_dev->fw_update_status = true;
nsim_dev->fw_update_overwrite_mask = 0;

Expand Down Expand Up @@ -1501,17 +1591,23 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev,
if (err)
goto err_psample_exit;

err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
err = nsim_dev_linecard_add_all(nsim_dev, nsim_bus_dev->linecard_count);
if (err)
goto err_hwstats_exit;

err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
if (err)
goto err_linecard_del_all;

nsim_dev->take_snapshot = debugfs_create_file("take_snapshot",
0200,
nsim_dev->ddir,
nsim_dev,
&nsim_dev_take_snapshot_fops);
return 0;

err_linecard_del_all:
nsim_dev_linecard_del_all(nsim_dev);
err_hwstats_exit:
nsim_dev_hwstats_exit(nsim_dev);
err_psample_exit:
Expand Down Expand Up @@ -1542,6 +1638,7 @@ int nsim_drv_probe(struct 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);
INIT_LIST_HEAD(&nsim_dev->linecard_list);
nsim_dev->fw_update_status = true;
nsim_dev->fw_update_overwrite_mask = 0;
nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT;
Expand Down Expand Up @@ -1602,15 +1699,21 @@ int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev)
if (err)
goto err_psample_exit;

err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
err = nsim_dev_linecard_add_all(nsim_dev, nsim_bus_dev->linecard_count);
if (err)
goto err_hwstats_exit;

err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count);
if (err)
goto err_linecard_del_all;

nsim_dev->esw_mode = DEVLINK_ESWITCH_MODE_LEGACY;
devlink_set_features(devlink, DEVLINK_F_RELOAD);
devlink_register(devlink);
return 0;

err_linecard_del_all:
nsim_dev_linecard_del_all(nsim_dev);
err_hwstats_exit:
nsim_dev_hwstats_exit(nsim_dev);
err_psample_exit:
Expand Down Expand Up @@ -1657,6 +1760,7 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev)
devl_unlock(devlink);

nsim_dev_port_del_all(nsim_dev);
nsim_dev_linecard_del_all(nsim_dev);
nsim_dev_hwstats_exit(nsim_dev);
nsim_dev_psample_exit(nsim_dev);
nsim_dev_health_exit(nsim_dev);
Expand Down
13 changes: 13 additions & 0 deletions drivers/net/netdevsim/netdevsim.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,12 @@ enum nsim_dev_port_type {
#define NSIM_DEV_VF_PORT_INDEX_BASE 128
#define NSIM_DEV_VF_PORT_INDEX_MAX UINT_MAX

struct nsim_dev_linecard;

struct nsim_dev_port {
struct list_head list;
struct devlink_port devlink_port;
struct nsim_dev_linecard *linecard;
unsigned int port_index;
enum nsim_dev_port_type port_type;
struct dentry *ddir;
Expand Down Expand Up @@ -258,6 +261,7 @@ struct nsim_dev {
struct nsim_trap_data *trap_data;
struct dentry *ddir;
struct dentry *ports_ddir;
struct dentry *linecards_ddir;
struct dentry *take_snapshot;
struct dentry *nodes_ddir;

Expand All @@ -273,6 +277,7 @@ struct nsim_dev {
struct list_head bpf_bound_maps;
struct netdev_phys_item_id switch_id;
struct list_head port_list;
struct list_head linecard_list;
bool fw_update_status;
u32 fw_update_overwrite_mask;
u32 max_macs;
Expand Down Expand Up @@ -302,6 +307,13 @@ struct nsim_dev {
u16 esw_mode;
};

struct nsim_dev_linecard {
struct list_head list;
struct nsim_dev *nsim_dev;
unsigned int linecard_index;
struct dentry *ddir;
};

static inline bool nsim_esw_mode_is_legacy(struct nsim_dev *nsim_dev)
{
return nsim_dev->esw_mode == DEVLINK_ESWITCH_MODE_LEGACY;
Expand Down Expand Up @@ -371,6 +383,7 @@ struct nsim_bus_dev {
struct list_head list;
unsigned int port_count;
unsigned int num_queues; /* Number of queues for each port on this bus */
unsigned int linecard_count;
struct net *initial_net; /* Purpose of this is to carry net pointer
* during the probe time only.
*/
Expand Down

0 comments on commit 505d891

Please sign in to comment.