From a5facc4cac4dc504397428c936ef1492ce4edd19 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 3 Oct 2019 11:49:26 +0200 Subject: netdevsim: change fib accounting and limitations to be per-device Currently, the accounting is done per-namespace. However, devlink instance is always in init_net namespace for now, so only the accounting related to init_net is used. Limitations set using devlink resources are only considered for init_net. nsim_devlink_net() always returns init_net always. Make the accounting per-device. This brings no functional change. Per-device accounting has the same values as per-net. For a single netdevsim instance, the behaviour is exactly the same as before. When multiple netdevsim instances are created, each can have different limits. This is in prepare to implement proper devlink netns support. After that, the devlink instance which would exist in particular netns would account and limit that netns. Signed-off-by: Jiri Pirko Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 79 ++++++++++----------------------------------- 1 file changed, 17 insertions(+), 62 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 56576d4f34a5..6087f5b99e47 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -123,39 +123,6 @@ static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port) debugfs_remove_recursive(nsim_dev_port->ddir); } -static struct net *nsim_devlink_net(struct devlink *devlink) -{ - return &init_net; -} - -static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) -{ - struct net *net = priv; - - return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, false); -} - -static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv) -{ - struct net *net = priv; - - return nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, false); -} - -static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv) -{ - struct net *net = priv; - - return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, false); -} - -static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv) -{ - struct net *net = priv; - - return nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, false); -} - static int nsim_dev_resources_register(struct devlink *devlink) { struct devlink_resource_size_params params = { @@ -163,9 +130,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) .size_granularity = 1, .unit = DEVLINK_RESOURCE_UNIT_ENTRY }; - struct net *net = nsim_devlink_net(devlink); int err; - u64 n; /* Resources for IPv4 */ err = devlink_resource_register(devlink, "IPv4", (u64)-1, @@ -177,8 +142,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) goto out; } - n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB, true); - err = devlink_resource_register(devlink, "fib", n, + err = devlink_resource_register(devlink, "fib", (u64)-1, NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4, ¶ms); if (err) { @@ -186,8 +150,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) return err; } - n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV4_FIB_RULES, true); - err = devlink_resource_register(devlink, "fib-rules", n, + err = devlink_resource_register(devlink, "fib-rules", (u64)-1, NSIM_RESOURCE_IPV4_FIB_RULES, NSIM_RESOURCE_IPV4, ¶ms); if (err) { @@ -205,8 +168,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) goto out; } - n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB, true); - err = devlink_resource_register(devlink, "fib", n, + err = devlink_resource_register(devlink, "fib", (u64)-1, NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6, ¶ms); if (err) { @@ -214,8 +176,7 @@ static int nsim_dev_resources_register(struct devlink *devlink) return err; } - n = nsim_fib_get_val(net, NSIM_RESOURCE_IPV6_FIB_RULES, true); - err = devlink_resource_register(devlink, "fib-rules", n, + err = devlink_resource_register(devlink, "fib-rules", (u64)-1, NSIM_RESOURCE_IPV6_FIB_RULES, NSIM_RESOURCE_IPV6, ¶ms); if (err) { @@ -223,22 +184,6 @@ static int nsim_dev_resources_register(struct devlink *devlink) return err; } - devlink_resource_occ_get_register(devlink, - NSIM_RESOURCE_IPV4_FIB, - nsim_dev_ipv4_fib_resource_occ_get, - net); - devlink_resource_occ_get_register(devlink, - NSIM_RESOURCE_IPV4_FIB_RULES, - nsim_dev_ipv4_fib_rules_res_occ_get, - net); - devlink_resource_occ_get_register(devlink, - NSIM_RESOURCE_IPV6_FIB, - nsim_dev_ipv6_fib_resource_occ_get, - net); - devlink_resource_occ_get_register(devlink, - NSIM_RESOURCE_IPV6_FIB_RULES, - nsim_dev_ipv6_fib_rules_res_occ_get, - net); out: return err; } @@ -533,11 +478,11 @@ static int nsim_dev_reload_down(struct devlink *devlink, static int nsim_dev_reload_up(struct devlink *devlink, struct netlink_ext_ack *extack) { + struct nsim_dev *nsim_dev = devlink_priv(devlink); enum nsim_resource_id res_ids[] = { NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES, NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES }; - struct net *net = nsim_devlink_net(devlink); int i; for (i = 0; i < ARRAY_SIZE(res_ids); ++i) { @@ -546,7 +491,8 @@ static int nsim_dev_reload_up(struct devlink *devlink, err = devlink_resource_size_get(devlink, res_ids[i], &val); if (!err) { - err = nsim_fib_set_max(net, res_ids[i], val, extack); + err = nsim_fib_set_max(nsim_dev->fib_data, + res_ids[i], val, extack); if (err) return err; } @@ -681,9 +627,15 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) if (err) goto err_devlink_free; + nsim_dev->fib_data = nsim_fib_create(devlink); + if (IS_ERR(nsim_dev->fib_data)) { + err = PTR_ERR(nsim_dev->fib_data); + goto err_resources_unregister; + } + err = devlink_register(devlink, &nsim_bus_dev->dev); if (err) - goto err_resources_unregister; + goto err_fib_destroy; err = devlink_params_register(devlink, nsim_devlink_params, ARRAY_SIZE(nsim_devlink_params)); @@ -721,6 +673,8 @@ err_params_unregister: ARRAY_SIZE(nsim_devlink_params)); err_dl_unregister: devlink_unregister(devlink); +err_fib_destroy: + nsim_fib_destroy(devlink, nsim_dev->fib_data); err_resources_unregister: devlink_resources_unregister(devlink, NULL); err_devlink_free: @@ -739,6 +693,7 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev) devlink_params_unregister(devlink, nsim_devlink_params, ARRAY_SIZE(nsim_devlink_params)); devlink_unregister(devlink); + nsim_fib_destroy(devlink, nsim_dev->fib_data); devlink_resources_unregister(devlink, NULL); mutex_destroy(&nsim_dev->port_list_lock); devlink_free(devlink); -- cgit v1.2.3 From 7f36a77ade6eefc243c64c64b8f8252fa43ea55e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 3 Oct 2019 11:49:35 +0200 Subject: netdevsim: add all ports in nsim_dev_create() and del them in destroy() Currently the probe/remove function does this separately. Put the addition an deletion of ports into nsim_dev_create() and nsim_dev_destroy(). Signed-off-by: Jiri Pirko Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 175 +++++++++++++++++++++++--------------------- 1 file changed, 93 insertions(+), 82 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 6087f5b99e47..3cc101aee991 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -603,8 +603,92 @@ static const struct devlink_ops nsim_dev_devlink_ops = { #define NSIM_DEV_MAX_MACS_DEFAULT 32 #define NSIM_DEV_TEST1_DEFAULT true +static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, + unsigned int port_index) +{ + struct nsim_dev_port *nsim_dev_port; + struct devlink_port *devlink_port; + int err; + + nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL); + if (!nsim_dev_port) + return -ENOMEM; + nsim_dev_port->port_index = port_index; + + devlink_port = &nsim_dev_port->devlink_port; + devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, + port_index + 1, 0, 0, + nsim_dev->switch_id.id, + nsim_dev->switch_id.id_len); + err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port, + port_index); + if (err) + goto err_port_free; + + 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); + 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: + kfree(nsim_dev_port); + return err; +} + +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); +} + +static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev) +{ + struct nsim_dev_port *nsim_dev_port, *tmp; + + list_for_each_entry_safe(nsim_dev_port, tmp, + &nsim_dev->port_list, list) + __nsim_dev_port_del(nsim_dev_port); +} + +static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev, + unsigned int port_count) +{ + int i, err; + + for (i = 0; i < port_count; i++) { + err = __nsim_dev_port_add(nsim_dev, i); + if (err) + goto err_port_del_all; + } + return 0; + +err_port_del_all: + nsim_dev_port_del_all(nsim_dev); + return err; +} + static struct nsim_dev * -nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) +nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -659,9 +743,15 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) if (err) goto err_debugfs_exit; + err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + if (err) + goto err_bpf_dev_exit; + devlink_params_publish(devlink); return nsim_dev; +err_bpf_dev_exit: + nsim_bpf_dev_exit(nsim_dev); err_debugfs_exit: nsim_dev_debugfs_exit(nsim_dev); err_traps_exit: @@ -686,6 +776,7 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev) { struct devlink *devlink = priv_to_devlink(nsim_dev); + nsim_dev_port_del_all(nsim_dev); nsim_bpf_dev_exit(nsim_dev); nsim_dev_debugfs_exit(nsim_dev); nsim_dev_traps_exit(devlink); @@ -699,102 +790,22 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev) devlink_free(devlink); } -static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, - unsigned int port_index) -{ - struct nsim_dev_port *nsim_dev_port; - struct devlink_port *devlink_port; - int err; - - nsim_dev_port = kzalloc(sizeof(*nsim_dev_port), GFP_KERNEL); - if (!nsim_dev_port) - return -ENOMEM; - nsim_dev_port->port_index = port_index; - - devlink_port = &nsim_dev_port->devlink_port; - devlink_port_attrs_set(devlink_port, DEVLINK_PORT_FLAVOUR_PHYSICAL, - port_index + 1, 0, 0, - nsim_dev->switch_id.id, - nsim_dev->switch_id.id_len); - err = devlink_port_register(priv_to_devlink(nsim_dev), devlink_port, - port_index); - if (err) - goto err_port_free; - - 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); - 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: - kfree(nsim_dev_port); - return err; -} - -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); -} - -static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev) -{ - struct nsim_dev_port *nsim_dev_port, *tmp; - - list_for_each_entry_safe(nsim_dev_port, tmp, - &nsim_dev->port_list, list) - __nsim_dev_port_del(nsim_dev_port); -} - int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev; - int i; - int err; - nsim_dev = nsim_dev_create(nsim_bus_dev, nsim_bus_dev->port_count); + nsim_dev = nsim_dev_create(nsim_bus_dev); if (IS_ERR(nsim_dev)) return PTR_ERR(nsim_dev); dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); - for (i = 0; i < nsim_bus_dev->port_count; i++) { - err = __nsim_dev_port_add(nsim_dev, i); - if (err) - goto err_port_del_all; - } return 0; - -err_port_del_all: - nsim_dev_port_del_all(nsim_dev); - nsim_dev_destroy(nsim_dev); - return err; } void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); - nsim_dev_port_del_all(nsim_dev); nsim_dev_destroy(nsim_dev); } -- cgit v1.2.3 From 75ba029f3c07f4755b88ee3a9c441e9ffb468e6a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 3 Oct 2019 11:49:36 +0200 Subject: netdevsim: implement proper devlink reload During devlink reload, all driver objects should be reinstantiated with the exception of devlink instance and devlink resources and params. Move existing devlink_resource_size_get() calls into fib_create() just before fib notifier is registered. Also, make sure that extack is propagated down to fib_notifier_register() call. Signed-off-by: Jiri Pirko Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 95 ++++++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 28 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 3cc101aee991..7de80faab047 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -469,9 +469,16 @@ static void nsim_dev_traps_exit(struct devlink *devlink) kfree(nsim_dev->trap_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); + static int nsim_dev_reload_down(struct devlink *devlink, struct netlink_ext_ack *extack) { + struct nsim_dev *nsim_dev = devlink_priv(devlink); + + nsim_dev_reload_destroy(nsim_dev); return 0; } @@ -479,27 +486,8 @@ static int nsim_dev_reload_up(struct devlink *devlink, struct netlink_ext_ack *extack) { struct nsim_dev *nsim_dev = devlink_priv(devlink); - enum nsim_resource_id res_ids[] = { - NSIM_RESOURCE_IPV4_FIB, NSIM_RESOURCE_IPV4_FIB_RULES, - NSIM_RESOURCE_IPV6_FIB, NSIM_RESOURCE_IPV6_FIB_RULES - }; - int i; - - for (i = 0; i < ARRAY_SIZE(res_ids); ++i) { - int err; - u64 val; - - err = devlink_resource_size_get(devlink, res_ids[i], &val); - if (!err) { - err = nsim_fib_set_max(nsim_dev->fib_data, - res_ids[i], val, extack); - if (err) - return err; - } - } - nsim_devlink_param_load_driverinit_values(devlink); - return 0; + return nsim_dev_reload_create(nsim_dev, extack); } #define NSIM_DEV_FLASH_SIZE 500000 @@ -687,8 +675,49 @@ err_port_del_all: return err; } -static struct nsim_dev * -nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) +static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, + struct netlink_ext_ack *extack) +{ + struct nsim_bus_dev *nsim_bus_dev = nsim_dev->nsim_bus_dev; + struct devlink *devlink; + int err; + + devlink = priv_to_devlink(nsim_dev); + nsim_dev = devlink_priv(devlink); + INIT_LIST_HEAD(&nsim_dev->port_list); + mutex_init(&nsim_dev->port_list_lock); + nsim_dev->fw_update_status = true; + + nsim_dev->fib_data = nsim_fib_create(devlink, extack); + if (IS_ERR(nsim_dev->fib_data)) + return PTR_ERR(nsim_dev->fib_data); + + nsim_devlink_param_load_driverinit_values(devlink); + + err = nsim_dev_dummy_region_init(nsim_dev, devlink); + if (err) + goto err_fib_destroy; + + err = nsim_dev_traps_init(devlink); + if (err) + goto err_dummy_region_exit; + + err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + if (err) + goto err_traps_exit; + + return 0; + +err_traps_exit: + nsim_dev_traps_exit(devlink); +err_dummy_region_exit: + nsim_dev_dummy_region_exit(nsim_dev); +err_fib_destroy: + nsim_fib_destroy(devlink, nsim_dev->fib_data); + return err; +} + +static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -711,7 +740,7 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) if (err) goto err_devlink_free; - nsim_dev->fib_data = nsim_fib_create(devlink); + nsim_dev->fib_data = nsim_fib_create(devlink, NULL); if (IS_ERR(nsim_dev->fib_data)) { err = PTR_ERR(nsim_dev->fib_data); goto err_resources_unregister; @@ -772,21 +801,31 @@ err_devlink_free: return ERR_PTR(err); } -static void nsim_dev_destroy(struct nsim_dev *nsim_dev) +static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) { struct devlink *devlink = priv_to_devlink(nsim_dev); + if (devlink_is_reload_failed(devlink)) + return; nsim_dev_port_del_all(nsim_dev); - nsim_bpf_dev_exit(nsim_dev); - nsim_dev_debugfs_exit(nsim_dev); nsim_dev_traps_exit(devlink); nsim_dev_dummy_region_exit(nsim_dev); + mutex_destroy(&nsim_dev->port_list_lock); + nsim_fib_destroy(devlink, nsim_dev->fib_data); +} + +static void nsim_dev_destroy(struct nsim_dev *nsim_dev) +{ + struct devlink *devlink = priv_to_devlink(nsim_dev); + + nsim_dev_reload_destroy(nsim_dev); + + nsim_bpf_dev_exit(nsim_dev); + nsim_dev_debugfs_exit(nsim_dev); devlink_params_unregister(devlink, nsim_devlink_params, ARRAY_SIZE(nsim_devlink_params)); devlink_unregister(devlink); - nsim_fib_destroy(devlink, nsim_dev->fib_data); devlink_resources_unregister(devlink, NULL); - mutex_destroy(&nsim_dev->port_list_lock); devlink_free(devlink); } -- cgit v1.2.3 From 070c63f20f6c739a3c534555f56c7327536bfcc2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 3 Oct 2019 11:49:39 +0200 Subject: net: devlink: allow to change namespaces during reload All devlink instances are created in init_net and stay there for a lifetime. Allow user to be able to move devlink instances into namespaces during devlink reload operation. That ensures proper re-instantiation of driver objects, including netdevices. Signed-off-by: Jiri Pirko Acked-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 7de80faab047..3f3c7cc21077 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -473,7 +473,7 @@ 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); -static int nsim_dev_reload_down(struct devlink *devlink, +static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change, struct netlink_ext_ack *extack) { struct nsim_dev *nsim_dev = devlink_priv(devlink); -- cgit v1.2.3 From 7b60027bbc6738b067bb9ed732a8c56b0ac430b2 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sat, 5 Oct 2019 08:10:32 +0200 Subject: netdevsim: create devlink and netdev instances in namespace When user does create new netdevsim instance using sysfs bus file, create the devlink instance and related netdev instance in the namespace of the caller. Signed-off-by: Jiri Pirko 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 3f3c7cc21077..fbc4cdcfe551 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -726,6 +726,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev)); if (!devlink) return ERR_PTR(-ENOMEM); + devlink_net_set(devlink, nsim_bus_dev->initial_net); nsim_dev = devlink_priv(devlink); nsim_dev->nsim_bus_dev = nsim_bus_dev; nsim_dev->switch_id.id_len = sizeof(nsim_dev->switch_id.id); -- cgit v1.2.3 From 155ddfc5e54a68f0e8d20f31f2b4b6b25e1071b5 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Sun, 6 Oct 2019 08:30:01 +0200 Subject: netdevsim: add couple of debugfs bools to debug devlink reload Add flag to disallow reload and another one that causes reload to always fail. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index fbc4cdcfe551..31d1752c703a 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -90,6 +90,10 @@ static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) &nsim_dev->test1); debugfs_create_file("take_snapshot", 0200, nsim_dev->ddir, nsim_dev, &nsim_dev_take_snapshot_fops); + debugfs_create_bool("dont_allow_reload", 0600, nsim_dev->ddir, + &nsim_dev->dont_allow_reload); + debugfs_create_bool("fail_reload", 0600, nsim_dev->ddir, + &nsim_dev->fail_reload); return 0; } @@ -478,6 +482,14 @@ static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change, { struct nsim_dev *nsim_dev = devlink_priv(devlink); + if (nsim_dev->dont_allow_reload) { + /* For testing purposes, user set debugfs dont_allow_reload + * value to true. So forbid it. + */ + NL_SET_ERR_MSG_MOD(extack, "User forbidded reload for testing purposes"); + return -EOPNOTSUPP; + } + nsim_dev_reload_destroy(nsim_dev); return 0; } @@ -487,6 +499,14 @@ static int nsim_dev_reload_up(struct devlink *devlink, { struct nsim_dev *nsim_dev = devlink_priv(devlink); + if (nsim_dev->fail_reload) { + /* For testing purposes, user set debugfs fail_reload + * value to true. Fail right away. + */ + NL_SET_ERR_MSG_MOD(extack, "User setup the reload to fail for testing purposes"); + return -EINVAL; + } + return nsim_dev_reload_create(nsim_dev, extack); } -- cgit v1.2.3 From 8e23cc0319b185de49e35ed4fec174552bdf2f9a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Mon, 7 Oct 2019 10:27:08 +0200 Subject: netdevsim: implement devlink dev_info op Do simple dev_info devlink operation implementation which only fills up the driver name. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 31d1752c703a..a3d7d39f231a 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -510,6 +510,13 @@ static int nsim_dev_reload_up(struct devlink *devlink, return nsim_dev_reload_create(nsim_dev, extack); } +static int nsim_dev_info_get(struct devlink *devlink, + struct devlink_info_req *req, + struct netlink_ext_ack *extack) +{ + return devlink_info_driver_name_put(req, DRV_NAME); +} + #define NSIM_DEV_FLASH_SIZE 500000 #define NSIM_DEV_FLASH_CHUNK_SIZE 1000 #define NSIM_DEV_FLASH_CHUNK_TIME_MS 10 @@ -603,6 +610,7 @@ nsim_dev_devlink_trap_action_set(struct devlink *devlink, static const struct devlink_ops nsim_dev_devlink_ops = { .reload_down = nsim_dev_reload_down, .reload_up = nsim_dev_reload_up, + .info_get = nsim_dev_info_get, .flash_update = nsim_dev_flash_update, .trap_init = nsim_dev_devlink_trap_init, .trap_action_set = nsim_dev_devlink_trap_action_set, -- cgit v1.2.3 From f9867b51d268d6fabcc4477d877f04aaad9299ae Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 8 Oct 2019 09:17:47 +0100 Subject: netdevsim: fix spelling mistake "forbidded" -> "forbid" There is a spelling mistake in a NL_SET_ERR_MSG_MOD message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Jakub Kicinski --- 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 a3d7d39f231a..e47fa7b6ca7c 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -486,7 +486,7 @@ static int nsim_dev_reload_down(struct devlink *devlink, bool netns_change, /* For testing purposes, user set debugfs dont_allow_reload * value to true. So forbid it. */ - NL_SET_ERR_MSG_MOD(extack, "User forbidded reload for testing purposes"); + NL_SET_ERR_MSG_MOD(extack, "User forbid the reload for testing purposes"); return -EOPNOTSUPP; } -- cgit v1.2.3 From 82c93a87bf8bc0cdb5ec2ab99da7d87715ff889f Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 10 Oct 2019 15:18:50 +0200 Subject: netdevsim: implement couple of testing devlink health reporters Implement "empty" and "dummy" reporters. The first one is really simple and does nothing. The other one has debugfs files to trigger breakage and it is able to do recovery. The ops also implement dummy fmsg content. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index e47fa7b6ca7c..468e157a7cb1 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -730,12 +730,18 @@ static int nsim_dev_reload_create(struct nsim_dev *nsim_dev, if (err) goto err_dummy_region_exit; - err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + err = nsim_dev_health_init(nsim_dev, devlink); if (err) goto err_traps_exit; + err = nsim_dev_port_add_all(nsim_dev, nsim_bus_dev->port_count); + if (err) + goto err_health_exit; + return 0; +err_health_exit: + nsim_dev_health_exit(nsim_dev); err_traps_exit: nsim_dev_traps_exit(devlink); err_dummy_region_exit: @@ -797,10 +803,14 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) if (err) goto err_traps_exit; - err = nsim_bpf_dev_init(nsim_dev); + err = nsim_dev_health_init(nsim_dev, devlink); if (err) goto err_debugfs_exit; + err = nsim_bpf_dev_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_bpf_dev_exit; @@ -810,6 +820,8 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) err_bpf_dev_exit: nsim_bpf_dev_exit(nsim_dev); +err_health_exit: + nsim_dev_health_exit(nsim_dev); err_debugfs_exit: nsim_dev_debugfs_exit(nsim_dev); err_traps_exit: @@ -837,6 +849,7 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) if (devlink_is_reload_failed(devlink)) return; nsim_dev_port_del_all(nsim_dev); + nsim_dev_health_exit(nsim_dev); nsim_dev_traps_exit(devlink); nsim_dev_dummy_region_exit(nsim_dev); mutex_destroy(&nsim_dev->port_list_lock); -- cgit v1.2.3 From bfcccfe78b361f5f6ef48554aed5bcd30c72f67f Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 5 Nov 2019 13:26:11 -0800 Subject: netdevsim: drop code duplicated by a merge Looks like the port adding loop makes a re-appearance on net-next after net was merged back into it (even though it doesn't feature in the merge diff). The ports are already added in nsim_dev_create() so when we try to add them again get EEXIST, and see: netdevsim: probe of netdevsim0 failed with error -17 in the logs. When we remove the loop again the nsim_dev_probe() and nsim_dev_remove() become a wrapper of nsim_dev_create() and nsim_dev_destroy(). Remove this layer of indirection. Fixes: d31e95585ca6 ("Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net") Signed-off-by: Jakub Kicinski Acked-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 47 ++++++++------------------------------------- 1 file changed, 8 insertions(+), 39 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index e59a8826f36d..3da96c7e8265 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -753,7 +753,7 @@ err_fib_destroy: return err; } -static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -761,7 +761,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev)); if (!devlink) - return ERR_PTR(-ENOMEM); + return -ENOMEM; devlink_net_set(devlink, nsim_bus_dev->initial_net); nsim_dev = devlink_priv(devlink); nsim_dev->nsim_bus_dev = nsim_bus_dev; @@ -773,6 +773,8 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) nsim_dev->max_macs = NSIM_DEV_MAX_MACS_DEFAULT; nsim_dev->test1 = NSIM_DEV_TEST1_DEFAULT; + dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); + err = nsim_dev_resources_register(devlink); if (err) goto err_devlink_free; @@ -818,7 +820,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) goto err_bpf_dev_exit; devlink_params_publish(devlink); - return nsim_dev; + return 0; err_bpf_dev_exit: nsim_bpf_dev_exit(nsim_dev); @@ -841,7 +843,7 @@ err_resources_unregister: devlink_resources_unregister(devlink, NULL); err_devlink_free: devlink_free(devlink); - return ERR_PTR(err); + return err; } static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) @@ -858,8 +860,9 @@ static void nsim_dev_reload_destroy(struct nsim_dev *nsim_dev) nsim_fib_destroy(devlink, nsim_dev->fib_data); } -static void nsim_dev_destroy(struct nsim_dev *nsim_dev) +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) { + struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); struct devlink *devlink = priv_to_devlink(nsim_dev); nsim_dev_reload_destroy(nsim_dev); @@ -873,40 +876,6 @@ static void nsim_dev_destroy(struct nsim_dev *nsim_dev) devlink_free(devlink); } -int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) -{ - struct nsim_dev *nsim_dev; - int i; - int err; - - nsim_dev = nsim_dev_create(nsim_bus_dev); - if (IS_ERR(nsim_dev)) - return PTR_ERR(nsim_dev); - dev_set_drvdata(&nsim_bus_dev->dev, nsim_dev); - - mutex_lock(&nsim_dev->port_list_lock); - for (i = 0; i < nsim_bus_dev->port_count; i++) { - err = __nsim_dev_port_add(nsim_dev, i); - if (err) - goto err_port_del_all; - } - mutex_unlock(&nsim_dev->port_list_lock); - return 0; - -err_port_del_all: - mutex_unlock(&nsim_dev->port_list_lock); - nsim_dev_port_del_all(nsim_dev); - nsim_dev_destroy(nsim_dev); - return err; -} - -void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) -{ - struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); - - nsim_dev_destroy(nsim_dev); -} - static struct nsim_dev_port * __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index) { -- cgit v1.2.3 From a0c76345e3d3dbc40c39de2e00d15a3b7eef7885 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Fri, 8 Nov 2019 21:42:43 +0100 Subject: devlink: disallow reload operation during device cleanup There is a race between driver code that does setup/cleanup of device and devlink reload operation that in some drivers works with the same code. Use after free could we easily obtained by running: while true; do echo 10 > /sys/bus/netdevsim/new_device devlink dev reload netdevsim/netdevsim10 & echo 10 > /sys/bus/netdevsim/del_device done Fix this by enabling reload only after setup of device is complete and disabling it at the beginning of the cleanup process. Reported-by: Ido Schimmel Fixes: 2d8dc5bbf4e7 ("devlink: Add support for reload") Signed-off-by: Jiri Pirko Acked-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 3da96c7e8265..059711edfc61 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -820,6 +820,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) goto err_bpf_dev_exit; devlink_params_publish(devlink); + devlink_reload_enable(devlink); return 0; err_bpf_dev_exit: @@ -865,6 +866,8 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); struct devlink *devlink = priv_to_devlink(nsim_dev); + devlink_reload_disable(devlink); + nsim_dev_reload_destroy(nsim_dev); nsim_bpf_dev_exit(nsim_dev); -- cgit v1.2.3