From 5a2e106c746d2740f425cce3ac039321c924dc85 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 25 Feb 2020 11:45:21 +0100 Subject: devlink: extend devlink_trap_report() to accept cookie and pass Add cookie argument to devlink_trap_report() allowing driver to pass in the user cookie. Pass on the cookie down to drop monitor code. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index d7706a0346f2..aa17533c06e1 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -385,7 +385,7 @@ static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port) */ local_bh_disable(); devlink_trap_report(devlink, skb, nsim_trap_item->trap_ctx, - &nsim_dev_port->devlink_port); + &nsim_dev_port->devlink_port, NULL); local_bh_enable(); consume_skb(skb); } -- cgit v1.2.3 From d3cbb907ae57fe5da314b51d949b617b538bdeae Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Tue, 25 Feb 2020 11:45:26 +0100 Subject: netdevsim: add ACL trap reporting cookie as a metadata Add new trap ACL which reports flow action cookie in a metadata. Allow used to setup the cookie using debugfs file. Signed-off-by: Jiri Pirko Signed-off-by: Ido Schimmel Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 117 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 3 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index aa17533c06e1..f81c47377f32 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -71,6 +72,98 @@ static const struct file_operations nsim_dev_take_snapshot_fops = { .llseek = generic_file_llseek, }; +static ssize_t nsim_dev_trap_fa_cookie_read(struct file *file, + char __user *data, + size_t count, loff_t *ppos) +{ + struct nsim_dev *nsim_dev = file->private_data; + struct flow_action_cookie *fa_cookie; + unsigned int buf_len; + ssize_t ret; + char *buf; + + spin_lock(&nsim_dev->fa_cookie_lock); + fa_cookie = nsim_dev->fa_cookie; + if (!fa_cookie) { + ret = -EINVAL; + goto errout; + } + buf_len = fa_cookie->cookie_len * 2; + buf = kmalloc(buf_len, GFP_ATOMIC); + if (!buf) { + ret = -ENOMEM; + goto errout; + } + bin2hex(buf, fa_cookie->cookie, fa_cookie->cookie_len); + spin_unlock(&nsim_dev->fa_cookie_lock); + + ret = simple_read_from_buffer(data, count, ppos, buf, buf_len); + + kfree(buf); + return ret; + +errout: + spin_unlock(&nsim_dev->fa_cookie_lock); + return ret; +} + +static ssize_t nsim_dev_trap_fa_cookie_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct nsim_dev *nsim_dev = file->private_data; + struct flow_action_cookie *fa_cookie; + size_t cookie_len; + ssize_t ret; + char *buf; + + if (*ppos != 0) + return -EINVAL; + cookie_len = (count - 1) / 2; + if ((count - 1) % 2) + return -EINVAL; + buf = kmalloc(count, GFP_KERNEL | __GFP_NOWARN); + if (!buf) + return -ENOMEM; + + ret = simple_write_to_buffer(buf, count, ppos, data, count); + if (ret < 0) + goto free_buf; + + fa_cookie = kmalloc(sizeof(*fa_cookie) + cookie_len, + GFP_KERNEL | __GFP_NOWARN); + if (!fa_cookie) { + ret = -ENOMEM; + goto free_buf; + } + + fa_cookie->cookie_len = cookie_len; + ret = hex2bin(fa_cookie->cookie, buf, cookie_len); + if (ret) + goto free_fa_cookie; + kfree(buf); + + spin_lock(&nsim_dev->fa_cookie_lock); + kfree(nsim_dev->fa_cookie); + nsim_dev->fa_cookie = fa_cookie; + spin_unlock(&nsim_dev->fa_cookie_lock); + + return count; + +free_fa_cookie: + kfree(fa_cookie); +free_buf: + kfree(buf); + return ret; +} + +static const struct file_operations nsim_dev_trap_fa_cookie_fops = { + .open = simple_open, + .read = nsim_dev_trap_fa_cookie_read, + .write = nsim_dev_trap_fa_cookie_write, + .llseek = generic_file_llseek, +}; + static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) { char dev_ddir_name[sizeof(DRV_NAME) + 10]; @@ -97,6 +190,8 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) &nsim_dev->dont_allow_reload); debugfs_create_bool("fail_reload", 0600, nsim_dev->ddir, &nsim_dev->fail_reload); + debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir, + nsim_dev, &nsim_dev_trap_fa_cookie_fops); return 0; } @@ -288,6 +383,10 @@ enum { DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ NSIM_TRAP_METADATA) +#define NSIM_TRAP_DROP_EXT(_id, _group_id, _metadata) \ + DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ + DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + NSIM_TRAP_METADATA | (_metadata)) #define NSIM_TRAP_EXCEPTION(_id, _group_id) \ DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ @@ -309,6 +408,10 @@ static const struct devlink_trap nsim_traps_arr[] = { NSIM_TRAP_DROP(BLACKHOLE_ROUTE, L3_DROPS), NSIM_TRAP_EXCEPTION(TTL_ERROR, L3_DROPS), NSIM_TRAP_DROP(TAIL_DROP, BUFFER_DROPS), + NSIM_TRAP_DROP_EXT(INGRESS_FLOW_ACTION_DROP, ACL_DROPS, + DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE), + NSIM_TRAP_DROP_EXT(EGRESS_FLOW_ACTION_DROP, ACL_DROPS, + DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE), }; #define NSIM_TRAP_L4_DATA_LEN 100 @@ -366,8 +469,13 @@ static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port) spin_lock(&nsim_trap_data->trap_lock); for (i = 0; i < ARRAY_SIZE(nsim_traps_arr); i++) { + struct flow_action_cookie *fa_cookie = NULL; struct nsim_trap_item *nsim_trap_item; struct sk_buff *skb; + bool has_fa_cookie; + + has_fa_cookie = nsim_traps_arr[i].metadata_cap & + DEVLINK_TRAP_METADATA_TYPE_F_FA_COOKIE; nsim_trap_item = &nsim_trap_data->trap_items_arr[i]; if (nsim_trap_item->action == DEVLINK_TRAP_ACTION_DROP) @@ -383,10 +491,12 @@ static void nsim_dev_trap_report(struct nsim_dev_port *nsim_dev_port) * softIRQs to prevent lockdep from complaining about * "incosistent lock state". */ - local_bh_disable(); + + spin_lock_bh(&nsim_dev->fa_cookie_lock); + fa_cookie = has_fa_cookie ? nsim_dev->fa_cookie : NULL; devlink_trap_report(devlink, skb, nsim_trap_item->trap_ctx, - &nsim_dev_port->devlink_port, NULL); - local_bh_enable(); + &nsim_dev_port->devlink_port, fa_cookie); + spin_unlock_bh(&nsim_dev->fa_cookie_lock); consume_skb(skb); } spin_unlock(&nsim_trap_data->trap_lock); @@ -780,6 +890,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) nsim_dev->fw_update_status = true; nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT; nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT; + spin_lock_init(&nsim_dev->fa_cookie_lock); dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); -- cgit v1.2.3 From b29545d840de5eba664a37a20f2152c4e6d0b50a Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 22 Mar 2020 20:48:28 +0200 Subject: netdevsim: Explicitly register packet trap groups Use the previously added API to explicitly register / unregister supported packet trap groups. This is in preparation for future patches that will enable drivers to pass additional group attributes, such as associated policer identifier. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index f81c47377f32..edeb61ddc8bc 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -397,6 +397,13 @@ enum { DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ NSIM_TRAP_METADATA) +static const struct devlink_trap_group nsim_trap_groups_arr[] = { + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS), + DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS), + DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS), + DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS), +}; + static const struct devlink_trap nsim_traps_arr[] = { NSIM_TRAP_DROP(SMAC_MC, L2_DROPS), NSIM_TRAP_DROP(VLAN_TAG_MISMATCH, L2_DROPS), @@ -556,10 +563,15 @@ static int nsim_dev_traps_init(struct devlink *devlink) nsim_trap_data->nsim_dev = nsim_dev; nsim_dev->trap_data = nsim_trap_data; + err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr, + ARRAY_SIZE(nsim_trap_groups_arr)); + if (err) + goto err_trap_items_free; + err = devlink_traps_register(devlink, nsim_traps_arr, ARRAY_SIZE(nsim_traps_arr), NULL); if (err) - goto err_trap_items_free; + goto err_trap_groups_unregister; INIT_DELAYED_WORK(&nsim_dev->trap_data->trap_report_dw, nsim_dev_trap_report_work); @@ -568,6 +580,9 @@ static int nsim_dev_traps_init(struct devlink *devlink) return 0; +err_trap_groups_unregister: + devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, + ARRAY_SIZE(nsim_trap_groups_arr)); err_trap_items_free: kfree(nsim_trap_data->trap_items_arr); err_trap_data_free: @@ -582,6 +597,8 @@ static void nsim_dev_traps_exit(struct devlink *devlink) cancel_delayed_work_sync(&nsim_dev->trap_data->trap_report_dw); devlink_traps_unregister(devlink, nsim_traps_arr, ARRAY_SIZE(nsim_traps_arr)); + devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, + ARRAY_SIZE(nsim_trap_groups_arr)); kfree(nsim_dev->trap_data->trap_items_arr); kfree(nsim_dev->trap_data); } -- cgit v1.2.3 From 107f1678941151ccccec67d230a48069aa27527e Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Sun, 22 Mar 2020 20:48:30 +0200 Subject: devlink: Only pass packet trap group identifier in trap structure Packet trap groups are now explicitly registered by drivers and not implicitly registered when the packet traps are registered. Therefore, there is no need to encode entire group structure the trap is associated with inside the trap structure. Instead, only pass the group identifier. Refer to it as initial group identifier, as future patches will allow user space to move traps between groups. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index edeb61ddc8bc..7bfd0622cef1 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -381,20 +381,20 @@ enum { #define NSIM_TRAP_DROP(_id, _group_id) \ DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ NSIM_TRAP_METADATA) #define NSIM_TRAP_DROP_EXT(_id, _group_id, _metadata) \ DEVLINK_TRAP_GENERIC(DROP, DROP, _id, \ - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ NSIM_TRAP_METADATA | (_metadata)) #define NSIM_TRAP_EXCEPTION(_id, _group_id) \ DEVLINK_TRAP_GENERIC(EXCEPTION, TRAP, _id, \ - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ NSIM_TRAP_METADATA) #define NSIM_TRAP_DRIVER_EXCEPTION(_id, _group_id) \ DEVLINK_TRAP_DRIVER(EXCEPTION, TRAP, NSIM_TRAP_ID_##_id, \ NSIM_TRAP_NAME_##_id, \ - DEVLINK_TRAP_GROUP_GENERIC(_group_id), \ + DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ NSIM_TRAP_METADATA) static const struct devlink_trap_group nsim_trap_groups_arr[] = { -- cgit v1.2.3 From e8937681797c9af491c8a1e362a9db4f4aa1f471 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 26 Mar 2020 11:37:08 -0700 Subject: devlink: prepare to support region operations Modify the devlink region code in preparation for adding new operations on regions. Create a devlink_region_ops structure, and move the name pointer from within the devlink_region structure into the ops structure (similar to the devlink_health_reporter_ops). This prepares the regions to enable support of additional operations in the future such as requesting snapshots, or accessing the region directly without a snapshot. In order to re-use the constant strings in the mlx4 driver their declaration must be changed to 'const char * const' to ensure the compiler realizes that both the data and the pointer cannot change. Signed-off-by: Jacob Keller Reviewed-by: Jakub Kicinski Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 7bfd0622cef1..47a8f8c570c4 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -340,11 +340,15 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) #define NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX 16 +static const struct devlink_region_ops dummy_region_ops = { + .name = "dummy", +}; + static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, struct devlink *devlink) { nsim_dev->dummy_region = - devlink_region_create(devlink, "dummy", + devlink_region_create(devlink, &dummy_region_ops, NSIM_DEV_DUMMY_REGION_SNAPSHOT_MAX, NSIM_DEV_DUMMY_REGION_SIZE); return PTR_ERR_OR_ZERO(nsim_dev->dummy_region); -- cgit v1.2.3 From a0a09f6bb2c1501e24246edf2a7d42558d263b2b Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 26 Mar 2020 11:37:09 -0700 Subject: devlink: convert snapshot destructor callback to region op It does not makes sense that two snapshots for a given region would use different destructors. Simplify snapshot creation by adding a .destructor op for regions. This operation will replace the data_destructor for the snapshot creation, and makes snapshot creation easier. Noticed-by: Jakub Kicinski Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 47a8f8c570c4..f7621ccb7b88 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -56,7 +56,7 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); err = devlink_region_snapshot_create(nsim_dev->dummy_region, - dummy_data, id, kfree); + dummy_data, id); if (err) { pr_err("Failed to create region snapshot\n"); kfree(dummy_data); @@ -342,6 +342,7 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) static const struct devlink_region_ops dummy_region_ops = { .name = "dummy", + .destructor = &kfree, }; static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, -- cgit v1.2.3 From 7ef19d3b1d5e2e1dad64d41df708638f20c5917f Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 26 Mar 2020 11:37:14 -0700 Subject: devlink: report error once U32_MAX snapshot ids have been used The devlink_snapshot_id_get() function returns a snapshot id. The snapshot id is a u32, so there is no way to indicate an error code. A future change is going to possibly add additional cases where this function could fail. Refactor the function to return the snapshot id in an argument, so that it can return zero or an error value. This ensures that snapshot ids cannot be confused with error values, and aids in the future refactor of snapshot id allocation management. Because there is no current way to release previously used snapshot ids, add a simple check ensuring that an error is reported in case the snapshot_id would over flow. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index f7621ccb7b88..609005f2ac85 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -54,7 +54,11 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); - id = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev)); + err = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev), &id); + if (err) { + pr_err("Failed to get snapshot id\n"); + return err; + } err = devlink_region_snapshot_create(nsim_dev->dummy_region, dummy_data, id); if (err) { -- cgit v1.2.3 From 12102436acf949b5e6eb087846b47488db2aa440 Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 26 Mar 2020 11:37:15 -0700 Subject: devlink: track snapshot id usage count using an xarray Each snapshot created for a devlink region must have an id. These ids are supposed to be unique per "event" that caused the snapshot to be created. Drivers call devlink_region_snapshot_id_get to obtain a new id to use for a new event trigger. The id values are tracked per devlink, so that the same id number can be used if a triggering event creates multiple snapshots on different regions. There is no mechanism for snapshot ids to ever be reused. Introduce an xarray to store the count of how many snapshots are using a given id, replacing the snapshot_id field previously used for picking the next id. The devlink_region_snapshot_id_get() function will use xa_alloc to insert an initial value of 1 value at an available slot between 0 and U32_MAX. The new __devlink_snapshot_id_increment() and __devlink_snapshot_id_decrement() functions will be used to track how many snapshots currently use an id. Drivers must now call devlink_snapshot_id_put() in order to release their reference of the snapshot id after adding region snapshots. By tracking the total number of snapshots using a given id, it is possible for the decrement() function to erase the id from the xarray when it is not in use. With this method, a snapshot id can become reused again once all snapshots that referred to it have been deleted via DEVLINK_CMD_REGION_DEL, and the driver has finished adding snapshots. This work also paves the way to introduce a mechanism for userspace to request a snapshot. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 609005f2ac85..f4f6539f1e17 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -44,23 +44,27 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, size_t count, loff_t *ppos) { struct nsim_dev *nsim_dev = file->private_data; + struct devlink *devlink; void *dummy_data; int err; u32 id; + devlink = priv_to_devlink(nsim_dev); + dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL); if (!dummy_data) return -ENOMEM; get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); - err = devlink_region_snapshot_id_get(priv_to_devlink(nsim_dev), &id); + err = devlink_region_snapshot_id_get(devlink, &id); if (err) { pr_err("Failed to get snapshot id\n"); return err; } err = devlink_region_snapshot_create(nsim_dev->dummy_region, dummy_data, id); + devlink_region_snapshot_id_put(devlink, id); if (err) { pr_err("Failed to create region snapshot\n"); kfree(dummy_data); -- cgit v1.2.3 From 3fe0fd531a35c229f8309c8b74ef0226de2626ab Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Thu, 26 Mar 2020 11:37:17 -0700 Subject: netdevsim: support taking immediate snapshot via devlink Implement the .snapshot region operation for the dummy data region. This enables a region snapshot to be taken upon request via the new DEVLINK_CMD_REGION_SNAPSHOT command. Signed-off-by: Jacob Keller Reviewed-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index f4f6539f1e17..2b727a7001f6 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -39,23 +39,38 @@ static struct dentry *nsim_dev_ddir; #define NSIM_DEV_DUMMY_REGION_SIZE (1024 * 32) +static int +nsim_dev_take_snapshot(struct devlink *devlink, struct netlink_ext_ack *extack, + u8 **data) +{ + void *dummy_data; + + dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL); + if (!dummy_data) + return -ENOMEM; + + get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); + + *data = dummy_data; + + return 0; +} + static ssize_t nsim_dev_take_snapshot_write(struct file *file, const char __user *data, size_t count, loff_t *ppos) { struct nsim_dev *nsim_dev = file->private_data; struct devlink *devlink; - void *dummy_data; + u8 *dummy_data; int err; u32 id; devlink = priv_to_devlink(nsim_dev); - dummy_data = kmalloc(NSIM_DEV_DUMMY_REGION_SIZE, GFP_KERNEL); - if (!dummy_data) - return -ENOMEM; - - get_random_bytes(dummy_data, NSIM_DEV_DUMMY_REGION_SIZE); + err = nsim_dev_take_snapshot(devlink, NULL, &dummy_data); + if (err) + return err; err = devlink_region_snapshot_id_get(devlink, &id); if (err) { @@ -351,6 +366,7 @@ static void nsim_devlink_param_load_driverinit_values(struct devlink *devlink) static const struct devlink_region_ops dummy_region_ops = { .name = "dummy", .destructor = &kfree, + .snapshot = nsim_dev_take_snapshot, }; static int nsim_dev_dummy_region_init(struct nsim_dev *nsim_dev, -- cgit v1.2.3 From ad188458d0123d4e116f14f7eab73d644aed149f Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 30 Mar 2020 22:38:20 +0300 Subject: netdevsim: Add devlink-trap policer support Register three dummy packet trap policers with devlink and implement callbacks to change their parameters and read their counters. This will be used later on in the series to test the devlink-trap policer infrastructure. v2: * Remove check about burst size being a power of 2 and instead add a debugfs knob to fail the operation * Provide max/min rate/burst size when registering policers and remove the validity checks from nsim_dev_devlink_trap_policer_set() Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 85 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 84 insertions(+), 1 deletion(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 2b727a7001f6..21341e592467 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -215,6 +215,12 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) &nsim_dev->fail_reload); debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir, nsim_dev, &nsim_dev_trap_fa_cookie_fops); + debugfs_create_bool("fail_trap_policer_set", 0600, + nsim_dev->ddir, + &nsim_dev->fail_trap_policer_set); + debugfs_create_bool("fail_trap_policer_counter_get", 0600, + nsim_dev->ddir, + &nsim_dev->fail_trap_policer_counter_get); return 0; } @@ -392,6 +398,7 @@ struct nsim_trap_item { struct nsim_trap_data { struct delayed_work trap_report_dw; struct nsim_trap_item *trap_items_arr; + u64 *trap_policers_cnt_arr; struct nsim_dev *nsim_dev; spinlock_t trap_lock; /* Protects trap_items_arr */ }; @@ -426,6 +433,24 @@ enum { DEVLINK_TRAP_GROUP_GENERIC_ID_##_group_id, \ NSIM_TRAP_METADATA) +#define NSIM_DEV_TRAP_POLICER_MIN_RATE 1 +#define NSIM_DEV_TRAP_POLICER_MAX_RATE 8000 +#define NSIM_DEV_TRAP_POLICER_MIN_BURST 8 +#define NSIM_DEV_TRAP_POLICER_MAX_BURST 65536 + +#define NSIM_TRAP_POLICER(_id, _rate, _burst) \ + DEVLINK_TRAP_POLICER(_id, _rate, _burst, \ + NSIM_DEV_TRAP_POLICER_MAX_RATE, \ + NSIM_DEV_TRAP_POLICER_MIN_RATE, \ + NSIM_DEV_TRAP_POLICER_MAX_BURST, \ + NSIM_DEV_TRAP_POLICER_MIN_BURST) + +static const struct devlink_trap_policer nsim_trap_policers_arr[] = { + NSIM_TRAP_POLICER(1, 1000, 128), + NSIM_TRAP_POLICER(2, 2000, 256), + NSIM_TRAP_POLICER(3, 3000, 512), +}; + static const struct devlink_trap_group nsim_trap_groups_arr[] = { DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS), DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS), @@ -568,6 +593,7 @@ static void nsim_dev_trap_report_work(struct work_struct *work) static int nsim_dev_traps_init(struct devlink *devlink) { + size_t policers_count = ARRAY_SIZE(nsim_trap_policers_arr); struct nsim_dev *nsim_dev = devlink_priv(devlink); struct nsim_trap_data *nsim_trap_data; int err; @@ -584,6 +610,14 @@ static int nsim_dev_traps_init(struct devlink *devlink) goto err_trap_data_free; } + nsim_trap_data->trap_policers_cnt_arr = kcalloc(policers_count, + sizeof(u64), + GFP_KERNEL); + if (!nsim_trap_data->trap_policers_cnt_arr) { + err = -ENOMEM; + goto err_trap_items_free; + } + /* The lock is used to protect the action state of the registered * traps. The value is written by user and read in delayed work when * iterating over all the traps. @@ -592,10 +626,15 @@ static int nsim_dev_traps_init(struct devlink *devlink) nsim_trap_data->nsim_dev = nsim_dev; nsim_dev->trap_data = nsim_trap_data; + err = devlink_trap_policers_register(devlink, nsim_trap_policers_arr, + policers_count); + if (err) + goto err_trap_policers_cnt_free; + err = devlink_trap_groups_register(devlink, nsim_trap_groups_arr, ARRAY_SIZE(nsim_trap_groups_arr)); if (err) - goto err_trap_items_free; + goto err_trap_policers_unregister; err = devlink_traps_register(devlink, nsim_traps_arr, ARRAY_SIZE(nsim_traps_arr), NULL); @@ -612,6 +651,11 @@ static int nsim_dev_traps_init(struct devlink *devlink) err_trap_groups_unregister: devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, ARRAY_SIZE(nsim_trap_groups_arr)); +err_trap_policers_unregister: + devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr, + ARRAY_SIZE(nsim_trap_policers_arr)); +err_trap_policers_cnt_free: + kfree(nsim_trap_data->trap_policers_cnt_arr); err_trap_items_free: kfree(nsim_trap_data->trap_items_arr); err_trap_data_free: @@ -628,6 +672,9 @@ static void nsim_dev_traps_exit(struct devlink *devlink) ARRAY_SIZE(nsim_traps_arr)); devlink_trap_groups_unregister(devlink, nsim_trap_groups_arr, ARRAY_SIZE(nsim_trap_groups_arr)); + devlink_trap_policers_unregister(devlink, nsim_trap_policers_arr, + ARRAY_SIZE(nsim_trap_policers_arr)); + kfree(nsim_dev->trap_data->trap_policers_cnt_arr); kfree(nsim_dev->trap_data->trap_items_arr); kfree(nsim_dev->trap_data); } @@ -766,6 +813,40 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink, return 0; } +static int +nsim_dev_devlink_trap_policer_set(struct devlink *devlink, + const struct devlink_trap_policer *policer, + u64 rate, u64 burst, + struct netlink_ext_ack *extack) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + + if (nsim_dev->fail_trap_policer_set) { + NL_SET_ERR_MSG_MOD(extack, "User setup the operation to fail for testing purposes"); + return -EINVAL; + } + + return 0; +} + +static int +nsim_dev_devlink_trap_policer_counter_get(struct devlink *devlink, + const struct devlink_trap_policer *policer, + u64 *p_drops) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + u64 *cnt; + + if (nsim_dev->fail_trap_policer_counter_get) + return -EINVAL; + + cnt = &nsim_dev->trap_data->trap_policers_cnt_arr[policer->id - 1]; + *p_drops = *cnt; + *cnt += jiffies % 64; + + return 0; +} + static const struct devlink_ops nsim_dev_devlink_ops = { .reload_down = nsim_dev_reload_down, .reload_up = nsim_dev_reload_up, @@ -773,6 +854,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .flash_update = nsim_dev_flash_update, .trap_init = nsim_dev_devlink_trap_init, .trap_action_set = nsim_dev_devlink_trap_action_set, + .trap_policer_set = nsim_dev_devlink_trap_policer_set, + .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get, }; #define NSIM_DEV_MAX_MACS_DEFAULT 32 -- cgit v1.2.3 From f9f54392d2c88b34a2aaa6e51b202b3fd9c984b4 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 30 Mar 2020 22:38:21 +0300 Subject: devlink: Add packet trap group parameters support Packet trap groups are used to aggregate logically related packet traps. Currently, these groups allow user space to batch operations such as setting the trap action of all member traps. In order to prevent the CPU from being overwhelmed by too many trapped packets, it is desirable to bind a packet trap policer to these groups. For example, to limit all the packets that encountered an exception during routing to 10Kpps. Allow device drivers to bind default packet trap policers to packet trap groups when the latter are registered with devlink. The next patch will enable user space to change this default binding. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 21341e592467..bda603cfe66a 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -452,10 +452,10 @@ static const struct devlink_trap_policer nsim_trap_policers_arr[] = { }; static const struct devlink_trap_group nsim_trap_groups_arr[] = { - DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS), - DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS), - DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS), - DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS), + DEVLINK_TRAP_GROUP_GENERIC(L2_DROPS, 0), + DEVLINK_TRAP_GROUP_GENERIC(L3_DROPS, 1), + DEVLINK_TRAP_GROUP_GENERIC(BUFFER_DROPS, 2), + DEVLINK_TRAP_GROUP_GENERIC(ACL_DROPS, 3), }; static const struct devlink_trap nsim_traps_arr[] = { -- cgit v1.2.3 From 0dc8249a2e7ce38d9b307d1277b64f8189f53dfc Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 30 Mar 2020 22:38:23 +0300 Subject: netdevsim: Add support for setting of packet trap group parameters Add a dummy callback to set trap group parameters. Return an error when the 'fail_trap_group_set' debugfs file is set in order to exercise error paths and verify that error is propagated to user space when should. Signed-off-by: Ido Schimmel Reviewed-by: Jiri Pirko Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index bda603cfe66a..1fe2a93ad382 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -215,6 +215,9 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) &nsim_dev->fail_reload); debugfs_create_file("trap_flow_action_cookie", 0600, nsim_dev->ddir, nsim_dev, &nsim_dev_trap_fa_cookie_fops); + debugfs_create_bool("fail_trap_group_set", 0600, + nsim_dev->ddir, + &nsim_dev->fail_trap_group_set); debugfs_create_bool("fail_trap_policer_set", 0600, nsim_dev->ddir, &nsim_dev->fail_trap_policer_set); @@ -813,6 +816,19 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink, return 0; } +static int +nsim_dev_devlink_trap_group_set(struct devlink *devlink, + const struct devlink_trap_group *group, + const struct devlink_trap_policer *policer) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + + if (nsim_dev->fail_trap_group_set) + return -EINVAL; + + return 0; +} + static int nsim_dev_devlink_trap_policer_set(struct devlink *devlink, const struct devlink_trap_policer *policer, @@ -854,6 +870,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .flash_update = nsim_dev_flash_update, .trap_init = nsim_dev_devlink_trap_init, .trap_action_set = nsim_dev_devlink_trap_action_set, + .trap_group_set = nsim_dev_devlink_trap_group_set, .trap_policer_set = nsim_dev_devlink_trap_policer_set, .trap_policer_counter_get = nsim_dev_devlink_trap_policer_counter_get, }; -- cgit v1.2.3 From 3902baf9abfa320b21e38fe206d66d5e6688e721 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Mon, 30 Mar 2020 18:27:02 -0500 Subject: netdevsim: dev: Fix memory leak in nsim_dev_take_snapshot_write In case memory resources for dummy_data were allocated, release them before return. Addresses-Coverity-ID: 1491997 ("Resource leak") Fixes: 7ef19d3b1d5e ("devlink: report error once U32_MAX snapshot ids have been used") Signed-off-by: Gustavo A. R. Silva Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 1fe2a93ad382..68668a22b9dd 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -75,6 +75,7 @@ static ssize_t nsim_dev_take_snapshot_write(struct file *file, err = devlink_region_snapshot_id_get(devlink, &id); if (err) { pr_err("Failed to get snapshot id\n"); + kfree(dummy_data); return err; } err = devlink_region_snapshot_create(nsim_dev->dummy_region, -- cgit v1.2.3