A single PCI device may have multiple netdevs associated with it. Each of those netdevs will have a different phys_port_id entry in sysfs. This patch modifies virPCIGetNetName() to allow matching the netdev for a PCI device that has the same phys_port_id that the caller wants. --- src/util/virhostdev.c | 2 +- src/util/virnetdev.c | 6 +++--- src/util/virpci.c | 49 ++++++++++++++++++++++++++++++++++++++++--------- src/util/virpci.h | 4 +++- 4 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 579563c3f..fcefebd07 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -326,7 +326,7 @@ virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, * type='hostdev'>, and it is only those devices that should * end up calling this function. */ - if (virPCIGetNetName(sysfs_path, linkdev) < 0) + if (virPCIGetNetName(sysfs_path, NULL, linkdev) < 0) goto cleanup; if (!linkdev) { diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c index a2664de78..1c150b7d7 100644 --- a/src/util/virnetdev.c +++ b/src/util/virnetdev.c @@ -1262,7 +1262,7 @@ virNetDevGetVirtualFunctions(const char *pfname, goto cleanup; } - if (virPCIGetNetName(pci_sysfs_device_link, &((*vfname)[i])) < 0) + if (virPCIGetNetName(pci_sysfs_device_link, NULL, &((*vfname)[i])) < 0) goto cleanup; if (!(*vfname)[i]) @@ -1362,7 +1362,7 @@ virNetDevGetPhysicalFunction(const char *ifname, char **pfname) if (virNetDevSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0) return ret; - if (virPCIGetNetName(physfn_sysfs_path, pfname) < 0) + if (virPCIGetNetName(physfn_sysfs_path, NULL, pfname) < 0) goto cleanup; if (!*pfname) { @@ -1422,7 +1422,7 @@ virNetDevPFGetVF(const char *pfname, int vf, char **vfname) * isn't bound to a netdev driver, it won't have a netdev name, * and vfname will be NULL). */ - ret = virPCIGetNetName(virtfnSysfsPath, vfname); + ret = virPCIGetNetName(virtfnSysfsPath, NULL, vfname); cleanup: VIR_FREE(virtfnName); diff --git a/src/util/virpci.c b/src/util/virpci.c index 2c1b75855..5d811ada6 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -24,6 +24,7 @@ #include <config.h> #include "virpci.h" +#include "virnetdev.h" #include <dirent.h> #include <fcntl.h> @@ -2857,12 +2858,15 @@ virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr addr, * Returns the network device name of a pci device */ int -virPCIGetNetName(char *device_link_sysfs_path, char **netname) +virPCIGetNetName(char *device_link_sysfs_path, + char *physPortID, + char **netname) { char *pcidev_sysfs_net_path = NULL; int ret = -1; DIR *dir = NULL; struct dirent *entry = NULL; + char *thisPhysPortID = NULL; if (virBuildPath(&pcidev_sysfs_net_path, device_link_sysfs_path, "net") == -1) { @@ -2873,21 +2877,47 @@ virPCIGetNetName(char *device_link_sysfs_path, char **netname) if (virDirOpenQuiet(&dir, pcidev_sysfs_net_path) < 0) { /* this *isn't* an error - caller needs to check for netname == NULL */ ret = 0; - goto out; + goto cleanup; } while (virDirRead(dir, &entry, pcidev_sysfs_net_path) > 0) { - /* Assume a single directory entry */ - if (VIR_STRDUP(*netname, entry->d_name) > 0) - ret = 0; + /* if the caller sent a physPortID, compare it to the + * physportID of this netdev. If not, accept the first netdev + */ + if (physPortID) { + if (virNetDevGetPhysPortID(entry->d_name, &thisPhysPortID) < 0) + goto cleanup; + + /* if this one doesn't match, keep looking */ + if (STRNEQ_NULLABLE(physPortID, thisPhysPortID)) { + VIR_FREE(thisPhysPortID); + continue; + } + } + if (VIR_STRDUP(*netname, entry->d_name) < 0) + goto cleanup; + + ret = 0; break; } + if (ret < 0) { + if (physPortID) { + 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); + } else { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("PCI device at %s had a net directory, " + "but it was empty"), + device_link_sysfs_path); + } + } + cleanup: VIR_DIR_CLOSE(dir); - - out: VIR_FREE(pcidev_sysfs_net_path); - + VIR_FREE(thisPhysPortID); return ret; } @@ -2915,7 +2945,7 @@ virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, goto cleanup; } - if (virPCIGetNetName(pf_sysfs_device_path, pfname) < 0) + if (virPCIGetNetName(pf_sysfs_device_path, NULL, pfname) < 0) goto cleanup; if (!*pfname) { @@ -2992,6 +3022,7 @@ virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr dev ATTRIBUTE_UNUSED, int virPCIGetNetName(char *device_link_sysfs_path ATTRIBUTE_UNUSED, + char *physPortID ATTRIBUTE_UNUSED, char **netname ATTRIBUTE_UNUSED) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported)); diff --git a/src/util/virpci.h b/src/util/virpci.h index 570684e75..c0e54d785 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -207,7 +207,9 @@ int virPCIGetVirtualFunctionIndex(const char *pf_sysfs_device_link, int virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr addr, char **pci_sysfs_device_link); -int virPCIGetNetName(char *device_link_sysfs_path, char **netname); +int virPCIGetNetName(char *device_link_sysfs_path, + char *physPortID, + char **netname); int virPCIGetSysfsFile(char *virPCIDeviceName, char **pci_sysfs_device_link) -- 2.13.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list