]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
net: netdevsim: Support setting dev->perm_addr on port creation
authorToke Høiland-Jørgensen <toke@redhat.com>
Thu, 10 Jul 2025 11:18:33 +0000 (13:18 +0200)
committerJakub Kicinski <kuba@kernel.org>
Sat, 12 Jul 2025 00:00:18 +0000 (17:00 -0700)
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.

To support this use case, support setting netdev->perm_addr when
creating a netdevsim port.

Reviewed-by: Simon Horman <horms@kernel.org>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Link: https://patch.msgid.link/20250710-netdevsim-perm_addr-v4-1-c9db2fecf3bf@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/netdevsim/bus.c
drivers/net/netdevsim/dev.c
drivers/net/netdevsim/netdev.c
drivers/net/netdevsim/netdevsim.h

index 64c0cdd31bf85468ce4fa2b2af5c8aff4cfba897..830abcb98476587940b79be36705ee00f86b51d3 100644 (file)
@@ -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,
+                    &eth_addr[0], &eth_addr[1], &eth_addr[2], &eth_addr[3],
+                    &eth_addr[4], &eth_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;
 }
 
index b3647691060c1f7a6fc6b1c63193ff1953b5ac08..01c7edb28d963c6d85fa8267e0dcf7a0f11525bb 100644 (file)
@@ -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;
 }
index e36d3e846c2dc314182efd1af03b59270397b007..f316e44130f722759f0ac4e5baac6a2f6956dc7d 100644 (file)
@@ -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:
index 809dd29fc5fea241a587d43fc3f89c1511db3c21..8eeeb925607745064f65f5c7d17443638cf5d21e 100644 (file)
@@ -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);