From 8fb4bc6fd5bd5bab9a34581e45b00d9a041d1d71 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:43 +0200 Subject: netdevsim: rename devlink.c to dev.c to contain per-dev(asic) items The existing devlink.c code is going to be extended to represent asic device on a bus. As this is about more than just devlink, rename the file. Do appropriate prefix renaming alongside with that. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 241 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 drivers/net/netdevsim/dev.c (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c new file mode 100644 index 000000000000..c87f0abfaff7 --- /dev/null +++ b/drivers/net/netdevsim/dev.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018 Cumulus Networks. All rights reserved. + * Copyright (c) 2018 David Ahern + * Copyright (c) 2019 Mellanox Technologies. All rights reserved. + * + * This software is licensed under the GNU General License Version 2, + * June 1991 as shown in the file COPYING in the top-level directory of this + * source tree. + * + * THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE + * OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME + * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + */ + +#include +#include +#include + +#include "netdevsim.h" + +struct nsim_dev { + struct nsim_fib_data *fib_data; +}; + +static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) +{ + struct nsim_dev *nsim_dev = priv; + + return nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV4_FIB, false); +} + +static u64 nsim_dev_ipv4_fib_rules_res_occ_get(void *priv) +{ + struct nsim_dev *nsim_dev = priv; + + return nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV4_FIB_RULES, false); +} + +static u64 nsim_dev_ipv6_fib_resource_occ_get(void *priv) +{ + struct nsim_dev *nsim_dev = priv; + + return nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV6_FIB, false); +} + +static u64 nsim_dev_ipv6_fib_rules_res_occ_get(void *priv) +{ + struct nsim_dev *nsim_dev = priv; + + return nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV6_FIB_RULES, false); +} + +static int nsim_dev_resources_register(struct devlink *devlink) +{ + struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct devlink_resource_size_params params = { + .size_max = (u64)-1, + .size_granularity = 1, + .unit = DEVLINK_RESOURCE_UNIT_ENTRY + }; + int err; + u64 n; + + /* Resources for IPv4 */ + err = devlink_resource_register(devlink, "IPv4", (u64)-1, + NSIM_RESOURCE_IPV4, + DEVLINK_RESOURCE_ID_PARENT_TOP, + ¶ms); + if (err) { + pr_err("Failed to register IPv4 top resource\n"); + goto out; + } + + n = nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV4_FIB, true); + err = devlink_resource_register(devlink, "fib", n, + NSIM_RESOURCE_IPV4_FIB, + NSIM_RESOURCE_IPV4, ¶ms); + if (err) { + pr_err("Failed to register IPv4 FIB resource\n"); + return err; + } + + n = nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV4_FIB_RULES, true); + err = devlink_resource_register(devlink, "fib-rules", n, + NSIM_RESOURCE_IPV4_FIB_RULES, + NSIM_RESOURCE_IPV4, ¶ms); + if (err) { + pr_err("Failed to register IPv4 FIB rules resource\n"); + return err; + } + + /* Resources for IPv6 */ + err = devlink_resource_register(devlink, "IPv6", (u64)-1, + NSIM_RESOURCE_IPV6, + DEVLINK_RESOURCE_ID_PARENT_TOP, + ¶ms); + if (err) { + pr_err("Failed to register IPv6 top resource\n"); + goto out; + } + + n = nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV6_FIB, true); + err = devlink_resource_register(devlink, "fib", n, + NSIM_RESOURCE_IPV6_FIB, + NSIM_RESOURCE_IPV6, ¶ms); + if (err) { + pr_err("Failed to register IPv6 FIB resource\n"); + return err; + } + + n = nsim_fib_get_val(nsim_dev->fib_data, + NSIM_RESOURCE_IPV6_FIB_RULES, true); + err = devlink_resource_register(devlink, "fib-rules", n, + NSIM_RESOURCE_IPV6_FIB_RULES, + NSIM_RESOURCE_IPV6, ¶ms); + if (err) { + pr_err("Failed to register IPv6 FIB rules resource\n"); + return err; + } + + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV4_FIB, + nsim_dev_ipv4_fib_resource_occ_get, + nsim_dev); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV4_FIB_RULES, + nsim_dev_ipv4_fib_rules_res_occ_get, + nsim_dev); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV6_FIB, + nsim_dev_ipv6_fib_resource_occ_get, + nsim_dev); + devlink_resource_occ_get_register(devlink, + NSIM_RESOURCE_IPV6_FIB_RULES, + nsim_dev_ipv6_fib_rules_res_occ_get, + nsim_dev); +out: + return err; +} + +static int nsim_dev_reload(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; + } + } + + return 0; +} + +static const struct devlink_ops nsim_dev_devlink_ops = { + .reload = nsim_dev_reload, +}; + +static int __nsim_dev_init(struct netdevsim *ns) +{ + struct nsim_dev *nsim_dev; + struct devlink *devlink; + int err; + + devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev)); + if (!devlink) + return -ENOMEM; + nsim_dev = devlink_priv(devlink); + + nsim_dev->fib_data = nsim_fib_create(); + if (IS_ERR(nsim_dev->fib_data)) { + err = PTR_ERR(nsim_dev->fib_data); + goto err_devlink_free; + } + + err = nsim_dev_resources_register(devlink); + if (err) + goto err_fib_destroy; + + err = devlink_register(devlink, &ns->dev); + if (err) + goto err_resources_unregister; + + ns->devlink = devlink; + + return 0; + +err_resources_unregister: + devlink_resources_unregister(devlink, NULL); +err_fib_destroy: + nsim_fib_destroy(nsim_dev->fib_data); +err_devlink_free: + devlink_free(devlink); + + return err; +} + +int nsim_dev_init(struct netdevsim *ns) +{ + int err; + + dev_hold(ns->netdev); + rtnl_unlock(); + err = __nsim_dev_init(ns); + rtnl_lock(); + dev_put(ns->netdev); + return err; +} + +void nsim_dev_exit(struct netdevsim *ns) +{ + struct devlink *devlink = ns->devlink; + struct nsim_dev *nsim_dev = devlink_priv(devlink); + + devlink_unregister(devlink); + devlink_resources_unregister(devlink, NULL); + nsim_fib_destroy(nsim_dev->fib_data); + devlink_free(devlink); +} -- cgit v1.2.3 From 40e4fe4ce115c409c3e2fbb247085103ef1cc755 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:45 +0200 Subject: netdevsim: move device registration and related code to bus.c Move netdevsim device registration into bus.c and alongside with that the related sysfs attributes. Introduce new struct nsim_bus_dev to represent a netdevsim device on netdevsim bus. Signed-off-by: Jiri Pirko 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 c87f0abfaff7..c83c08edf94f 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -199,7 +199,7 @@ static int __nsim_dev_init(struct netdevsim *ns) if (err) goto err_fib_destroy; - err = devlink_register(devlink, &ns->dev); + err = devlink_register(devlink, &ns->nsim_bus_dev->dev); if (err) goto err_resources_unregister; -- cgit v1.2.3 From a60f9e48b7707b70a0701dd841e43492e1e68371 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:49 +0200 Subject: netdevsim: rename dev_init/exit() functions and make them independent on ns These functions are going to be called from bus probe/release(), therefore make them independent on ns struct and rename accordingly. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index c83c08edf94f..664b9329a65c 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -21,10 +21,6 @@ #include "netdevsim.h" -struct nsim_dev { - struct nsim_fib_data *fib_data; -}; - static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) { struct nsim_dev *nsim_dev = priv; @@ -178,7 +174,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .reload = nsim_dev_reload, }; -static int __nsim_dev_init(struct netdevsim *ns) +static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -186,7 +182,7 @@ static int __nsim_dev_init(struct netdevsim *ns) devlink = devlink_alloc(&nsim_dev_devlink_ops, sizeof(*nsim_dev)); if (!devlink) - return -ENOMEM; + return ERR_PTR(-ENOMEM); nsim_dev = devlink_priv(devlink); nsim_dev->fib_data = nsim_fib_create(); @@ -199,13 +195,11 @@ static int __nsim_dev_init(struct netdevsim *ns) if (err) goto err_fib_destroy; - err = devlink_register(devlink, &ns->nsim_bus_dev->dev); + err = devlink_register(devlink, &nsim_bus_dev->dev); if (err) goto err_resources_unregister; - ns->devlink = devlink; - - return 0; + return nsim_dev; err_resources_unregister: devlink_resources_unregister(devlink, NULL); @@ -213,26 +207,26 @@ err_fib_destroy: nsim_fib_destroy(nsim_dev->fib_data); err_devlink_free: devlink_free(devlink); - - return err; + return ERR_PTR(err); } -int nsim_dev_init(struct netdevsim *ns) +struct nsim_dev * +nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, + struct netdevsim *ns) { - int err; + struct nsim_dev *nsim_dev; dev_hold(ns->netdev); rtnl_unlock(); - err = __nsim_dev_init(ns); + nsim_dev = nsim_dev_create(nsim_bus_dev); rtnl_lock(); dev_put(ns->netdev); - return err; + return nsim_dev; } -void nsim_dev_exit(struct netdevsim *ns) +void nsim_dev_destroy(struct nsim_dev *nsim_dev) { - struct devlink *devlink = ns->devlink; - struct nsim_dev *nsim_dev = devlink_priv(devlink); + struct devlink *devlink = priv_to_devlink(nsim_dev); devlink_unregister(devlink); devlink_resources_unregister(devlink, NULL); -- cgit v1.2.3 From d514f41e793d2cbc737ba107d7ae26f387f5eecf Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:50 +0200 Subject: netdevsim: merge sdev into dev As previously introduce dev which is mapped 1:1 to a bus device covers the purpose of the original shared device, merge the sdev code into dev. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 47 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 664b9329a65c..93abd0b6c1f9 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -15,12 +15,31 @@ * THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. */ +#include #include #include #include #include "netdevsim.h" +static struct dentry *nsim_dev_ddir; + +static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) +{ + char dev_ddir_name[10]; + + sprintf(dev_ddir_name, "%u", nsim_dev->nsim_bus_dev->dev.id); + nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir); + if (IS_ERR_OR_NULL(nsim_dev->ddir)) + return PTR_ERR_OR_ZERO(nsim_dev->ddir) ?: -EINVAL; + return 0; +} + +static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev) +{ + debugfs_remove_recursive(nsim_dev->ddir); +} + static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) { struct nsim_dev *nsim_dev = priv; @@ -184,6 +203,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) if (!devlink) return ERR_PTR(-ENOMEM); nsim_dev = devlink_priv(devlink); + nsim_dev->nsim_bus_dev = nsim_bus_dev; nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { @@ -199,8 +219,20 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) if (err) goto err_resources_unregister; + err = nsim_dev_debugfs_init(nsim_dev); + if (err) + goto err_dl_unregister; + + err = nsim_bpf_dev_init(nsim_dev); + if (err) + goto err_debugfs_exit; + return nsim_dev; +err_debugfs_exit: + nsim_dev_debugfs_exit(nsim_dev); +err_dl_unregister: + devlink_unregister(devlink); err_resources_unregister: devlink_resources_unregister(devlink, NULL); err_fib_destroy: @@ -228,8 +260,23 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev) { struct devlink *devlink = priv_to_devlink(nsim_dev); + nsim_bpf_dev_exit(nsim_dev); + nsim_dev_debugfs_exit(nsim_dev); devlink_unregister(devlink); devlink_resources_unregister(devlink, NULL); nsim_fib_destroy(nsim_dev->fib_data); devlink_free(devlink); } + +int nsim_dev_init(void) +{ + nsim_dev_ddir = debugfs_create_dir(DRV_NAME "_dev", NULL); + if (IS_ERR_OR_NULL(nsim_dev_ddir)) + return -ENOMEM; + return 0; +} + +void nsim_dev_exit(void) +{ + debugfs_remove_recursive(nsim_dev_ddir); +} -- cgit v1.2.3 From 514cf64cc5353929fbfb82ed1bda24588acaf96a Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:51 +0200 Subject: netdevsim: generate random switch id instead of using dev id Current implementation of parent_id/switch_id does not follow the original idea of being unique. The values are "0", "1", etc. Instead of that, generate 32 random bytes. Signed-off-by: Jiri Pirko 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 93abd0b6c1f9..98a56d8bdcec 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -204,6 +205,8 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) return ERR_PTR(-ENOMEM); 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); + get_random_bytes(nsim_dev->switch_id.id, nsim_dev->switch_id.id_len); nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { -- cgit v1.2.3 From ab1d0cc004d706523dcad7cdad97a2b94eecf169 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:52 +0200 Subject: netdevsim: change debugfs tree topology With the model where dev is represented by devlink and ports are represented by devlink ports, make debugfs file names independent on netdev names. Change the topology to the one illustrated by the following example: $ ls /sys/kernel/debug/netdevsim/ netdevsim1 $ ls /sys/kernel/debug/netdevsim/netdevsim1/ bpf_bind_accept bpf_bind_verifier_delay bpf_bound_progs ports $ ls /sys/kernel/debug/netdevsim/netdevsim1/ports/ 0 1 $ ls /sys/kernel/debug/netdevsim/netdevsim1/ports/0/ bpf_map_accept bpf_offloaded_id bpf_tc_accept bpf_tc_non_bound_accept bpf_xdpdrv_accept bpf_xdpoffload_accept dev ipsec $ ls /sys/kernel/debug/netdevsim/netdevsim1/ports/0/dev -l lrwxrwxrwx 1 root root 0 Apr 13 15:58 /sys/kernel/debug/netdevsim/netdevsim1/ports/0/dev -> ../../../netdevsim1 Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 10 +++++++--- 1 file changed, 7 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 98a56d8bdcec..14946d162e53 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -27,17 +27,21 @@ static struct dentry *nsim_dev_ddir; static int nsim_dev_debugfs_init(struct nsim_dev *nsim_dev) { - char dev_ddir_name[10]; + char dev_ddir_name[16]; - sprintf(dev_ddir_name, "%u", nsim_dev->nsim_bus_dev->dev.id); + sprintf(dev_ddir_name, DRV_NAME "%u", nsim_dev->nsim_bus_dev->dev.id); nsim_dev->ddir = debugfs_create_dir(dev_ddir_name, nsim_dev_ddir); if (IS_ERR_OR_NULL(nsim_dev->ddir)) return PTR_ERR_OR_ZERO(nsim_dev->ddir) ?: -EINVAL; + nsim_dev->ports_ddir = debugfs_create_dir("ports", nsim_dev->ddir); + if (IS_ERR_OR_NULL(nsim_dev->ports_ddir)) + return PTR_ERR_OR_ZERO(nsim_dev->ports_ddir) ?: -EINVAL; return 0; } static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev) { + debugfs_remove_recursive(nsim_dev->ports_ddir); debugfs_remove_recursive(nsim_dev->ddir); } @@ -273,7 +277,7 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev) int nsim_dev_init(void) { - nsim_dev_ddir = debugfs_create_dir(DRV_NAME "_dev", NULL); + nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL); if (IS_ERR_OR_NULL(nsim_dev_ddir)) return -ENOMEM; return 0; -- cgit v1.2.3 From 8320d145912738655cf631d27aa1829d8b17804e Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:53 +0200 Subject: netdevsim: implement dev probe/remove skeleton with port initialization Implement netdevsim bus probing of netdevsim devices. For every probed device create a devlink instance. According to the user-passed value, create a number of ports represented by devlink port instances. Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 130 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 115 insertions(+), 15 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index 14946d162e53..6ee9d43ae252 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,30 @@ static void nsim_dev_debugfs_exit(struct nsim_dev *nsim_dev) debugfs_remove_recursive(nsim_dev->ddir); } +static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, + struct nsim_dev_port *nsim_dev_port) +{ + char port_ddir_name[16]; + char dev_link_name[32]; + + sprintf(port_ddir_name, "%u", nsim_dev_port->port_index); + nsim_dev_port->ddir = debugfs_create_dir(port_ddir_name, + nsim_dev->ports_ddir); + if (IS_ERR_OR_NULL(nsim_dev_port->ddir)) + return -ENOMEM; + + sprintf(dev_link_name, "../../../" DRV_NAME "%u", + nsim_dev->nsim_bus_dev->dev.id); + debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name); + + return 0; +} + +static void nsim_dev_port_debugfs_exit(struct nsim_dev_port *nsim_dev_port) +{ + debugfs_remove_recursive(nsim_dev_port->ddir); +} + static u64 nsim_dev_ipv4_fib_resource_occ_get(void *priv) { struct nsim_dev *nsim_dev = priv; @@ -198,7 +223,8 @@ static const struct devlink_ops nsim_dev_devlink_ops = { .reload = nsim_dev_reload, }; -static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) +static struct nsim_dev * +nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) { struct nsim_dev *nsim_dev; struct devlink *devlink; @@ -211,6 +237,7 @@ static struct nsim_dev *nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev) nsim_dev->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); nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { @@ -249,20 +276,6 @@ err_devlink_free: return ERR_PTR(err); } -struct nsim_dev * -nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, - struct netdevsim *ns) -{ - struct nsim_dev *nsim_dev; - - dev_hold(ns->netdev); - rtnl_unlock(); - nsim_dev = nsim_dev_create(nsim_bus_dev); - rtnl_lock(); - dev_put(ns->netdev); - return nsim_dev; -} - void nsim_dev_destroy(struct nsim_dev *nsim_dev) { struct devlink *devlink = priv_to_devlink(nsim_dev); @@ -275,6 +288,93 @@ 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; + + list_add(&nsim_dev_port->list, &nsim_dev->port_list); + + return 0; + +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); + 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); + 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); +} + int nsim_dev_init(void) { nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL); -- cgit v1.2.3 From 794b2c05ca1c4ded4a023d11833e3855a0ed6ea8 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:54 +0200 Subject: netdevsim: extend device attrs to support port addition and deletion In order to test flows in core, it is beneficial to maintain previously supported possibility to add and delete ports during netdevsim lifetime. Do it by extending device sysfs attrs by "new_port" and "del_port". Signed-off-by: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 55 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 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 6ee9d43ae252..2fa1b2061370 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -238,6 +239,7 @@ nsim_dev_create(struct nsim_bus_dev *nsim_bus_dev, unsigned int port_count) 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); + mutex_init(&nsim_dev->port_list_lock); nsim_dev->fib_data = nsim_fib_create(); if (IS_ERR(nsim_dev->fib_data)) { @@ -285,10 +287,12 @@ void nsim_dev_destroy(struct nsim_dev *nsim_dev) devlink_unregister(devlink); devlink_resources_unregister(devlink, NULL); nsim_fib_destroy(nsim_dev->fib_data); + mutex_destroy(&nsim_dev->port_list_lock); devlink_free(devlink); } -static int nsim_dev_port_add(struct nsim_dev *nsim_dev, unsigned int port_index) +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; @@ -324,7 +328,7 @@ err_port_free: return err; } -static void nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port) +static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port) { struct devlink_port *devlink_port = &nsim_dev_port->devlink_port; @@ -340,7 +344,7 @@ static void nsim_dev_port_del_all(struct nsim_dev *nsim_dev) list_for_each_entry_safe(nsim_dev_port, tmp, &nsim_dev->port_list, list) - nsim_dev_port_del(nsim_dev_port); + __nsim_dev_port_del(nsim_dev_port); } int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev) @@ -355,7 +359,7 @@ int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_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); + err = __nsim_dev_port_add(nsim_dev, i); if (err) goto err_port_del_all; } @@ -375,6 +379,49 @@ void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev) nsim_dev_destroy(nsim_dev); } +static struct nsim_dev_port * +__nsim_dev_port_lookup(struct nsim_dev *nsim_dev, unsigned int port_index) +{ + struct nsim_dev_port *nsim_dev_port; + + list_for_each_entry(nsim_dev_port, &nsim_dev->port_list, list) + if (nsim_dev_port->port_index == port_index) + return nsim_dev_port; + return NULL; +} + +int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, + unsigned int port_index) +{ + struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); + int err; + + mutex_lock(&nsim_dev->port_list_lock); + if (__nsim_dev_port_lookup(nsim_dev, port_index)) + err = -EEXIST; + else + err = __nsim_dev_port_add(nsim_dev, port_index); + mutex_unlock(&nsim_dev->port_list_lock); + return err; +} + +int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, + unsigned int port_index) +{ + struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev); + struct nsim_dev_port *nsim_dev_port; + int err = 0; + + mutex_lock(&nsim_dev->port_list_lock); + nsim_dev_port = __nsim_dev_port_lookup(nsim_dev, port_index); + if (!nsim_dev_port) + err = -ENOENT; + else + __nsim_dev_port_del(nsim_dev_port); + mutex_unlock(&nsim_dev->port_list_lock); + return err; +} + int nsim_dev_init(void) { nsim_dev_ddir = debugfs_create_dir(DRV_NAME, NULL); -- cgit v1.2.3 From e05b2d141fef22cfac1928cf0eb6890e5dae4216 Mon Sep 17 00:00:00 2001 From: Jiri Pirko Date: Thu, 25 Apr 2019 15:59:55 +0200 Subject: 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: Jiri Pirko Signed-off-by: David S. Miller --- drivers/net/netdevsim/dev.c | 13 ++++++++++++- 1 file changed, 12 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 2fa1b2061370..b509b941d5ca 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -278,7 +278,7 @@ err_devlink_free: 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); -- cgit v1.2.3