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/bus.c | 142 ++++++++++++++++++++++++++- drivers/net/netdevsim/dev.c | 2 +- drivers/net/netdevsim/netdev.c | 195 +++++++++----------------------------- drivers/net/netdevsim/netdevsim.h | 31 +++--- 4 files changed, 207 insertions(+), 163 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index 26b866b72afc..7e83a2e856d3 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -4,15 +4,155 @@ */ #include +#include +#include +#include +#include #include "netdevsim.h" -struct bus_type nsim_bus = { +static u32 nsim_bus_dev_id; + +static struct nsim_bus_dev *to_nsim_bus_dev(struct device *dev) +{ + return container_of(dev, struct nsim_bus_dev, dev); +} + +static int nsim_bus_dev_vfs_enable(struct nsim_bus_dev *nsim_bus_dev, + unsigned int num_vfs) +{ + nsim_bus_dev->vfconfigs = kcalloc(num_vfs, + sizeof(struct nsim_vf_config), + GFP_KERNEL); + if (!nsim_bus_dev->vfconfigs) + return -ENOMEM; + nsim_bus_dev->num_vfs = num_vfs; + + return 0; +} + +static void nsim_bus_dev_vfs_disable(struct nsim_bus_dev *nsim_bus_dev) +{ + kfree(nsim_bus_dev->vfconfigs); + nsim_bus_dev->vfconfigs = NULL; + nsim_bus_dev->num_vfs = 0; +} + +static ssize_t +nsim_bus_dev_numvfs_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + unsigned int num_vfs; + int ret; + + ret = kstrtouint(buf, 0, &num_vfs); + if (ret) + return ret; + + rtnl_lock(); + if (nsim_bus_dev->num_vfs == num_vfs) + goto exit_good; + if (nsim_bus_dev->num_vfs && num_vfs) { + ret = -EBUSY; + goto exit_unlock; + } + + if (num_vfs) { + ret = nsim_bus_dev_vfs_enable(nsim_bus_dev, num_vfs); + if (ret) + goto exit_unlock; + } else { + nsim_bus_dev_vfs_disable(nsim_bus_dev); + } +exit_good: + ret = count; +exit_unlock: + rtnl_unlock(); + + return ret; +} + +static ssize_t +nsim_bus_dev_numvfs_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + return sprintf(buf, "%u\n", nsim_bus_dev->num_vfs); +} + +static struct device_attribute nsim_bus_dev_numvfs_attr = + __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, + nsim_bus_dev_numvfs_store); + +static struct attribute *nsim_bus_dev_attrs[] = { + &nsim_bus_dev_numvfs_attr.attr, + NULL, +}; + +static const struct attribute_group nsim_bus_dev_attr_group = { + .attrs = nsim_bus_dev_attrs, +}; + +static const struct attribute_group *nsim_bus_dev_attr_groups[] = { + &nsim_bus_dev_attr_group, + NULL, +}; + +static void nsim_bus_dev_release(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + nsim_bus_dev_vfs_disable(nsim_bus_dev); +} + +static struct device_type nsim_bus_dev_type = { + .groups = nsim_bus_dev_attr_groups, + .release = nsim_bus_dev_release, +}; + +int nsim_num_vf(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + return nsim_bus_dev->num_vfs; +} + +static struct bus_type nsim_bus = { .name = DRV_NAME, .dev_name = DRV_NAME, .num_vf = nsim_num_vf, }; +struct nsim_bus_dev *nsim_bus_dev_new(void) +{ + struct nsim_bus_dev *nsim_bus_dev; + int err; + + nsim_bus_dev = kzalloc(sizeof(*nsim_bus_dev), GFP_KERNEL); + if (!nsim_bus_dev) + return ERR_PTR(-ENOMEM); + + nsim_bus_dev->dev.id = nsim_bus_dev_id++; + nsim_bus_dev->dev.bus = &nsim_bus; + nsim_bus_dev->dev.type = &nsim_bus_dev_type; + err = device_register(&nsim_bus_dev->dev); + if (err) + goto err_nsim_bus_dev_free; + return nsim_bus_dev; + +err_nsim_bus_dev_free: + kfree(nsim_bus_dev); + return ERR_PTR(err); +} + +void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) +{ + device_unregister(&nsim_bus_dev->dev); + kfree(nsim_bus_dev); +} + int nsim_bus_init(void) { return bus_register(&nsim_bus); 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; diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 7bc0da8cc10d..3407b009929e 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -25,120 +25,8 @@ #include "netdevsim.h" -static u32 nsim_dev_id; - -struct nsim_vf_config { - int link_state; - u16 min_tx_rate; - u16 max_tx_rate; - u16 vlan; - __be16 vlan_proto; - u16 qos; - u8 vf_mac[ETH_ALEN]; - bool spoofchk_enabled; - bool trusted; - bool rss_query_enabled; -}; - static struct dentry *nsim_ddir; -int nsim_num_vf(struct device *dev) -{ - struct netdevsim *ns = to_nsim(dev); - - return ns->num_vfs; -} - -static int nsim_vfs_enable(struct netdevsim *ns, unsigned int num_vfs) -{ - ns->vfconfigs = kcalloc(num_vfs, sizeof(struct nsim_vf_config), - GFP_KERNEL); - if (!ns->vfconfigs) - return -ENOMEM; - ns->num_vfs = num_vfs; - - return 0; -} - -static void nsim_vfs_disable(struct netdevsim *ns) -{ - kfree(ns->vfconfigs); - ns->vfconfigs = NULL; - ns->num_vfs = 0; -} - -static ssize_t -nsim_numvfs_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct netdevsim *ns = to_nsim(dev); - unsigned int num_vfs; - int ret; - - ret = kstrtouint(buf, 0, &num_vfs); - if (ret) - return ret; - - rtnl_lock(); - if (ns->num_vfs == num_vfs) - goto exit_good; - if (ns->num_vfs && num_vfs) { - ret = -EBUSY; - goto exit_unlock; - } - - if (num_vfs) { - ret = nsim_vfs_enable(ns, num_vfs); - if (ret) - goto exit_unlock; - } else { - nsim_vfs_disable(ns); - } -exit_good: - ret = count; -exit_unlock: - rtnl_unlock(); - - return ret; -} - -static ssize_t -nsim_numvfs_show(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct netdevsim *ns = to_nsim(dev); - - return sprintf(buf, "%u\n", ns->num_vfs); -} - -static struct device_attribute nsim_numvfs_attr = - __ATTR(sriov_numvfs, 0664, nsim_numvfs_show, nsim_numvfs_store); - -static struct attribute *nsim_dev_attrs[] = { - &nsim_numvfs_attr.attr, - NULL, -}; - -static const struct attribute_group nsim_dev_attr_group = { - .attrs = nsim_dev_attrs, -}; - -static const struct attribute_group *nsim_dev_attr_groups[] = { - &nsim_dev_attr_group, - NULL, -}; - -static void nsim_dev_release(struct device *dev) -{ - struct netdevsim *ns = to_nsim(dev); - - nsim_vfs_disable(ns); -} - -static struct device_type nsim_dev_type = { - .groups = nsim_dev_attr_groups, - .release = nsim_dev_release, -}; - static int nsim_get_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid) { @@ -190,7 +78,7 @@ static void nsim_free(struct net_device *dev) struct netdevsim *ns = netdev_priv(dev); nsim_dev_exit(ns); - device_unregister(&ns->dev); + nsim_bus_dev_del(ns->nsim_bus_dev); /* netdev and vf state will be freed out of device_release() */ nsim_sdev_put(ns->sdev); } @@ -271,11 +159,12 @@ nsim_setup_tc_block(struct net_device *dev, struct tc_block_offload *f) static int nsim_set_vf_mac(struct net_device *dev, int vf, u8 *mac) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; /* Only refuse multicast addresses, zero address can mean unset/any. */ - if (vf >= ns->num_vfs || is_multicast_ether_addr(mac)) + if (vf >= nsim_bus_dev->num_vfs || is_multicast_ether_addr(mac)) return -EINVAL; - memcpy(ns->vfconfigs[vf].vf_mac, mac, ETH_ALEN); + memcpy(nsim_bus_dev->vfconfigs[vf].vf_mac, mac, ETH_ALEN); return 0; } @@ -284,13 +173,14 @@ static int nsim_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos, __be16 vlan_proto) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs || vlan > 4095 || qos > 7) + if (vf >= nsim_bus_dev->num_vfs || vlan > 4095 || qos > 7) return -EINVAL; - ns->vfconfigs[vf].vlan = vlan; - ns->vfconfigs[vf].qos = qos; - ns->vfconfigs[vf].vlan_proto = vlan_proto; + nsim_bus_dev->vfconfigs[vf].vlan = vlan; + nsim_bus_dev->vfconfigs[vf].qos = qos; + nsim_bus_dev->vfconfigs[vf].vlan_proto = vlan_proto; return 0; } @@ -298,12 +188,13 @@ static int nsim_set_vf_vlan(struct net_device *dev, int vf, static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; - ns->vfconfigs[vf].min_tx_rate = min; - ns->vfconfigs[vf].max_tx_rate = max; + nsim_bus_dev->vfconfigs[vf].min_tx_rate = min; + nsim_bus_dev->vfconfigs[vf].max_tx_rate = max; return 0; } @@ -311,10 +202,11 @@ static int nsim_set_vf_rate(struct net_device *dev, int vf, int min, int max) static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; - ns->vfconfigs[vf].spoofchk_enabled = val; + nsim_bus_dev->vfconfigs[vf].spoofchk_enabled = val; return 0; } @@ -322,10 +214,11 @@ static int nsim_set_vf_spoofchk(struct net_device *dev, int vf, bool val) static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; - ns->vfconfigs[vf].rss_query_enabled = val; + nsim_bus_dev->vfconfigs[vf].rss_query_enabled = val; return 0; } @@ -333,10 +226,11 @@ static int nsim_set_vf_rss_query_en(struct net_device *dev, int vf, bool val) static int nsim_set_vf_trust(struct net_device *dev, int vf, bool val) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; - ns->vfconfigs[vf].trusted = val; + nsim_bus_dev->vfconfigs[vf].trusted = val; return 0; } @@ -345,21 +239,22 @@ static int nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; ivi->vf = vf; - ivi->linkstate = ns->vfconfigs[vf].link_state; - ivi->min_tx_rate = ns->vfconfigs[vf].min_tx_rate; - ivi->max_tx_rate = ns->vfconfigs[vf].max_tx_rate; - ivi->vlan = ns->vfconfigs[vf].vlan; - ivi->vlan_proto = ns->vfconfigs[vf].vlan_proto; - ivi->qos = ns->vfconfigs[vf].qos; - memcpy(&ivi->mac, ns->vfconfigs[vf].vf_mac, ETH_ALEN); - ivi->spoofchk = ns->vfconfigs[vf].spoofchk_enabled; - ivi->trusted = ns->vfconfigs[vf].trusted; - ivi->rss_query_en = ns->vfconfigs[vf].rss_query_enabled; + ivi->linkstate = nsim_bus_dev->vfconfigs[vf].link_state; + ivi->min_tx_rate = nsim_bus_dev->vfconfigs[vf].min_tx_rate; + ivi->max_tx_rate = nsim_bus_dev->vfconfigs[vf].max_tx_rate; + ivi->vlan = nsim_bus_dev->vfconfigs[vf].vlan; + ivi->vlan_proto = nsim_bus_dev->vfconfigs[vf].vlan_proto; + ivi->qos = nsim_bus_dev->vfconfigs[vf].qos; + memcpy(&ivi->mac, nsim_bus_dev->vfconfigs[vf].vf_mac, ETH_ALEN); + ivi->spoofchk = nsim_bus_dev->vfconfigs[vf].spoofchk_enabled; + ivi->trusted = nsim_bus_dev->vfconfigs[vf].trusted; + ivi->rss_query_en = nsim_bus_dev->vfconfigs[vf].rss_query_enabled; return 0; } @@ -367,8 +262,9 @@ nsim_get_vf_config(struct net_device *dev, int vf, struct ifla_vf_info *ivi) static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state) { struct netdevsim *ns = netdev_priv(dev); + struct nsim_bus_dev *nsim_bus_dev = ns->nsim_bus_dev; - if (vf >= ns->num_vfs) + if (vf >= nsim_bus_dev->num_vfs) return -EINVAL; switch (state) { @@ -380,7 +276,7 @@ static int nsim_set_vf_link_state(struct net_device *dev, int vf, int state) return -EINVAL; } - ns->vfconfigs[vf].link_state = state; + nsim_bus_dev->vfconfigs[vf].link_state = state; return 0; } @@ -490,19 +386,18 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, if (IS_ERR(ns->sdev)) return PTR_ERR(ns->sdev); - ns->dev.id = nsim_dev_id++; - ns->dev.bus = &nsim_bus; - ns->dev.type = &nsim_dev_type; - err = device_register(&ns->dev); - if (err) + ns->nsim_bus_dev = nsim_bus_dev_new(); + if (IS_ERR(ns->nsim_bus_dev)) { + err = PTR_ERR(ns->nsim_bus_dev); goto err_sdev_put; + } - SET_NETDEV_DEV(dev, &ns->dev); + SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); ns->netdev = dev; err = nsim_dev_init(ns); if (err) - goto err_unreg_dev; + goto err_dev_del; err = register_netdevice(dev); if (err) @@ -511,8 +406,8 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, err_dev_exit: nsim_dev_exit(ns); -err_unreg_dev: - device_unregister(&ns->dev); +err_dev_del: + nsim_bus_dev_del(ns->nsim_bus_dev); err_sdev_put: nsim_sdev_put(ns->sdev); return err; diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 7a144aa7965a..528d1e7d3e6b 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -85,14 +85,11 @@ struct netdevsim { u64 tx_bytes; struct u64_stats_sync syncp; - struct device dev; + struct nsim_bus_dev *nsim_bus_dev; struct netdevsim_shared_dev *sdev; struct dentry *ddir; - unsigned int num_vfs; - struct nsim_vf_config *vfconfigs; - struct bpf_prog *bpf_offloaded; u32 bpf_offloaded_id; @@ -184,14 +181,26 @@ static inline bool nsim_ipsec_tx(struct netdevsim *ns, struct sk_buff *skb) } #endif -static inline struct netdevsim *to_nsim(struct device *ptr) -{ - return container_of(ptr, struct netdevsim, dev); -} - -int nsim_num_vf(struct device *dev); +struct nsim_vf_config { + int link_state; + u16 min_tx_rate; + u16 max_tx_rate; + u16 vlan; + __be16 vlan_proto; + u16 qos; + u8 vf_mac[ETH_ALEN]; + bool spoofchk_enabled; + bool trusted; + bool rss_query_enabled; +}; -extern struct bus_type nsim_bus; +struct nsim_bus_dev { + struct device dev; + unsigned int num_vfs; + struct nsim_vf_config *vfconfigs; +}; +struct nsim_bus_dev *nsim_bus_dev_new(void); +void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); int nsim_bus_init(void); void nsim_bus_exit(void); -- 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 +++++++++++++------------------- drivers/net/netdevsim/netdev.c | 14 ++++++++------ drivers/net/netdevsim/netdevsim.h | 12 +++++++++--- 3 files changed, 30 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 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); diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 37a442ffcb8b..28231bfbc989 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -77,7 +77,7 @@ static void nsim_free(struct net_device *dev) { struct netdevsim *ns = netdev_priv(dev); - nsim_dev_exit(ns); + nsim_dev_destroy(ns->nsim_dev); nsim_bus_dev_del(ns->nsim_bus_dev); /* netdev and vf state will be freed out of device_release() */ nsim_sdev_put(ns->sdev); @@ -395,17 +395,19 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); ns->netdev = dev; - err = nsim_dev_init(ns); - if (err) + ns->nsim_dev = nsim_dev_create_with_ns(ns->nsim_bus_dev, ns); + if (IS_ERR(ns->nsim_dev)) { + err = PTR_ERR(ns->nsim_dev); goto err_dev_del; + } err = register_netdevice(dev); if (err) - goto err_dev_exit; + goto err_dev_destroy; return 0; -err_dev_exit: - nsim_dev_exit(ns); +err_dev_destroy: + nsim_dev_destroy(ns->nsim_dev); err_dev_del: nsim_bus_dev_del(ns->nsim_bus_dev); err_sdev_put: diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 8d61fcb55f39..d6b3668f9afd 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -80,6 +80,7 @@ struct nsim_ipsec { struct netdevsim { struct net_device *netdev; + struct nsim_dev *nsim_dev; u64 tx_packets; u64 tx_bytes; @@ -102,7 +103,6 @@ struct netdevsim { bool bpf_xdpoffload_accept; bool bpf_map_accept; - struct devlink *devlink; struct nsim_ipsec ipsec; }; @@ -151,8 +151,14 @@ enum nsim_resource_id { NSIM_RESOURCE_IPV6_FIB_RULES, }; -int nsim_dev_init(struct netdevsim *ns); -void nsim_dev_exit(struct netdevsim *ns); +struct nsim_dev { + struct nsim_fib_data *fib_data; +}; + +struct nsim_dev * +nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, + struct netdevsim *ns); +void nsim_dev_destroy(struct nsim_dev *nsim_dev); struct nsim_fib_data *nsim_fib_create(void); void nsim_fib_destroy(struct nsim_fib_data *fib_data); -- 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/Makefile | 2 +- drivers/net/netdevsim/bpf.c | 79 ++++++++++++----------------- drivers/net/netdevsim/dev.c | 47 +++++++++++++++++ drivers/net/netdevsim/netdev.c | 49 +++++------------- drivers/net/netdevsim/netdevsim.h | 54 ++++++++------------ tools/testing/selftests/bpf/test_offload.py | 8 +-- 6 files changed, 120 insertions(+), 119 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/Makefile b/drivers/net/netdevsim/Makefile index ab7e2c42088f..09f1315d2f2a 100644 --- a/drivers/net/netdevsim/Makefile +++ b/drivers/net/netdevsim/Makefile @@ -3,7 +3,7 @@ obj-$(CONFIG_NETDEVSIM) += netdevsim.o netdevsim-objs := \ - netdev.o dev.o fib.o sdev.o bus.o + netdev.o dev.o fib.o bus.o ifeq ($(CONFIG_BPF_SYSCALL),y) netdevsim-objs += \ diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index a93aafe87db3..89980b223adc 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -27,7 +27,7 @@ bpf_verifier_log_write(env, "[netdevsim] " fmt, ##__VA_ARGS__) struct nsim_bpf_bound_prog { - struct netdevsim_shared_dev *sdev; + struct nsim_dev *nsim_dev; struct bpf_prog *prog; struct dentry *ddir; const char *state; @@ -65,8 +65,8 @@ nsim_bpf_verify_insn(struct bpf_verifier_env *env, int insn_idx, int prev_insn) struct nsim_bpf_bound_prog *state; state = env->prog->aux->offload->dev_priv; - if (state->sdev->bpf_bind_verifier_delay && !insn_idx) - msleep(state->sdev->bpf_bind_verifier_delay); + if (state->nsim_dev->bpf_bind_verifier_delay && !insn_idx) + msleep(state->nsim_dev->bpf_bind_verifier_delay); if (insn_idx == env->prog->len - 1) pr_vlog(env, "Hello from netdevsim!\n"); @@ -213,7 +213,7 @@ nsim_xdp_set_prog(struct netdevsim *ns, struct netdev_bpf *bpf, return 0; } -static int nsim_bpf_create_prog(struct netdevsim_shared_dev *sdev, +static int nsim_bpf_create_prog(struct nsim_dev *nsim_dev, struct bpf_prog *prog) { struct nsim_bpf_bound_prog *state; @@ -223,13 +223,13 @@ static int nsim_bpf_create_prog(struct netdevsim_shared_dev *sdev, if (!state) return -ENOMEM; - state->sdev = sdev; + state->nsim_dev = nsim_dev; state->prog = prog; state->state = "verify"; /* Program id is not populated yet when we create the state. */ - sprintf(name, "%u", sdev->prog_id_gen++); - state->ddir = debugfs_create_dir(name, sdev->ddir_bpf_bound_progs); + sprintf(name, "%u", nsim_dev->prog_id_gen++); + state->ddir = debugfs_create_dir(name, nsim_dev->ddir_bpf_bound_progs); if (IS_ERR_OR_NULL(state->ddir)) { kfree(state); return -ENOMEM; @@ -240,7 +240,7 @@ static int nsim_bpf_create_prog(struct netdevsim_shared_dev *sdev, &state->state, &nsim_bpf_string_fops); debugfs_create_bool("loaded", 0400, state->ddir, &state->is_loaded); - list_add_tail(&state->l, &sdev->bpf_bound_progs); + list_add_tail(&state->l, &nsim_dev->bpf_bound_progs); prog->aux->offload->dev_priv = state; @@ -249,13 +249,13 @@ static int nsim_bpf_create_prog(struct netdevsim_shared_dev *sdev, static int nsim_bpf_verifier_prep(struct bpf_prog *prog) { - struct netdevsim_shared_dev *sdev = + struct nsim_dev *nsim_dev = bpf_offload_dev_priv(prog->aux->offload->offdev); - if (!sdev->bpf_bind_accept) + if (!nsim_dev->bpf_bind_accept) return -EOPNOTSUPP; - return nsim_bpf_create_prog(sdev, prog); + return nsim_bpf_create_prog(nsim_dev, prog); } static int nsim_bpf_translate(struct bpf_prog *prog) @@ -514,7 +514,7 @@ nsim_bpf_map_alloc(struct netdevsim *ns, struct bpf_offloaded_map *offmap) } offmap->dev_ops = &nsim_bpf_map_ops; - list_add_tail(&nmap->l, &ns->sdev->bpf_bound_maps); + list_add_tail(&nmap->l, &ns->nsim_dev->bpf_bound_maps); return 0; @@ -578,51 +578,46 @@ int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf) } } -static int nsim_bpf_sdev_init(struct netdevsim_shared_dev *sdev) +int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) { int err; - INIT_LIST_HEAD(&sdev->bpf_bound_progs); - INIT_LIST_HEAD(&sdev->bpf_bound_maps); + INIT_LIST_HEAD(&nsim_dev->bpf_bound_progs); + INIT_LIST_HEAD(&nsim_dev->bpf_bound_maps); - sdev->ddir_bpf_bound_progs = - debugfs_create_dir("bpf_bound_progs", sdev->ddir); - if (IS_ERR_OR_NULL(sdev->ddir_bpf_bound_progs)) + nsim_dev->ddir_bpf_bound_progs = debugfs_create_dir("bpf_bound_progs", + nsim_dev->ddir); + if (IS_ERR_OR_NULL(nsim_dev->ddir_bpf_bound_progs)) return -ENOMEM; - sdev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops, sdev); - err = PTR_ERR_OR_ZERO(sdev->bpf_dev); + nsim_dev->bpf_dev = bpf_offload_dev_create(&nsim_bpf_dev_ops, nsim_dev); + err = PTR_ERR_OR_ZERO(nsim_dev->bpf_dev); if (err) return err; - sdev->bpf_bind_accept = true; - debugfs_create_bool("bpf_bind_accept", 0600, sdev->ddir, - &sdev->bpf_bind_accept); - debugfs_create_u32("bpf_bind_verifier_delay", 0600, sdev->ddir, - &sdev->bpf_bind_verifier_delay); + nsim_dev->bpf_bind_accept = true; + debugfs_create_bool("bpf_bind_accept", 0600, nsim_dev->ddir, + &nsim_dev->bpf_bind_accept); + debugfs_create_u32("bpf_bind_verifier_delay", 0600, nsim_dev->ddir, + &nsim_dev->bpf_bind_verifier_delay); return 0; } -static void nsim_bpf_sdev_uninit(struct netdevsim_shared_dev *sdev) +void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) { - WARN_ON(!list_empty(&sdev->bpf_bound_progs)); - WARN_ON(!list_empty(&sdev->bpf_bound_maps)); - bpf_offload_dev_destroy(sdev->bpf_dev); + WARN_ON(!list_empty(&nsim_dev->bpf_bound_progs)); + WARN_ON(!list_empty(&nsim_dev->bpf_bound_maps)); + bpf_offload_dev_destroy(nsim_dev->bpf_dev); } int nsim_bpf_init(struct netdevsim *ns) { int err; - if (ns->sdev->refcnt == 1) { - err = nsim_bpf_sdev_init(ns->sdev); - if (err) - return err; - } - - err = bpf_offload_dev_netdev_register(ns->sdev->bpf_dev, ns->netdev); + err = bpf_offload_dev_netdev_register(ns->nsim_dev->bpf_dev, + ns->netdev); if (err) - goto err_bpf_sdev_uninit; + return err; debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir, &ns->bpf_offloaded_id); @@ -644,11 +639,6 @@ int nsim_bpf_init(struct netdevsim *ns) &ns->bpf_map_accept); return 0; - -err_bpf_sdev_uninit: - if (ns->sdev->refcnt == 1) - nsim_bpf_sdev_uninit(ns->sdev); - return err; } void nsim_bpf_uninit(struct netdevsim *ns) @@ -656,8 +646,5 @@ void nsim_bpf_uninit(struct netdevsim *ns) WARN_ON(ns->xdp.prog); WARN_ON(ns->xdp_hw.prog); WARN_ON(ns->bpf_offloaded); - bpf_offload_dev_netdev_unregister(ns->sdev->bpf_dev, ns->netdev); - - if (ns->sdev->refcnt == 1) - nsim_bpf_sdev_uninit(ns->sdev); + bpf_offload_dev_netdev_unregister(ns->nsim_dev->bpf_dev, ns->netdev); } 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); +} diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 28231bfbc989..c5f4bbb9716f 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -32,24 +32,24 @@ static int nsim_get_port_parent_id(struct net_device *dev, { struct netdevsim *ns = netdev_priv(dev); - ppid->id_len = sizeof(ns->sdev->switch_id); - memcpy(&ppid->id, &ns->sdev->switch_id, ppid->id_len); + ppid->id_len = sizeof(ns->nsim_dev->nsim_bus_dev->dev.id); + memcpy(&ppid->id, &ns->nsim_dev->nsim_bus_dev->dev.id, ppid->id_len); return 0; } static int nsim_init(struct net_device *dev) { struct netdevsim *ns = netdev_priv(dev); - char sdev_link_name[32]; + char dev_link_name[32]; int err; ns->ddir = debugfs_create_dir(netdev_name(dev), nsim_ddir); if (IS_ERR_OR_NULL(ns->ddir)) return -ENOMEM; - sprintf(sdev_link_name, "../../" DRV_NAME "_sdev/%u", - ns->sdev->switch_id); - debugfs_create_symlink("sdev", ns->ddir, sdev_link_name); + sprintf(dev_link_name, "../../" DRV_NAME "_dev/%u", + ns->nsim_dev->nsim_bus_dev->dev.id); + debugfs_create_symlink("dev", ns->ddir, dev_link_name); err = nsim_bpf_init(ns); if (err) @@ -80,7 +80,6 @@ static void nsim_free(struct net_device *dev) nsim_dev_destroy(ns->nsim_dev); nsim_bus_dev_del(ns->nsim_bus_dev); /* netdev and vf state will be freed out of device_release() */ - nsim_sdev_put(ns->sdev); } static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) @@ -366,31 +365,11 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, struct netlink_ext_ack *extack) { struct netdevsim *ns = netdev_priv(dev); - struct netdevsim *joinns = NULL; int err; - if (tb[IFLA_LINK]) { - struct net_device *joindev; - - joindev = __dev_get_by_index(src_net, - nla_get_u32(tb[IFLA_LINK])); - if (!joindev) - return -ENODEV; - if (joindev->netdev_ops != &nsim_netdev_ops) - return -EINVAL; - - joinns = netdev_priv(joindev); - } - - ns->sdev = nsim_sdev_get(joinns); - if (IS_ERR(ns->sdev)) - return PTR_ERR(ns->sdev); - ns->nsim_bus_dev = nsim_bus_dev_new(~0, 0); - if (IS_ERR(ns->nsim_bus_dev)) { - err = PTR_ERR(ns->nsim_bus_dev); - goto err_sdev_put; - } + if (IS_ERR(ns->nsim_bus_dev)) + return PTR_ERR(ns->nsim_bus_dev); SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); ns->netdev = dev; @@ -410,8 +389,6 @@ err_dev_destroy: nsim_dev_destroy(ns->nsim_dev); err_dev_del: nsim_bus_dev_del(ns->nsim_bus_dev); -err_sdev_put: - nsim_sdev_put(ns->sdev); return err; } @@ -431,13 +408,13 @@ static int __init nsim_module_init(void) if (IS_ERR_OR_NULL(nsim_ddir)) return -ENOMEM; - err = nsim_sdev_init(); + err = nsim_dev_init(); if (err) goto err_debugfs_destroy; err = nsim_bus_init(); if (err) - goto err_sdev_exit; + goto err_dev_exit; err = rtnl_link_register(&nsim_link_ops); if (err) @@ -447,8 +424,8 @@ static int __init nsim_module_init(void) err_bus_exit: nsim_bus_exit(); -err_sdev_exit: - nsim_sdev_exit(); +err_dev_exit: + nsim_dev_exit(); err_debugfs_destroy: debugfs_remove_recursive(nsim_ddir); return err; @@ -458,7 +435,7 @@ static void __exit nsim_module_exit(void) { rtnl_link_unregister(&nsim_link_ops); nsim_bus_exit(); - nsim_sdev_exit(); + nsim_dev_exit(); debugfs_remove_recursive(nsim_ddir); } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index d6b3668f9afd..4ef44a9538db 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -26,37 +26,6 @@ #define NSIM_EA(extack, msg) NL_SET_ERR_MSG_MOD((extack), msg) -struct bpf_prog; -struct bpf_offload_dev; -struct dentry; -struct nsim_vf_config; -struct nsim_fib_data; - -struct netdevsim_shared_dev { - unsigned int refcnt; - u32 switch_id; - - struct dentry *ddir; - - struct bpf_offload_dev *bpf_dev; - - bool bpf_bind_accept; - u32 bpf_bind_verifier_delay; - - struct dentry *ddir_bpf_bound_progs; - u32 prog_id_gen; - - struct list_head bpf_bound_progs; - struct list_head bpf_bound_maps; -}; - -struct netdevsim; - -struct netdevsim_shared_dev *nsim_sdev_get(struct netdevsim *joinns); -void nsim_sdev_put(struct netdevsim_shared_dev *sdev); -int nsim_sdev_init(void); -void nsim_sdev_exit(void); - #define NSIM_IPSEC_MAX_SA_COUNT 33 #define NSIM_IPSEC_VALID BIT(31) @@ -87,7 +56,6 @@ struct netdevsim { struct u64_stats_sync syncp; struct nsim_bus_dev *nsim_bus_dev; - struct netdevsim_shared_dev *sdev; struct dentry *ddir; @@ -107,6 +75,8 @@ struct netdevsim { }; #ifdef CONFIG_BPF_SYSCALL +int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); +void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); int nsim_bpf_init(struct netdevsim *ns); void nsim_bpf_uninit(struct netdevsim *ns); int nsim_bpf(struct net_device *dev, struct netdev_bpf *bpf); @@ -114,6 +84,15 @@ int nsim_bpf_disable_tc(struct netdevsim *ns); int nsim_bpf_setup_tc_block_cb(enum tc_setup_type type, void *type_data, void *cb_priv); #else + +static inline int nsim_bpf_dev_init(struct nsim_dev *nsim_dev) +{ + return 0; +} + +static inline void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) +{ +} static inline int nsim_bpf_init(struct netdevsim *ns) { return 0; @@ -152,13 +131,24 @@ enum nsim_resource_id { }; struct nsim_dev { + struct nsim_bus_dev *nsim_bus_dev; struct nsim_fib_data *fib_data; + struct dentry *ddir; + struct bpf_offload_dev *bpf_dev; + bool bpf_bind_accept; + u32 bpf_bind_verifier_delay; + struct dentry *ddir_bpf_bound_progs; + u32 prog_id_gen; + struct list_head bpf_bound_progs; + struct list_head bpf_bound_maps; }; struct nsim_dev * nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, struct netdevsim *ns); void nsim_dev_destroy(struct nsim_dev *nsim_dev); +int nsim_dev_init(void); +void nsim_dev_exit(void); struct nsim_fib_data *nsim_fib_create(void); void nsim_fib_destroy(struct nsim_fib_data *fib_data); diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index a7f95106119f..91dfe876a707 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py @@ -335,7 +335,7 @@ class NetdevSim: self.ns = "" self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname']) - self.sdev_dir = self.dfs_dir + '/sdev/' + self.dev_dir = self.dfs_dir + '/dev/' self.dfs_refresh() def __getitem__(self, key): @@ -368,12 +368,12 @@ class NetdevSim: return data.strip() def dfs_num_bound_progs(self): - path = os.path.join(self.sdev_dir, "bpf_bound_progs") + path = os.path.join(self.dev_dir, "bpf_bound_progs") _, progs = cmd('ls %s' % (path)) return len(progs.split()) def dfs_get_bound_progs(self, expected): - progs = DebugfsDir(os.path.join(self.sdev_dir, "bpf_bound_progs")) + progs = DebugfsDir(os.path.join(self.dev_dir, "bpf_bound_progs")) if expected is not None: if len(progs) != expected: fail(True, "%d BPF programs bound, expected %d" % @@ -1055,7 +1055,7 @@ try: start_test("Test if netdev removal waits for translation...") delay_msec = 500 - sim.dfs["sdev/bpf_bind_verifier_delay"] = delay_msec + sim.dfs["dev/bpf_bind_verifier_delay"] = delay_msec start = time.time() cmd_line = "tc filter add dev %s ingress bpf %s da skip_sw" % \ (sim['ifname'], obj) -- 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 +++ drivers/net/netdevsim/netdev.c | 3 +-- drivers/net/netdevsim/netdevsim.h | 1 + 3 files changed, 5 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 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)) { diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index c5f4bbb9716f..9b4310e20129 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -32,8 +32,7 @@ static int nsim_get_port_parent_id(struct net_device *dev, { struct netdevsim *ns = netdev_priv(dev); - ppid->id_len = sizeof(ns->nsim_dev->nsim_bus_dev->dev.id); - memcpy(&ppid->id, &ns->nsim_dev->nsim_bus_dev->dev.id, ppid->id_len); + memcpy(ppid, &ns->nsim_dev->switch_id, sizeof(*ppid)); return 0; } diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 4ef44a9538db..17639c7c9032 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -141,6 +141,7 @@ struct nsim_dev { u32 prog_id_gen; struct list_head bpf_bound_progs; struct list_head bpf_bound_maps; + struct netdev_phys_item_id switch_id; }; struct nsim_dev * -- 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 +++++++--- drivers/net/netdevsim/netdev.c | 15 +++------------ drivers/net/netdevsim/netdevsim.h | 1 + tools/testing/selftests/bpf/test_offload.py | 4 +++- tools/testing/selftests/net/rtnetlink.sh | 2 +- 5 files changed, 15 insertions(+), 17 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; diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 9b4310e20129..eb823bd0dc39 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -25,8 +25,6 @@ #include "netdevsim.h" -static struct dentry *nsim_ddir; - static int nsim_get_port_parent_id(struct net_device *dev, struct netdev_phys_item_id *ppid) { @@ -42,11 +40,11 @@ static int nsim_init(struct net_device *dev) char dev_link_name[32]; int err; - ns->ddir = debugfs_create_dir(netdev_name(dev), nsim_ddir); + ns->ddir = debugfs_create_dir("0", ns->nsim_dev->ports_ddir); if (IS_ERR_OR_NULL(ns->ddir)) return -ENOMEM; - sprintf(dev_link_name, "../../" DRV_NAME "_dev/%u", + sprintf(dev_link_name, "../../../" DRV_NAME "%u", ns->nsim_dev->nsim_bus_dev->dev.id); debugfs_create_symlink("dev", ns->ddir, dev_link_name); @@ -403,13 +401,9 @@ static int __init nsim_module_init(void) { int err; - nsim_ddir = debugfs_create_dir(DRV_NAME, NULL); - if (IS_ERR_OR_NULL(nsim_ddir)) - return -ENOMEM; - err = nsim_dev_init(); if (err) - goto err_debugfs_destroy; + return err; err = nsim_bus_init(); if (err) @@ -425,8 +419,6 @@ err_bus_exit: nsim_bus_exit(); err_dev_exit: nsim_dev_exit(); -err_debugfs_destroy: - debugfs_remove_recursive(nsim_ddir); return err; } @@ -435,7 +427,6 @@ static void __exit nsim_module_exit(void) rtnl_link_unregister(&nsim_link_ops); nsim_bus_exit(); nsim_dev_exit(); - debugfs_remove_recursive(nsim_ddir); } module_init(nsim_module_init); diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 17639c7c9032..e951b1ccc3f2 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -134,6 +134,7 @@ struct nsim_dev { struct nsim_bus_dev *nsim_bus_dev; struct nsim_fib_data *fib_data; struct dentry *ddir; + struct dentry *ports_ddir; struct bpf_offload_dev *bpf_dev; bool bpf_bind_accept; u32 bpf_bind_verifier_delay; diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index 91dfe876a707..5f2e4f9e70e4 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py @@ -306,6 +306,8 @@ class DebugfsDir: _, out = cmd('ls ' + path) for f in out.split(): + if f == "ports": + continue p = os.path.join(path, f) if os.path.isfile(p): _, out = cmd('cat %s/%s' % (path, f)) @@ -334,7 +336,7 @@ class NetdevSim: self.ns = "" - self.dfs_dir = '/sys/kernel/debug/netdevsim/%s' % (self.dev['ifname']) + self.dfs_dir = '/sys/kernel/debug/netdevsim/netdevsim0/ports/0/' self.dev_dir = self.dfs_dir + '/dev/' self.dfs_refresh() diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh index b447803f3f8a..311f82bcbe8d 100755 --- a/tools/testing/selftests/net/rtnetlink.sh +++ b/tools/testing/selftests/net/rtnetlink.sh @@ -697,7 +697,7 @@ kci_test_ipsec_offload() srcip=192.168.123.3 dstip=192.168.123.4 dev=simx1 - sysfsd=/sys/kernel/debug/netdevsim/$dev + sysfsd=/sys/kernel/debug/netdevsim/netdevsim0/ports/0/ sysfsf=$sysfsd/ipsec # setup netdevsim since dummydev doesn't have offload support -- 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/bus.c | 29 +++++++++ drivers/net/netdevsim/dev.c | 130 +++++++++++++++++++++++++++++++++----- drivers/net/netdevsim/netdev.c | 15 ++--- drivers/net/netdevsim/netdevsim.h | 16 +++-- 4 files changed, 160 insertions(+), 30 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index c30692f17374..1ee14e1bb12d 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -194,6 +194,21 @@ static struct attribute *nsim_bus_attrs[] = { }; ATTRIBUTE_GROUPS(nsim_bus); +static int nsim_bus_probe(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + return nsim_dev_probe(nsim_bus_dev); +} + +static int nsim_bus_remove(struct device *dev) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + + nsim_dev_remove(nsim_bus_dev); + return 0; +} + int nsim_num_vf(struct device *dev) { struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); @@ -205,6 +220,8 @@ static struct bus_type nsim_bus = { .name = DRV_NAME, .dev_name = DRV_NAME, .bus_groups = nsim_bus_groups, + .probe = nsim_bus_probe, + .remove = nsim_bus_remove, .num_vf = nsim_num_vf, }; @@ -238,6 +255,18 @@ err_nsim_bus_dev_free: return ERR_PTR(err); } +struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns) +{ + struct nsim_bus_dev *nsim_bus_dev; + + dev_hold(ns->netdev); + rtnl_unlock(); + nsim_bus_dev = nsim_bus_dev_new(~0, 0); + rtnl_lock(); + dev_put(ns->netdev); + return nsim_bus_dev; +} + void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) { device_unregister(&nsim_bus_dev->dev); 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); diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index eb823bd0dc39..99169fe521f2 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -74,7 +74,6 @@ static void nsim_free(struct net_device *dev) { struct netdevsim *ns = netdev_priv(dev); - nsim_dev_destroy(ns->nsim_dev); nsim_bus_dev_del(ns->nsim_bus_dev); /* netdev and vf state will be freed out of device_release() */ } @@ -364,26 +363,20 @@ static int nsim_newlink(struct net *src_net, struct net_device *dev, struct netdevsim *ns = netdev_priv(dev); int err; - ns->nsim_bus_dev = nsim_bus_dev_new(~0, 0); + ns->netdev = dev; + ns->nsim_bus_dev = nsim_bus_dev_new_with_ns(ns); if (IS_ERR(ns->nsim_bus_dev)) return PTR_ERR(ns->nsim_bus_dev); SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); - ns->netdev = dev; - ns->nsim_dev = nsim_dev_create_with_ns(ns->nsim_bus_dev, ns); - if (IS_ERR(ns->nsim_dev)) { - err = PTR_ERR(ns->nsim_dev); - goto err_dev_del; - } + ns->nsim_dev = dev_get_drvdata(&ns->nsim_bus_dev->dev); err = register_netdevice(dev); if (err) - goto err_dev_destroy; + goto err_dev_del; return 0; -err_dev_destroy: - nsim_dev_destroy(ns->nsim_dev); err_dev_del: nsim_bus_dev_del(ns->nsim_bus_dev); return err; diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index e951b1ccc3f2..0e6ca85e5487 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #define DRV_NAME "netdevsim" @@ -130,6 +131,13 @@ enum nsim_resource_id { NSIM_RESOURCE_IPV6_FIB_RULES, }; +struct nsim_dev_port { + struct list_head list; + struct devlink_port devlink_port; + unsigned int port_index; + struct dentry *ddir; +}; + struct nsim_dev { struct nsim_bus_dev *nsim_bus_dev; struct nsim_fib_data *fib_data; @@ -143,14 +151,13 @@ struct nsim_dev { struct list_head bpf_bound_progs; struct list_head bpf_bound_maps; struct netdev_phys_item_id switch_id; + struct list_head port_list; }; -struct nsim_dev * -nsim_dev_create_with_ns(struct nsim_bus_dev *nsim_bus_dev, - struct netdevsim *ns); -void nsim_dev_destroy(struct nsim_dev *nsim_dev); int nsim_dev_init(void); void nsim_dev_exit(void); +int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); +void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); struct nsim_fib_data *nsim_fib_create(void); void nsim_fib_destroy(struct nsim_fib_data *fib_data); @@ -201,6 +208,7 @@ struct nsim_bus_dev { }; struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count); +struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns); void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); int nsim_bus_init(void); void nsim_bus_exit(void); -- 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/bus.c | 36 +++++++++++++++++++++++++ drivers/net/netdevsim/dev.c | 55 ++++++++++++++++++++++++++++++++++++--- drivers/net/netdevsim/netdevsim.h | 5 ++++ 3 files changed, 92 insertions(+), 4 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index 1ee14e1bb12d..549c399f29da 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -91,8 +91,44 @@ static struct device_attribute nsim_bus_dev_numvfs_attr = __ATTR(sriov_numvfs, 0664, nsim_bus_dev_numvfs_show, nsim_bus_dev_numvfs_store); +static ssize_t +new_port_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + unsigned int port_index; + int ret; + + ret = kstrtouint(buf, 0, &port_index); + if (ret) + return ret; + ret = nsim_dev_port_add(nsim_bus_dev, port_index); + return ret ? ret : count; +} + +static struct device_attribute nsim_bus_dev_new_port_attr = __ATTR_WO(new_port); + +static ssize_t +del_port_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct nsim_bus_dev *nsim_bus_dev = to_nsim_bus_dev(dev); + unsigned int port_index; + int ret; + + ret = kstrtouint(buf, 0, &port_index); + if (ret) + return ret; + ret = nsim_dev_port_del(nsim_bus_dev, port_index); + return ret ? ret : count; +} + +static struct device_attribute nsim_bus_dev_del_port_attr = __ATTR_WO(del_port); + static struct attribute *nsim_bus_dev_attrs[] = { &nsim_bus_dev_numvfs_attr.attr, + &nsim_bus_dev_new_port_attr.attr, + &nsim_bus_dev_del_port_attr.attr, NULL, }; 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); diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 0e6ca85e5487..6b60589cab91 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -152,12 +152,17 @@ struct nsim_dev { struct list_head bpf_bound_maps; struct netdev_phys_item_id switch_id; struct list_head port_list; + struct mutex port_list_lock; /* protects port list */ }; int nsim_dev_init(void); void nsim_dev_exit(void); int nsim_dev_probe(struct nsim_bus_dev *nsim_bus_dev); void nsim_dev_remove(struct nsim_bus_dev *nsim_bus_dev); +int nsim_dev_port_add(struct nsim_bus_dev *nsim_bus_dev, + unsigned int port_index); +int nsim_dev_port_del(struct nsim_bus_dev *nsim_bus_dev, + unsigned int port_index); struct nsim_fib_data *nsim_fib_create(void); void nsim_fib_destroy(struct nsim_fib_data *fib_data); -- 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/bpf.c | 13 +- drivers/net/netdevsim/bus.c | 25 ++-- drivers/net/netdevsim/dev.c | 13 +- drivers/net/netdevsim/ipsec.c | 3 +- drivers/net/netdevsim/netdev.c | 138 ++++++----------- drivers/net/netdevsim/netdevsim.h | 11 +- tools/testing/selftests/bpf/test_offload.py | 223 ++++++++++++++++++---------- tools/testing/selftests/net/rtnetlink.sh | 9 +- 8 files changed, 238 insertions(+), 197 deletions(-) (limited to 'drivers/net/netdevsim/dev.c') diff --git a/drivers/net/netdevsim/bpf.c b/drivers/net/netdevsim/bpf.c index 89980b223adc..2b74425822ab 100644 --- a/drivers/net/netdevsim/bpf.c +++ b/drivers/net/netdevsim/bpf.c @@ -612,6 +612,7 @@ void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev) int nsim_bpf_init(struct netdevsim *ns) { + struct dentry *ddir = ns->nsim_dev_port->ddir; int err; err = bpf_offload_dev_netdev_register(ns->nsim_dev->bpf_dev, @@ -619,23 +620,23 @@ int nsim_bpf_init(struct netdevsim *ns) if (err) return err; - debugfs_create_u32("bpf_offloaded_id", 0400, ns->ddir, + debugfs_create_u32("bpf_offloaded_id", 0400, ddir, &ns->bpf_offloaded_id); ns->bpf_tc_accept = true; - debugfs_create_bool("bpf_tc_accept", 0600, ns->ddir, + debugfs_create_bool("bpf_tc_accept", 0600, ddir, &ns->bpf_tc_accept); - debugfs_create_bool("bpf_tc_non_bound_accept", 0600, ns->ddir, + debugfs_create_bool("bpf_tc_non_bound_accept", 0600, ddir, &ns->bpf_tc_non_bound_accept); ns->bpf_xdpdrv_accept = true; - debugfs_create_bool("bpf_xdpdrv_accept", 0600, ns->ddir, + debugfs_create_bool("bpf_xdpdrv_accept", 0600, ddir, &ns->bpf_xdpdrv_accept); ns->bpf_xdpoffload_accept = true; - debugfs_create_bool("bpf_xdpoffload_accept", 0600, ns->ddir, + debugfs_create_bool("bpf_xdpoffload_accept", 0600, ddir, &ns->bpf_xdpoffload_accept); ns->bpf_map_accept = true; - debugfs_create_bool("bpf_map_accept", 0600, ns->ddir, + debugfs_create_bool("bpf_map_accept", 0600, ddir, &ns->bpf_map_accept); return 0; diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index 549c399f29da..ae482347b67b 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -153,6 +153,9 @@ static struct device_type nsim_bus_dev_type = { .release = nsim_bus_dev_release, }; +static struct nsim_bus_dev * +nsim_bus_dev_new(unsigned int id, unsigned int port_count); + static ssize_t new_device_store(struct bus_type *bus, const char *buf, size_t count) { @@ -188,6 +191,8 @@ new_device_store(struct bus_type *bus, const char *buf, size_t count) } static BUS_ATTR_WO(new_device); +static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); + static ssize_t del_device_store(struct bus_type *bus, const char *buf, size_t count) { @@ -261,7 +266,8 @@ static struct bus_type nsim_bus = { .num_vf = nsim_num_vf, }; -struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count) +static struct nsim_bus_dev * +nsim_bus_dev_new(unsigned int id, unsigned int port_count) { struct nsim_bus_dev *nsim_bus_dev; int err; @@ -270,8 +276,7 @@ struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count) if (!nsim_bus_dev) return ERR_PTR(-ENOMEM); - err = ida_alloc_range(&nsim_bus_dev_ids, - id == ~0 ? 0 : id, id, GFP_KERNEL); + err = ida_alloc_range(&nsim_bus_dev_ids, id, id, GFP_KERNEL); if (err < 0) goto err_nsim_bus_dev_free; nsim_bus_dev->dev.id = err; @@ -291,19 +296,7 @@ err_nsim_bus_dev_free: return ERR_PTR(err); } -struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns) -{ - struct nsim_bus_dev *nsim_bus_dev; - - dev_hold(ns->netdev); - rtnl_unlock(); - nsim_bus_dev = nsim_bus_dev_new(~0, 0); - rtnl_lock(); - dev_put(ns->netdev); - return nsim_bus_dev; -} - -void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) +static void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev) { device_unregister(&nsim_bus_dev->dev); ida_free(&nsim_bus_dev_ids, nsim_bus_dev->dev.id); 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); diff --git a/drivers/net/netdevsim/ipsec.c b/drivers/net/netdevsim/ipsec.c index 76e11d889bb6..e27fc1a4516d 100644 --- a/drivers/net/netdevsim/ipsec.c +++ b/drivers/net/netdevsim/ipsec.c @@ -283,7 +283,8 @@ void nsim_ipsec_init(struct netdevsim *ns) ns->netdev->features |= NSIM_ESP_FEATURES; ns->netdev->hw_enc_features |= NSIM_ESP_FEATURES; - ns->ipsec.pfile = debugfs_create_file("ipsec", 0400, ns->ddir, ns, + ns->ipsec.pfile = debugfs_create_file("ipsec", 0400, + ns->nsim_dev_port->ddir, ns, &ipsec_dbg_fops); } diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 99169fe521f2..040c390d0c01 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -25,59 +25,6 @@ #include "netdevsim.h" -static int nsim_get_port_parent_id(struct net_device *dev, - struct netdev_phys_item_id *ppid) -{ - struct netdevsim *ns = netdev_priv(dev); - - memcpy(ppid, &ns->nsim_dev->switch_id, sizeof(*ppid)); - return 0; -} - -static int nsim_init(struct net_device *dev) -{ - struct netdevsim *ns = netdev_priv(dev); - char dev_link_name[32]; - int err; - - ns->ddir = debugfs_create_dir("0", ns->nsim_dev->ports_ddir); - if (IS_ERR_OR_NULL(ns->ddir)) - return -ENOMEM; - - sprintf(dev_link_name, "../../../" DRV_NAME "%u", - ns->nsim_dev->nsim_bus_dev->dev.id); - debugfs_create_symlink("dev", ns->ddir, dev_link_name); - - err = nsim_bpf_init(ns); - if (err) - goto err_debugfs_destroy; - - nsim_ipsec_init(ns); - - return 0; - -err_debugfs_destroy: - debugfs_remove_recursive(ns->ddir); - return err; -} - -static void nsim_uninit(struct net_device *dev) -{ - struct netdevsim *ns = netdev_priv(dev); - - nsim_ipsec_teardown(ns); - debugfs_remove_recursive(ns->ddir); - nsim_bpf_uninit(ns); -} - -static void nsim_free(struct net_device *dev) -{ - struct netdevsim *ns = netdev_priv(dev); - - nsim_bus_dev_del(ns->nsim_bus_dev); - /* netdev and vf state will be freed out of device_release() */ -} - static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct netdevsim *ns = netdev_priv(dev); @@ -299,8 +246,6 @@ nsim_set_features(struct net_device *dev, netdev_features_t features) } static const struct net_device_ops nsim_netdev_ops = { - .ndo_init = nsim_init, - .ndo_uninit = nsim_uninit, .ndo_start_xmit = nsim_start_xmit, .ndo_set_rx_mode = nsim_set_rx_mode, .ndo_set_mac_address = eth_mac_addr, @@ -318,7 +263,6 @@ static const struct net_device_ops nsim_netdev_ops = { .ndo_setup_tc = nsim_setup_tc, .ndo_set_features = nsim_set_features, .ndo_bpf = nsim_bpf, - .ndo_get_port_parent_id = nsim_get_port_parent_id, }; static void nsim_setup(struct net_device *dev) @@ -326,10 +270,6 @@ static void nsim_setup(struct net_device *dev) ether_setup(dev); eth_hw_addr_random(dev); - dev->netdev_ops = &nsim_netdev_ops; - dev->needs_free_netdev = true; - dev->priv_destructor = nsim_free; - dev->tx_queue_len = 0; dev->flags |= IFF_NOARP; dev->flags &= ~IFF_MULTICAST; @@ -344,50 +284,70 @@ static void nsim_setup(struct net_device *dev) dev->max_mtu = ETH_MAX_MTU; } -static int nsim_validate(struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) -{ - if (tb[IFLA_ADDRESS]) { - if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) - return -EINVAL; - if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) - return -EADDRNOTAVAIL; - } - return 0; -} - -static int nsim_newlink(struct net *src_net, struct net_device *dev, - struct nlattr *tb[], struct nlattr *data[], - struct netlink_ext_ack *extack) +struct netdevsim * +nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) { - struct netdevsim *ns = netdev_priv(dev); + struct net_device *dev; + struct netdevsim *ns; int err; - ns->netdev = dev; - ns->nsim_bus_dev = nsim_bus_dev_new_with_ns(ns); - if (IS_ERR(ns->nsim_bus_dev)) - return PTR_ERR(ns->nsim_bus_dev); + dev = alloc_netdev(sizeof(*ns), "eth%d", NET_NAME_UNKNOWN, nsim_setup); + if (!dev) + return ERR_PTR(-ENOMEM); + ns = netdev_priv(dev); + ns->netdev = dev; + ns->nsim_dev = nsim_dev; + ns->nsim_dev_port = nsim_dev_port; + ns->nsim_bus_dev = nsim_dev->nsim_bus_dev; SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); + dev->netdev_ops = &nsim_netdev_ops; - ns->nsim_dev = dev_get_drvdata(&ns->nsim_bus_dev->dev); + rtnl_lock(); + err = nsim_bpf_init(ns); + if (err) + goto err_free_netdev; + + nsim_ipsec_init(ns); err = register_netdevice(dev); if (err) - goto err_dev_del; - return 0; + goto err_ipsec_teardown; + rtnl_unlock(); -err_dev_del: - nsim_bus_dev_del(ns->nsim_bus_dev); - return err; + return ns; + +err_ipsec_teardown: + nsim_ipsec_teardown(ns); + nsim_bpf_uninit(ns); + rtnl_unlock(); +err_free_netdev: + free_netdev(dev); + return ERR_PTR(err); +} + +void nsim_destroy(struct netdevsim *ns) +{ + struct net_device *dev = ns->netdev; + + rtnl_lock(); + unregister_netdevice(dev); + nsim_ipsec_teardown(ns); + nsim_bpf_uninit(ns); + rtnl_unlock(); + free_netdev(dev); +} + +static int nsim_validate(struct nlattr *tb[], struct nlattr *data[], + struct netlink_ext_ack *extack) +{ + NL_SET_ERR_MSG_MOD(extack, "Please use: echo \"[ID] [PORT_COUNT]\" > /sys/bus/netdevsim/new_device"); + return -EOPNOTSUPP; } static struct rtnl_link_ops nsim_link_ops __read_mostly = { .kind = DRV_NAME, - .priv_size = sizeof(struct netdevsim), - .setup = nsim_setup, .validate = nsim_validate, - .newlink = nsim_newlink, }; static int __init nsim_module_init(void) diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 6b60589cab91..3f398797c2bc 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -51,6 +51,7 @@ struct nsim_ipsec { struct netdevsim { struct net_device *netdev; struct nsim_dev *nsim_dev; + struct nsim_dev_port *nsim_dev_port; u64 tx_packets; u64 tx_bytes; @@ -58,8 +59,6 @@ struct netdevsim { struct nsim_bus_dev *nsim_bus_dev; - struct dentry *ddir; - struct bpf_prog *bpf_offloaded; u32 bpf_offloaded_id; @@ -75,6 +74,10 @@ struct netdevsim { struct nsim_ipsec ipsec; }; +struct netdevsim * +nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port); +void nsim_destroy(struct netdevsim *ns); + #ifdef CONFIG_BPF_SYSCALL int nsim_bpf_dev_init(struct nsim_dev *nsim_dev); void nsim_bpf_dev_exit(struct nsim_dev *nsim_dev); @@ -136,6 +139,7 @@ struct nsim_dev_port { struct devlink_port devlink_port; unsigned int port_index; struct dentry *ddir; + struct netdevsim *ns; }; struct nsim_dev { @@ -212,8 +216,5 @@ struct nsim_bus_dev { struct nsim_vf_config *vfconfigs; }; -struct nsim_bus_dev *nsim_bus_dev_new(unsigned int id, unsigned int port_count); -struct nsim_bus_dev *nsim_bus_dev_new_with_ns(struct netdevsim *ns); -void nsim_bus_dev_del(struct nsim_bus_dev *nsim_bus_dev); int nsim_bus_init(void); void nsim_bus_exit(void); diff --git a/tools/testing/selftests/bpf/test_offload.py b/tools/testing/selftests/bpf/test_offload.py index 5f2e4f9e70e4..425f9ed27c3b 100755 --- a/tools/testing/selftests/bpf/test_offload.py +++ b/tools/testing/selftests/bpf/test_offload.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 # Copyright (C) 2017 Netronome Systems, Inc. +# 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 @@ -15,10 +16,12 @@ from datetime import datetime import argparse +import errno import json import os import pprint import random +import re import string import struct import subprocess @@ -323,42 +326,112 @@ class DebugfsDir: return dfs -class NetdevSim: +class NetdevSimDev: """ - Class for netdevsim netdevice and its attributes. + Class for netdevsim bus device and its attributes. """ - def __init__(self, link=None): - self.link = link + def __init__(self, port_count=1): + addr = 0 + while True: + try: + with open("/sys/bus/netdevsim/new_device", "w") as f: + f.write("%u %u" % (addr, port_count)) + except OSError as e: + if e.errno == errno.ENOSPC: + addr += 1 + continue + raise e + break + self.addr = addr + + # As probe of netdevsim device might happen from a workqueue, + # so wait here until all netdevs appear. + self.wait_for_netdevs(port_count) + + ret, out = cmd("udevadm settle", fail=False) + if ret: + raise Exception("udevadm settle failed") + ifnames = self.get_ifnames() - self.dev = self._netdevsim_create() devs.append(self) + self.dfs_dir = "/sys/kernel/debug/netdevsim/netdevsim%u/" % addr + + self.nsims = [] + for port_index in range(port_count): + self.nsims.append(NetdevSim(self, port_index, ifnames[port_index])) + + def get_ifnames(self): + ifnames = [] + listdir = os.listdir("/sys/bus/netdevsim/devices/netdevsim%u/net/" % self.addr) + for ifname in listdir: + ifnames.append(ifname) + ifnames.sort() + return ifnames + + def wait_for_netdevs(self, port_count): + timeout = 5 + timeout_start = time.time() + + while True: + try: + ifnames = self.get_ifnames() + except FileNotFoundError as e: + ifnames = [] + if len(ifnames) == port_count: + break + if time.time() < timeout_start + timeout: + continue + raise Exception("netdevices did not appear within timeout") - self.ns = "" + def dfs_num_bound_progs(self): + path = os.path.join(self.dfs_dir, "bpf_bound_progs") + _, progs = cmd('ls %s' % (path)) + return len(progs.split()) - self.dfs_dir = '/sys/kernel/debug/netdevsim/netdevsim0/ports/0/' - self.dev_dir = self.dfs_dir + '/dev/' - self.dfs_refresh() + def dfs_get_bound_progs(self, expected): + progs = DebugfsDir(os.path.join(self.dfs_dir, "bpf_bound_progs")) + if expected is not None: + if len(progs) != expected: + fail(True, "%d BPF programs bound, expected %d" % + (len(progs), expected)) + return progs - def __getitem__(self, key): - return self.dev[key] + def remove(self): + with open("/sys/bus/netdevsim/del_device", "w") as f: + f.write("%u" % self.addr) + devs.remove(self) + + def remove_nsim(self, nsim): + self.nsims.remove(nsim) + with open("/sys/bus/netdevsim/devices/netdevsim%u/del_port" % self.addr ,"w") as f: + f.write("%u" % nsim.port_index) + +class NetdevSim: + """ + Class for netdevsim netdevice and its attributes. + """ - def _netdevsim_create(self): - link = "" if self.link is None else "link " + self.link.dev['ifname'] - _, old = ip("link show") - ip("link add sim%d {link} type netdevsim".format(link=link)) - _, new = ip("link show") + def __init__(self, nsimdev, port_index, ifname): + # In case udev renamed the netdev to according to new schema, + # check if the name matches the port_index. + nsimnamere = re.compile("eni\d+np(\d+)") + match = nsimnamere.match(ifname) + if match and int(match.groups()[0]) != port_index + 1: + raise Exception("netdevice name mismatches the expected one") - for dev in new: - f = filter(lambda x: x["ifname"] == dev["ifname"], old) - if len(list(f)) == 0: - return dev + self.nsimdev = nsimdev + self.port_index = port_index + self.ns = "" + self.dfs_dir = "%s/ports/%u/" % (nsimdev.dfs_dir, port_index) + self.dfs_refresh() + _, [self.dev] = ip("link show dev %s" % ifname) - raise Exception("failed to create netdevsim device") + def __getitem__(self, key): + return self.dev[key] def remove(self): - devs.remove(self) - ip("link del dev %s" % (self.dev["ifname"]), ns=self.ns) + self.nsimdev.remove_nsim(self) def dfs_refresh(self): self.dfs = DebugfsDir(self.dfs_dir) @@ -369,22 +442,9 @@ class NetdevSim: _, data = cmd('cat %s' % (path)) return data.strip() - def dfs_num_bound_progs(self): - path = os.path.join(self.dev_dir, "bpf_bound_progs") - _, progs = cmd('ls %s' % (path)) - return len(progs.split()) - - def dfs_get_bound_progs(self, expected): - progs = DebugfsDir(os.path.join(self.dev_dir, "bpf_bound_progs")) - if expected is not None: - if len(progs) != expected: - fail(True, "%d BPF programs bound, expected %d" % - (len(progs), expected)) - return progs - def wait_for_flush(self, bound=0, total=0, n_retry=20): for i in range(n_retry): - nbound = self.dfs_num_bound_progs() + nbound = self.nsimdev.dfs_num_bound_progs() nprogs = len(bpftool_prog_list()) if nbound == bound and nprogs == total: return @@ -614,7 +674,7 @@ def test_spurios_extack(sim, obj, skip_hw, needle): include_stderr=True) check_no_extack(res, needle) -def test_multi_prog(sim, obj, modename, modeid): +def test_multi_prog(simdev, sim, obj, modename, modeid): start_test("Test multi-attachment XDP - %s + offload..." % (modename or "default", )) sim.set_xdp(obj, "offload") @@ -670,11 +730,12 @@ def test_multi_prog(sim, obj, modename, modeid): check_multi_basic(two_xdps) start_test("Test multi-attachment XDP - device remove...") - sim.remove() + simdev.remove() - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.set_ethtool_tc_offloads(True) - return sim + return [simdev, sim] # Parse command line parser = argparse.ArgumentParser() @@ -731,12 +792,14 @@ try: bytecode = bpf_bytecode("1,6 0 0 4294967295,") start_test("Test destruction of generic XDP...") - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.set_xdp(obj, "generic") - sim.remove() + simdev.remove() bpftool_prog_list_wait(expected=0) - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.tc_add_ingress() start_test("Test TC non-offloaded...") @@ -746,7 +809,7 @@ try: start_test("Test TC non-offloaded isn't getting bound...") ret, _ = sim.cls_bpf_add_filter(obj, fail=False) fail(ret != 0, "Software TC filter did not load") - sim.dfs_get_bound_progs(expected=0) + simdev.dfs_get_bound_progs(expected=0) sim.tc_flush_filters() @@ -763,7 +826,7 @@ try: start_test("Test TC offload by default...") ret, _ = sim.cls_bpf_add_filter(obj, fail=False) fail(ret != 0, "Software TC filter did not load") - sim.dfs_get_bound_progs(expected=0) + simdev.dfs_get_bound_progs(expected=0) ingress = sim.tc_show_ingress(expected=1) fltr = ingress[0] fail(not fltr["in_hw"], "Filter not offloaded by default") @@ -773,7 +836,7 @@ try: start_test("Test TC cBPF bytcode tries offload by default...") ret, _ = sim.cls_bpf_add_filter(bytecode, fail=False) fail(ret != 0, "Software TC filter did not load") - sim.dfs_get_bound_progs(expected=0) + simdev.dfs_get_bound_progs(expected=0) ingress = sim.tc_show_ingress(expected=1) fltr = ingress[0] fail(not fltr["in_hw"], "Bytecode not offloaded by default") @@ -841,7 +904,7 @@ try: check_verifier_log(err, "[netdevsim] Hello from netdevsim!") start_test("Test TC offload basics...") - dfs = sim.dfs_get_bound_progs(expected=1) + dfs = simdev.dfs_get_bound_progs(expected=1) progs = bpftool_prog_list(expected=1) ingress = sim.tc_show_ingress(expected=1) @@ -876,18 +939,20 @@ try: start_test("Test destroying device gets rid of TC filters...") sim.cls_bpf_add_filter(obj, skip_sw=True) - sim.remove() + simdev.remove() bpftool_prog_list_wait(expected=0) - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.set_ethtool_tc_offloads(True) start_test("Test destroying device gets rid of XDP...") sim.set_xdp(obj, "offload") - sim.remove() + simdev.remove() bpftool_prog_list_wait(expected=0) - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.set_ethtool_tc_offloads(True) start_test("Test XDP prog reporting...") @@ -973,7 +1038,7 @@ try: check_verifier_log(err, "[netdevsim] Hello from netdevsim!") start_test("Test XDP offload is device bound...") - dfs = sim.dfs_get_bound_progs(expected=1) + dfs = simdev.dfs_get_bound_progs(expected=1) dprog = dfs[0] fail(prog["id"] != link_xdp["id"], "Program IDs don't match") @@ -992,7 +1057,8 @@ try: bpftool_prog_list_wait(expected=0) start_test("Test attempt to use a program for a wrong device...") - sim2 = NetdevSim() + simdev2 = NetdevSimDev() + sim2, = simdev2.nsims sim2.set_xdp(obj, "offload") pin_file, pinned = pin_prog("/sys/fs/bpf/tmp") @@ -1000,7 +1066,7 @@ try: fail=False, include_stderr=True) fail(ret == 0, "Pinned program loaded for a different device accepted") check_extack_nsim(err, "program bound to different dev.", args) - sim2.remove() + simdev2.remove() ret, _, err = sim.set_xdp(pinned, "offload", fail=False, include_stderr=True) fail(ret == 0, "Pinned program loaded for a removed device accepted") @@ -1008,9 +1074,9 @@ try: rm(pin_file) bpftool_prog_list_wait(expected=0) - sim = test_multi_prog(sim, obj, "", 1) - sim = test_multi_prog(sim, obj, "drv", 1) - sim = test_multi_prog(sim, obj, "generic", 2) + simdev, sim = test_multi_prog(simdev, sim, obj, "", 1) + simdev, sim = test_multi_prog(simdev, sim, obj, "drv", 1) + simdev, sim = test_multi_prog(simdev, sim, obj, "generic", 2) start_test("Test mixing of TC and XDP...") sim.tc_add_ingress() @@ -1063,9 +1129,9 @@ try: (sim['ifname'], obj) tc_proc = cmd(cmd_line, background=True, fail=False) # Wait for the verifier to start - while sim.dfs_num_bound_progs() <= 2: + while simdev.dfs_num_bound_progs() <= 2: pass - sim.remove() + simdev.remove() end = time.time() ret, _ = cmd_result(tc_proc, fail=False) time_diff = end - start @@ -1080,7 +1146,8 @@ try: clean_up() bpftool_prog_list_wait(expected=0) - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims map_obj = bpf_obj("sample_map_ret0.o") start_test("Test loading program with maps...") sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON @@ -1102,7 +1169,7 @@ try: prog_file, _ = pin_prog("/sys/fs/bpf/tmp_prog") map_file, _ = pin_map("/sys/fs/bpf/tmp_map", idx=1, expected=2) - sim.remove() + simdev.remove() start_test("Test bpftool bound info reporting (removed dev)...") check_dev_info_removed(prog_file=prog_file, map_file=map_file) @@ -1111,7 +1178,8 @@ try: clean_up() bpftool_prog_list_wait(expected=0) - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims start_test("Test map update (no flags)...") sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON @@ -1192,27 +1260,29 @@ try: start_test("Test map remove...") sim.unset_xdp("offload") bpftool_map_list_wait(expected=0) - sim.remove() + simdev.remove() - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.set_xdp(map_obj, "offload", JSON=False) # map fixup msg breaks JSON - sim.remove() + simdev.remove() bpftool_map_list_wait(expected=0) start_test("Test map creation fail path...") - sim = NetdevSim() + simdev = NetdevSimDev() + sim, = simdev.nsims sim.dfs["bpf_map_accept"] = "N" ret, _ = sim.set_xdp(map_obj, "offload", JSON=False, fail=False) fail(ret == 0, "netdevsim didn't refuse to create a map with offload disabled") - sim.remove() + simdev.remove() start_test("Test multi-dev ASIC program reuse...") - simA = NetdevSim() - simB1 = NetdevSim() - simB2 = NetdevSim(link=simB1) - simB3 = NetdevSim(link=simB1) + simdevA = NetdevSimDev() + simA, = simdevA.nsims + simdevB = NetdevSimDev(3) + simB1, simB2, simB3 = simdevB.nsims sims = (simA, simB1, simB2, simB3) simB = (simB1, simB2, simB3) @@ -1224,13 +1294,13 @@ try: progB = bpf_pinned("/sys/fs/bpf/nsimB") simA.set_xdp(progA, "offload", JSON=False) - for d in simB: + for d in simdevB.nsims: d.set_xdp(progB, "offload", JSON=False) start_test("Test multi-dev ASIC cross-dev replace...") ret, _ = simA.set_xdp(progB, "offload", force=True, JSON=False, fail=False) fail(ret == 0, "cross-ASIC program allowed") - for d in simB: + for d in simdevB.nsims: ret, _ = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False) fail(ret == 0, "cross-ASIC program allowed") @@ -1242,7 +1312,7 @@ try: fail=False, include_stderr=True) fail(ret == 0, "cross-ASIC program allowed") check_extack_nsim(err, "program bound to different dev.", args) - for d in simB: + for d in simdevB.nsims: ret, _, err = d.set_xdp(progA, "offload", force=True, JSON=False, fail=False, include_stderr=True) fail(ret == 0, "cross-ASIC program allowed") @@ -1279,7 +1349,7 @@ try: start_test("Test multi-dev ASIC cross-dev destruction...") bpftool_prog_list_wait(expected=2) - simA.remove() + simdevA.remove() bpftool_prog_list_wait(expected=1) ifnameB = bpftool("prog show %s" % (progB))[1]["dev"]["ifname"] @@ -1297,6 +1367,7 @@ try: fail(ifnameB != simB3['ifname'], "program not bound to remaining device") simB3.remove() + simdevB.remove() bpftool_prog_list_wait(expected=0) start_test("Test multi-dev ASIC cross-dev destruction - orphaned...") diff --git a/tools/testing/selftests/net/rtnetlink.sh b/tools/testing/selftests/net/rtnetlink.sh index 311f82bcbe8d..b25c9fe019d2 100755 --- a/tools/testing/selftests/net/rtnetlink.sh +++ b/tools/testing/selftests/net/rtnetlink.sh @@ -696,9 +696,9 @@ kci_test_ipsec_offload() algo="aead rfc4106(gcm(aes)) 0x3132333435363738393031323334353664636261 128" srcip=192.168.123.3 dstip=192.168.123.4 - dev=simx1 sysfsd=/sys/kernel/debug/netdevsim/netdevsim0/ports/0/ sysfsf=$sysfsd/ipsec + sysfsnet=/sys/bus/netdevsim/devices/netdevsim0/net/ # setup netdevsim since dummydev doesn't have offload support modprobe netdevsim @@ -708,7 +708,11 @@ kci_test_ipsec_offload() return 1 fi - ip link add $dev type netdevsim + echo "0" > /sys/bus/netdevsim/new_device + while [ ! -d $sysfsnet ] ; do :; done + udevadm settle + dev=`ls $sysfsnet` + ip addr add $srcip dev $dev ip link set $dev up if [ ! -d $sysfsd ] ; then @@ -781,7 +785,6 @@ EOF fi # clean up any leftovers - ip link del $dev rmmod netdevsim if [ $ret -ne 0 ]; then -- cgit v1.2.3