From: Ido Schimmel <ido...@nvidia.com> Register a dummy counter with devlink that is incremented by one whenever queried.
Allow the query to fail by writing to a file in debugfs so that error paths in the core infrastructure could be exercised. Signed-off-by: Amit Cohen <amco...@nvidia.com> Signed-off-by: Danielle Ratson <daniel...@nvidia.com> Signed-off-by: Ido Schimmel <ido...@nvidia.com> --- drivers/net/netdevsim/dev.c | 92 ++++++++++++++++++++++++++++++- drivers/net/netdevsim/netdevsim.h | 1 + 2 files changed, 91 insertions(+), 2 deletions(-) diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 32f339fedb21..075d2d4e22a5 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -692,6 +692,81 @@ static void nsim_dev_traps_exit(struct devlink *devlink) kfree(nsim_dev->trap_data); } +struct nsim_metric_data { + struct devlink_metric *dummy_counter; + struct dentry *ddir; + u64 dummy_counter_value; + bool fail_counter_get; +}; + +static int nsim_dev_dummy_counter_get(struct devlink_metric *metric, u64 *p_val) +{ + struct nsim_dev *nsim_dev = devlink_metric_priv(metric); + u64 *cnt; + + if (nsim_dev->metric_data->fail_counter_get) + return -EINVAL; + + cnt = &nsim_dev->metric_data->dummy_counter_value; + *p_val = (*cnt)++; + + return 0; +} + +static const struct devlink_metric_ops nsim_dev_dummy_counter_ops = { + .counter_get = nsim_dev_dummy_counter_get, +}; + +static int nsim_dev_metric_init(struct nsim_dev *nsim_dev) +{ + struct devlink *devlink = priv_to_devlink(nsim_dev); + struct nsim_metric_data *nsim_metric_data; + struct devlink_metric *dummy_counter; + int err; + + nsim_metric_data = kzalloc(sizeof(*nsim_metric_data), GFP_KERNEL); + if (!nsim_metric_data) + return -ENOMEM; + nsim_dev->metric_data = nsim_metric_data; + + dummy_counter = devlink_metric_counter_create(devlink, "dummy_counter", + &nsim_dev_dummy_counter_ops, + nsim_dev); + if (IS_ERR(dummy_counter)) { + err = PTR_ERR(dummy_counter); + goto err_free_metric_data; + } + nsim_metric_data->dummy_counter = dummy_counter; + + nsim_metric_data->ddir = debugfs_create_dir("metric", nsim_dev->ddir); + if (IS_ERR(nsim_metric_data->ddir)) { + err = PTR_ERR(nsim_metric_data->ddir); + goto err_dummy_counter_destroy; + } + + nsim_metric_data->fail_counter_get = false; + debugfs_create_bool("fail_counter_get", 0600, nsim_metric_data->ddir, + &nsim_metric_data->fail_counter_get); + + return 0; + +err_dummy_counter_destroy: + devlink_metric_destroy(devlink, dummy_counter); +err_free_metric_data: + kfree(nsim_metric_data); + return err; +} + +static void nsim_dev_metric_exit(struct nsim_dev *nsim_dev) +{ + struct nsim_metric_data *nsim_metric_data = nsim_dev->metric_data; + struct devlink *devlink = priv_to_devlink(nsim_dev); + + debugfs_remove_recursive(nsim_metric_data->ddir); + devlink_metric_destroy(devlink, nsim_metric_data->dummy_counter); + kfree(nsim_metric_data); +} + static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, struct netlink_ext_ack *extack); static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev); @@ -1008,10 +1083,14 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, if (err) goto err_traps_exit; - err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + err = nsim_dev_metric_init(nsim_dev); if (err) goto err_health_exit; + err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + if (err) + goto err_metric_exit; + nsim_dev->take_snapshot = debugfs_create_file("take_snapshot", 0200, nsim_dev->ddir, @@ -1019,6 +1098,8 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, &nsim_dev_take_snapshot_fops); return 0; +err_metric_exit: + nsim_dev_metric_exit(nsim_dev); err_health_exit: nsim_dev_health_exit(nsim_dev); err_traps_exit: @@ -1089,10 +1170,14 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) if (err) goto err_debugfs_exit; - err = nsim_bpf_dev_init(nsim_dev); + err = nsim_dev_metric_init(nsim_dev); if (err) goto err_health_exit; + err = nsim_bpf_dev_init(nsim_dev); + if (err) + goto err_metric_exit; + err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); if (err) goto err_bpf_dev_exit; @@ -1103,6 +1188,8 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) err_bpf_dev_exit: nsim_bpf_dev_exit(nsim_dev); +err_metric_exit: + nsim_dev_metric_exit(nsim_dev); err_health_exit: nsim_dev_health_exit(nsim_dev); err_debugfs_exit: @@ -1133,6 +1220,7 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) return; debugfs_remove(nsim_dev->take_snapshot); nsim_dev_port_del_all(nsim_dev); + nsim_dev_metric_exit(nsim_dev); nsim_dev_health_exit(nsim_dev); nsim_dev_traps_exit(devlink); nsim_dev_dummy_region_exit(nsim_dev); diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 284f7092241d..5f9a99bc4022 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -171,6 +171,7 @@ struct nsim_dev { struct nsim_bus_dev *nsim_bus_dev; struct nsim_fib_data *fib_data; struct nsim_trap_data *trap_data; + struct nsim_metric_data *metric_data; struct dentry *ddir; struct dentry *ports_ddir; struct dentry *take_snapshot; -- 2.26.2