mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
Merge branch 'netdevsim-support-setting-a-permanent-address'
Toke Høiland-Jørgensen says: ==================== netdevsim: support setting a permanent address Network management daemons that match on the device permanent address currently have no virtual interface types to test against. NetworkManager, in particular, has carried an out of tree patch to set the permanent address on netdevsim devices to use in its CI for this purpose. This series adds support to netdevsim to set a permanent address on port creation, and adds a test script to test setting and getting of the different L2 address types. v3: https://lore.kernel.org/20250706-netdevsim-perm_addr-v3-0-88123e2b2027@redhat.com v2: https://lore.kernel.org/20250702-netdevsim-perm_addr-v2-0-66359a6288f0@redhat.com v1: https://lore.kernel.org/20250203-netdevsim-perm_addr-v1-1-10084bc93044@redhat.com ==================== Link: https://patch.msgid.link/20250710-netdevsim-perm_addr-v4-0-c9db2fecf3bf@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
9ae277096f
|
|
@ -66,17 +66,35 @@ 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);
|
||||
u8 eth_addr[ETH_ALEN] = {};
|
||||
unsigned int port_index;
|
||||
bool addr_set = false;
|
||||
int ret;
|
||||
|
||||
/* Prevent to use nsim_bus_dev before initialization. */
|
||||
if (!smp_load_acquire(&nsim_bus_dev->init))
|
||||
return -EBUSY;
|
||||
ret = kstrtouint(buf, 0, &port_index);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index);
|
||||
ret = sscanf(buf, "%u %hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &port_index,
|
||||
ð_addr[0], ð_addr[1], ð_addr[2], ð_addr[3],
|
||||
ð_addr[4], ð_addr[5]);
|
||||
switch (ret) {
|
||||
case 7:
|
||||
if (!is_valid_ether_addr(eth_addr)) {
|
||||
pr_err("The supplied perm_addr is not a valid MAC address\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
addr_set = true;
|
||||
fallthrough;
|
||||
case 1:
|
||||
break;
|
||||
default:
|
||||
pr_err("Format for adding new port is \"id [perm_addr]\" (uint MAC).\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = nsim_drv_port_add(nsim_bus_dev, NSIM_DEV_PORT_TYPE_PF, port_index,
|
||||
addr_set ? eth_addr : NULL);
|
||||
return ret ? ret : count;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -589,7 +589,7 @@ static void nsim_dev_dummy_region_exit(struct nsim_dev *nsim_dev)
|
|||
|
||||
static int
|
||||
__nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,
|
||||
unsigned int port_index);
|
||||
unsigned int port_index, u8 perm_addr[ETH_ALEN]);
|
||||
static void __nsim_dev_port_del(struct nsim_dev_port *nsim_dev_port);
|
||||
|
||||
static int nsim_esw_legacy_enable(struct nsim_dev *nsim_dev,
|
||||
|
|
@ -613,7 +613,7 @@ static int nsim_esw_switchdev_enable(struct nsim_dev *nsim_dev,
|
|||
int i, err;
|
||||
|
||||
for (i = 0; i < nsim_dev_get_vfs(nsim_dev); i++) {
|
||||
err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_VF, i);
|
||||
err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_VF, i, NULL);
|
||||
if (err) {
|
||||
NL_SET_ERR_MSG_MOD(extack, "Failed to initialize VFs' netdevsim ports");
|
||||
pr_err("Failed to initialize VF id=%d. %d.\n", i, err);
|
||||
|
|
@ -1396,7 +1396,7 @@ static const struct devlink_ops nsim_dev_devlink_ops = {
|
|||
#define NSIM_DEV_TEST1_DEFAULT true
|
||||
|
||||
static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,
|
||||
unsigned int port_index)
|
||||
unsigned int port_index, u8 perm_addr[ETH_ALEN])
|
||||
{
|
||||
struct devlink_port_attrs attrs = {};
|
||||
struct nsim_dev_port *nsim_dev_port;
|
||||
|
|
@ -1433,7 +1433,7 @@ static int __nsim_dev_port_add(struct nsim_dev *nsim_dev, enum nsim_dev_port_typ
|
|||
if (err)
|
||||
goto err_dl_port_unregister;
|
||||
|
||||
nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port);
|
||||
nsim_dev_port->ns = nsim_create(nsim_dev, nsim_dev_port, perm_addr);
|
||||
if (IS_ERR(nsim_dev_port->ns)) {
|
||||
err = PTR_ERR(nsim_dev_port->ns);
|
||||
goto err_port_debugfs_exit;
|
||||
|
|
@ -1489,7 +1489,7 @@ static int nsim_dev_port_add_all(struct nsim_dev *nsim_dev,
|
|||
int i, err;
|
||||
|
||||
for (i = 0; i < port_count; i++) {
|
||||
err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i);
|
||||
err = __nsim_dev_port_add(nsim_dev, NSIM_DEV_PORT_TYPE_PF, i, NULL);
|
||||
if (err)
|
||||
goto err_port_del_all;
|
||||
}
|
||||
|
|
@ -1745,7 +1745,7 @@ __nsim_dev_port_lookup(struct nsim_dev *nsim_dev, enum nsim_dev_port_type type,
|
|||
}
|
||||
|
||||
int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type type,
|
||||
unsigned int port_index)
|
||||
unsigned int port_index, u8 perm_addr[ETH_ALEN])
|
||||
{
|
||||
struct nsim_dev *nsim_dev = dev_get_drvdata(&nsim_bus_dev->dev);
|
||||
int err;
|
||||
|
|
@ -1754,7 +1754,7 @@ int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev, enum nsim_dev_port_type
|
|||
if (__nsim_dev_port_lookup(nsim_dev, type, port_index))
|
||||
err = -EEXIST;
|
||||
else
|
||||
err = __nsim_dev_port_add(nsim_dev, type, port_index);
|
||||
err = __nsim_dev_port_add(nsim_dev, type, port_index, perm_addr);
|
||||
devl_unlock(priv_to_devlink(nsim_dev));
|
||||
return err;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -998,8 +998,9 @@ static void nsim_exit_netdevsim(struct netdevsim *ns)
|
|||
mock_phc_destroy(ns->phc);
|
||||
}
|
||||
|
||||
struct netdevsim *
|
||||
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
|
||||
struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
|
||||
struct nsim_dev_port *nsim_dev_port,
|
||||
u8 perm_addr[ETH_ALEN])
|
||||
{
|
||||
struct net_device *dev;
|
||||
struct netdevsim *ns;
|
||||
|
|
@ -1010,6 +1011,9 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
|
|||
if (!dev)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (perm_addr)
|
||||
memcpy(dev->perm_addr, perm_addr, ETH_ALEN);
|
||||
|
||||
dev_net_set(dev, nsim_dev_net(nsim_dev));
|
||||
ns = netdev_priv(dev);
|
||||
ns->netdev = dev;
|
||||
|
|
@ -1031,7 +1035,6 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
|
|||
ns->qr_dfs = debugfs_create_file("queue_reset", 0200,
|
||||
nsim_dev_port->ddir, ns,
|
||||
&nsim_qreset_fops);
|
||||
|
||||
return ns;
|
||||
|
||||
err_free_netdev:
|
||||
|
|
|
|||
|
|
@ -143,8 +143,9 @@ struct netdevsim {
|
|||
struct netdev_net_notifier nn;
|
||||
};
|
||||
|
||||
struct netdevsim *
|
||||
nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port);
|
||||
struct netdevsim *nsim_create(struct nsim_dev *nsim_dev,
|
||||
struct nsim_dev_port *nsim_dev_port,
|
||||
u8 perm_addr[ETH_ALEN]);
|
||||
void nsim_destroy(struct netdevsim *ns);
|
||||
bool netdev_is_nsim(struct net_device *dev);
|
||||
|
||||
|
|
@ -362,8 +363,8 @@ void nsim_dev_exit(void);
|
|||
int nsim_drv_probe(struct nsim_bus_dev *nsim_bus_dev);
|
||||
void nsim_drv_remove(struct nsim_bus_dev *nsim_bus_dev);
|
||||
int nsim_drv_port_add(struct nsim_bus_dev *nsim_bus_dev,
|
||||
enum nsim_dev_port_type type,
|
||||
unsigned int port_index);
|
||||
enum nsim_dev_port_type type, unsigned int port_index,
|
||||
u8 perm_addr[ETH_ALEN]);
|
||||
int nsim_drv_port_del(struct nsim_bus_dev *nsim_bus_dev,
|
||||
enum nsim_dev_port_type type,
|
||||
unsigned int port_index);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ TEST_PROGS += ip_local_port_range.sh
|
|||
TEST_PROGS += rps_default_mask.sh
|
||||
TEST_PROGS += big_tcp.sh
|
||||
TEST_PROGS += netns-sysctl.sh
|
||||
TEST_PROGS += netdev-l2addr.sh
|
||||
TEST_PROGS_EXTENDED := toeplitz_client.sh toeplitz.sh xfrm_policy_add_speed.sh
|
||||
TEST_GEN_FILES = socket nettest
|
||||
TEST_GEN_FILES += psock_fanout psock_tpacket msg_zerocopy reuseport_addr_any
|
||||
|
|
|
|||
|
|
@ -240,6 +240,29 @@ create_netdevsim() {
|
|||
echo nsim$id
|
||||
}
|
||||
|
||||
create_netdevsim_port() {
|
||||
local nsim_id="$1"
|
||||
local ns="$2"
|
||||
local port_id="$3"
|
||||
local perm_addr="$4"
|
||||
local orig_dev
|
||||
local new_dev
|
||||
local nsim_path
|
||||
|
||||
nsim_path="/sys/bus/netdevsim/devices/netdevsim$nsim_id"
|
||||
|
||||
echo "$port_id $perm_addr" | ip netns exec "$ns" tee "$nsim_path"/new_port > /dev/null || return 1
|
||||
|
||||
orig_dev=$(ip netns exec "$ns" find "$nsim_path"/net/ -maxdepth 1 -name 'e*' | tail -n 1)
|
||||
orig_dev=$(basename "$orig_dev")
|
||||
new_dev="nsim${nsim_id}p$port_id"
|
||||
|
||||
ip -netns "$ns" link set dev "$orig_dev" name "$new_dev"
|
||||
ip -netns "$ns" link set dev "$new_dev" up
|
||||
|
||||
echo "$new_dev"
|
||||
}
|
||||
|
||||
# Remove netdevsim with given id.
|
||||
cleanup_netdevsim() {
|
||||
local id="$1"
|
||||
|
|
|
|||
59
tools/testing/selftests/net/netdev-l2addr.sh
Executable file
59
tools/testing/selftests/net/netdev-l2addr.sh
Executable file
|
|
@ -0,0 +1,59 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
source lib.sh
|
||||
set -o pipefail
|
||||
|
||||
NSIM_ADDR=2025
|
||||
TEST_ADDR="d0:be:d0:be:d0:00"
|
||||
|
||||
RET_CODE=0
|
||||
|
||||
cleanup() {
|
||||
cleanup_netdevsim "$NSIM_ADDR"
|
||||
cleanup_ns "$NS"
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
|
||||
fail() {
|
||||
echo "ERROR: ${1:-unexpected return code} (ret: $_)" >&2
|
||||
RET_CODE=1
|
||||
}
|
||||
|
||||
get_addr()
|
||||
{
|
||||
local type="$1"
|
||||
local dev="$2"
|
||||
local ns="$3"
|
||||
|
||||
ip -j -n "$ns" link show dev "$dev" | jq -er ".[0].$type"
|
||||
}
|
||||
|
||||
setup_ns NS
|
||||
|
||||
nsim=$(create_netdevsim $NSIM_ADDR "$NS")
|
||||
|
||||
get_addr address "$nsim" "$NS" >/dev/null || fail "Couldn't get ether addr"
|
||||
get_addr broadcast "$nsim" "$NS" >/dev/null || fail "Couldn't get brd addr"
|
||||
get_addr permaddr "$nsim" "$NS" >/dev/null && fail "Found perm_addr without setting it"
|
||||
|
||||
ip -n "$NS" link set dev "$nsim" address "$TEST_ADDR"
|
||||
ip -n "$NS" link set dev "$nsim" brd "$TEST_ADDR"
|
||||
|
||||
[[ "$(get_addr address "$nsim" "$NS")" == "$TEST_ADDR" ]] || fail "Couldn't set ether addr"
|
||||
[[ "$(get_addr broadcast "$nsim" "$NS")" == "$TEST_ADDR" ]] || fail "Couldn't set brd addr"
|
||||
|
||||
if create_netdevsim_port "$NSIM_ADDR" "$NS" 2 "FF:FF:FF:FF:FF:FF" 2>/dev/null; then
|
||||
fail "Created netdevsim with broadcast permaddr"
|
||||
fi
|
||||
|
||||
nsim_port=$(create_netdevsim_port "$NSIM_ADDR" "$NS" 2 "$TEST_ADDR")
|
||||
|
||||
get_addr address "$nsim_port" "$NS" >/dev/null || fail "Couldn't get ether addr"
|
||||
get_addr broadcast "$nsim_port" "$NS" >/dev/null || fail "Couldn't get brd addr"
|
||||
[[ "$(get_addr permaddr "$nsim_port" "$NS")" == "$TEST_ADDR" ]] || fail "Couldn't get permaddr"
|
||||
|
||||
cleanup_netdevsim "$NSIM_ADDR" "$NS"
|
||||
|
||||
exit $RET_CODE
|
||||
Loading…
Reference in New Issue
Block a user