Description: To support kernels or dkms builds of mlx5_core driver with https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net.git/commit/?id=123f0f53dd64b67e34142485fe866a8a581f12f1 Origin: backport, https://github.com/libvirt/libvirt/commit/5b1c525b1f3608156884aed0dc5e925306c1e260 Bug-Ubuntu: https://bugs.launchpad.net/bugs/1892132 Last-Update: 2021-08-13 diff --git a/src/util/virpci.c b/src/util/virpci.c index 0b1222373e..a54be60da0 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -2424,9 +2424,9 @@ virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr addr, * virPCIGetNetName: * @device_link_sysfs_path: sysfs path to the PCI device * @idx: used to choose which netdev when there are several - * (ignored if physPortID is set) + * (ignored if physPortID is set or physPortName is available) * @physPortID: match this string in the netdev's phys_port_id - * (or NULL to ignore and use idx instead) + * (or NULL to ignore and use phys_port_name or idx instead) * @netname: used to return the name of the netdev * (set to NULL (but returns success) if there is no netdev) * @@ -2461,6 +2461,14 @@ virPCIGetNetName(const char *device_link_sysfs_path, } while (virDirRead(dir, &entry, pcidev_sysfs_net_path) > 0) { + /* save the first entry we find to use as a failsafe + * in case we don't match the phys_port_id. This is + * needed because some NIC drivers (e.g. i40e) + * implement phys_port_id for PFs, but not for VFs + */ + if (!firstEntryName) + firstEntryName = g_strdup(entry->d_name); + /* if the caller sent a physPortID, compare it to the * physportID of this netdev. If not, look for entry[idx]. */ @@ -2471,19 +2479,35 @@ virPCIGetNetName(const char *device_link_sysfs_path, /* if this one doesn't match, keep looking */ if (STRNEQ_NULLABLE(physPortID, thisPhysPortID)) { VIR_FREE(thisPhysPortID); - /* save the first entry we find to use as a failsafe - * in case we don't match the phys_port_id. This is - * needed because some NIC drivers (e.g. i40e) - * implement phys_port_id for PFs, but not for VFs - */ - if (!firstEntryName) - firstEntryName = g_strdup(entry->d_name); - continue; } } else { - if (i++ < idx) - continue; + /* Most switch devices use phys_port_name instead of + * phys_port_id. + * NOTE: VFs' representors net devices can be linked to PF's PCI + * device, which mean that there'll be multiple net devices + * instances and to get a proper net device need to match on + * specific regex. + * To get PF netdev, for ex., used following regex: + * "(p[0-9]+$)|(p[0-9]+s[0-9]+$)" + * or to get exact VF's netdev next regex is used: + * "pf0vf1$" + */ + g_autofree char *thisPhysPortName = NULL; + if (virNetDevGetPhysPortName(entry->d_name, &thisPhysPortName) < 0) + goto cleanup; + + if (thisPhysPortName) { + + /* if this one doesn't match, keep looking */ + if (!virStringMatch(thisPhysPortName, VIR_PF_PHYS_PORT_NAME_REGEX)) + continue; + + } else { + + if (i++ < idx) + continue; + } } *netname = g_strdup(entry->d_name); @@ -2493,24 +2517,21 @@ virPCIGetNetName(const char *device_link_sysfs_path, } if (ret < 0) { - if (physPortID) { - if (firstEntryName) { - /* we didn't match the provided phys_port_id, but this - * is probably because phys_port_id isn't implemented - * for this NIC driver, so just return the first - * (probably only) netname we found. - */ - *netname = firstEntryName; - firstEntryName = NULL; - ret = 0; - } else { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Could not find network device with " - "phys_port_id '%s' under PCI device at %s"), - physPortID, device_link_sysfs_path); - } + if (firstEntryName) { + /* we didn't match the provided phys_port_id / find a + * phys_port_name matching VIR_PF_PHYS_PORT_NAME_REGEX / find + * as many net devices as the value of idx, but this is + * probably because phys_port_id / phys_port_name isn't + * implemented for this NIC driver, so just return the first + * (probably only) netname we found. + */ + *netname = g_steal_pointer(&firstEntryName); + ret = 0; } else { - ret = 0; /* no netdev at the given index is *not* an error */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find any network device under PCI device at %s"), + device_link_sysfs_path); + ret = -1; } } cleanup: diff --git a/src/util/virpci.h b/src/util/virpci.h index f6796fc422..e47c766918 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -49,6 +49,11 @@ struct _virZPCIDeviceAddress { #define VIR_PCI_DEVICE_ADDRESS_FMT "%04x:%02x:%02x.%d" +/* Represents format of PF's phys_port_name in switchdev mode: + * 'p%u' or 'p%us%u'. New line checked since value is readed from sysfs file. + */ +#define VIR_PF_PHYS_PORT_NAME_REGEX "(p[0-9]+$)|(p[0-9]+s[0-9]+$)" + struct _virPCIDeviceAddress { unsigned int domain; unsigned int bus;