lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Message-Id: <20231210010448.816126-2-dw@davidwei.uk> Date: Sat, 9 Dec 2023 17:04:46 -0800 From: David Wei <dw@...idwei.uk> To: Jakub Kicinski <kuba@...nel.org>, Jiri Pirko <jiri@...nulli.us>, Sabrina Dubroca <sd@...asysnail.net>, netdev@...r.kernel.org Cc: "David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>, Paolo Abeni <pabeni@...hat.com> Subject: [PATCH net-next v2 1/3] netdevsim: allow two netdevsim ports to be connected From: David Wei <davidhwei@...a.com> Add a debugfs file in /sys/kernel/debug/netdevsim/netdevsimN/ports/A/peer Writing "M B" to this file will link port A of netdevsim N with port B of netdevsim M. Reading this file will return the linked netdevsim id and port, if any. Signed-off-by: David Wei <dw@...idwei.uk> --- drivers/net/netdevsim/bus.c | 10 ++++ drivers/net/netdevsim/dev.c | 85 +++++++++++++++++++++++++++++++ drivers/net/netdevsim/netdev.c | 6 +++ drivers/net/netdevsim/netdevsim.h | 3 ++ 4 files changed, 104 insertions(+) diff --git a/drivers/net/netdevsim/bus.c b/drivers/net/netdevsim/bus.c index bcbc1e19edde..3e4378e9dbee 100644 --- a/drivers/net/netdevsim/bus.c +++ b/drivers/net/netdevsim/bus.c @@ -364,3 +364,13 @@ void nsim_bus_exit(void) driver_unregister(&nsim_driver); bus_unregister(&nsim_bus); } + +struct nsim_bus_dev *nsim_bus_dev_get(unsigned int id) +{ + struct nsim_bus_dev *nsim_bus_dev; + list_for_each_entry(nsim_bus_dev, &nsim_bus_dev_list, list) { + if (nsim_bus_dev->dev.id == id) + return nsim_bus_dev; + } + return NULL; +} diff --git a/drivers/net/netdevsim/dev.c b/drivers/net/netdevsim/dev.c index b4d3b9cde8bd..7af219ff6fa9 100644 --- a/drivers/net/netdevsim/dev.c +++ b/drivers/net/netdevsim/dev.c @@ -388,6 +388,88 @@ static const struct file_operations nsim_dev_rate_parent_fops = { .owner = THIS_MODULE, }; +static ssize_t nsim_dev_peer_read(struct file *file, char __user *data, + size_t count, loff_t *ppos) +{ + struct nsim_dev_port *nsim_dev_port; + struct netdevsim *peer; + unsigned int id, port; + char buf[23]; + ssize_t len; + + nsim_dev_port = file->private_data; + rcu_read_lock(); + peer = rcu_dereference(nsim_dev_port->ns->peer); + if (!peer) { + len = scnprintf(buf, sizeof(buf), "\n"); + goto out; + } + + id = peer->nsim_bus_dev->dev.id; + port = peer->nsim_dev_port->port_index; + len = scnprintf(buf, sizeof(buf), "%u %u\n", id, port); + +out: + rcu_read_unlock(); + return simple_read_from_buffer(data, count, ppos, buf, len); +} + +static ssize_t nsim_dev_peer_write(struct file *file, + const char __user *data, + size_t count, loff_t *ppos) +{ + struct nsim_dev_port *nsim_dev_port, *peer_dev_port; + struct nsim_bus_dev *peer_bus_dev; + struct nsim_dev *peer_dev; + unsigned int id, port; + char buf[22]; + ssize_t ret; + + if (count >= sizeof(buf)) + return -ENOSPC; + + ret = copy_from_user(buf, data, count); + if (ret) + return -EFAULT; + buf[count] = '\0'; + + ret = sscanf(buf, "%u %u", &id, &port); + if (ret != 2) { + pr_err("Format for adding a peer is \"id port\" (uint uint)"); + return -EINVAL; + } + + /* invalid netdevsim id */ + peer_bus_dev = nsim_bus_dev_get(id); + if (!peer_bus_dev) + return -EINVAL; + + /* cannot link to self */ + nsim_dev_port = file->private_data; + if (nsim_dev_port->ns->nsim_bus_dev == peer_bus_dev && + nsim_dev_port->port_index == port) + return -EINVAL; + + peer_dev = dev_get_drvdata(&peer_bus_dev->dev); + list_for_each_entry(peer_dev_port, &peer_dev->port_list, list) { + if (peer_dev_port->port_index != port) + continue; + rcu_assign_pointer(nsim_dev_port->ns->peer, peer_dev_port->ns); + rcu_assign_pointer(peer_dev_port->ns->peer, nsim_dev_port->ns); + return count; + } + + return -EINVAL; +} + +static const struct file_operations nsim_dev_peer_fops = { + .open = simple_open, + .read = nsim_dev_peer_read, + .write = nsim_dev_peer_write, + .llseek = generic_file_llseek, + .owner = THIS_MODULE, +}; + static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) { @@ -418,6 +500,9 @@ static int nsim_dev_port_debugfs_init(struct nsim_dev *nsim_dev, } debugfs_create_symlink("dev", nsim_dev_port->ddir, dev_link_name); + debugfs_create_file("peer", 0600, nsim_dev_port->ddir, + nsim_dev_port, &nsim_dev_peer_fops); + return 0; } diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index aecaf5f44374..e290c54b0e70 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -388,6 +388,7 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) ns->nsim_dev = nsim_dev; ns->nsim_dev_port = nsim_dev_port; ns->nsim_bus_dev = nsim_dev->nsim_bus_dev; + RCU_INIT_POINTER(ns->peer, NULL); SET_NETDEV_DEV(dev, &ns->nsim_bus_dev->dev); SET_NETDEV_DEVLINK_PORT(dev, &nsim_dev_port->devlink_port); nsim_ethtool_init(ns); @@ -407,9 +408,14 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) void nsim_destroy(struct netdevsim *ns) { struct net_device *dev = ns->netdev; + struct netdevsim *peer; rtnl_lock(); + peer = rtnl_dereference(ns->peer); + RCU_INIT_POINTER(ns->peer, NULL); unregister_netdevice(dev); + if (peer) + RCU_INIT_POINTER(peer->peer, NULL); if (nsim_dev_port_is_pf(ns->nsim_dev_port)) { nsim_macsec_teardown(ns); nsim_ipsec_teardown(ns); diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index 028c825b86db..2601c3ad1d17 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -125,6 +125,7 @@ struct netdevsim { } udp_ports; struct nsim_ethtool ethtool; + struct netdevsim __rcu *peer; }; struct netdevsim * @@ -417,3 +418,5 @@ struct nsim_bus_dev { int nsim_bus_init(void); void nsim_bus_exit(void); + +struct nsim_bus_dev *nsim_bus_dev_get(unsigned int id); -- 2.39.3
Powered by blists - more mailing lists