|
|
6d3351 |
From 282c1d8582c7b3a30c87f3ad50859ad139cdce7c Mon Sep 17 00:00:00 2001
|
|
|
6d3351 |
Message-Id: <282c1d8582c7b3a30c87f3ad50859ad139cdce7c@dist-git>
|
|
|
6d3351 |
From: Laine Stump <laine@laine.org>
|
|
|
6d3351 |
Date: Mon, 14 Aug 2017 21:28:18 -0400
|
|
|
6d3351 |
Subject: [PATCH] util: make virPCIGetNetName() more versatile
|
|
|
6d3351 |
|
|
|
6d3351 |
A single PCI device may have multiple netdevs associated with it. Each
|
|
|
6d3351 |
of those netdevs will have a different phys_port_id entry in
|
|
|
6d3351 |
sysfs. This patch modifies virPCIGetNetName() to allow selecting one
|
|
|
6d3351 |
of the potential many netdevs in two different ways:
|
|
|
6d3351 |
|
|
|
6d3351 |
1) by setting the "idx" argument, the caller can select the 1st (0),
|
|
|
6d3351 |
2nd (1), etc. netdev from the PCI device's net subdirectory.
|
|
|
6d3351 |
|
|
|
6d3351 |
2) If the physPortID arg is set (to a null-terminated string) then
|
|
|
6d3351 |
virPCIGetNetName() returns the netdev that has that phys_port_id in
|
|
|
6d3351 |
the sysfs file of the same name in the netdev's directory.
|
|
|
6d3351 |
|
|
|
6d3351 |
Resolves: https://bugzilla.redhat.com/1460082
|
|
|
6d3351 |
|
|
|
6d3351 |
(cherry picked from commit b3b5aa75ed40d14bb96d3e7d2cff7356ccaab442)
|
|
|
6d3351 |
|
|
|
6d3351 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
6d3351 |
---
|
|
|
6d3351 |
src/util/virhostdev.c | 2 +-
|
|
|
6d3351 |
src/util/virnetdev.c | 9 ++++---
|
|
|
6d3351 |
src/util/virpci.c | 66 ++++++++++++++++++++++++++++++++++++++++++---------
|
|
|
6d3351 |
src/util/virpci.h | 5 +++-
|
|
|
6d3351 |
4 files changed, 66 insertions(+), 16 deletions(-)
|
|
|
6d3351 |
|
|
|
6d3351 |
diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c
|
|
|
6d3351 |
index 579563c3f3..580f0fac06 100644
|
|
|
6d3351 |
--- a/src/util/virhostdev.c
|
|
|
6d3351 |
+++ b/src/util/virhostdev.c
|
|
|
6d3351 |
@@ -326,7 +326,7 @@ virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
|
|
|
6d3351 |
* type='hostdev'>, and it is only those devices that should
|
|
|
6d3351 |
* end up calling this function.
|
|
|
6d3351 |
*/
|
|
|
6d3351 |
- if (virPCIGetNetName(sysfs_path, linkdev) < 0)
|
|
|
6d3351 |
+ if (virPCIGetNetName(sysfs_path, 0, NULL, linkdev) < 0)
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
|
|
|
6d3351 |
if (!linkdev) {
|
|
|
6d3351 |
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
|
|
|
6d3351 |
index 2fced369b3..b6d31ef938 100644
|
|
|
6d3351 |
--- a/src/util/virnetdev.c
|
|
|
6d3351 |
+++ b/src/util/virnetdev.c
|
|
|
6d3351 |
@@ -1262,8 +1262,10 @@ virNetDevGetVirtualFunctions(const char *pfname,
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
- if (virPCIGetNetName(pci_sysfs_device_link, &((*vfname)[i])) < 0)
|
|
|
6d3351 |
+ if (virPCIGetNetName(pci_sysfs_device_link, 0,
|
|
|
6d3351 |
+ NULL, &((*vfname)[i])) < 0) {
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
|
|
|
6d3351 |
if (!(*vfname)[i])
|
|
|
6d3351 |
VIR_INFO("VF does not have an interface name");
|
|
|
6d3351 |
@@ -1362,7 +1364,8 @@ virNetDevGetPhysicalFunction(const char *ifname, char **pfname)
|
|
|
6d3351 |
if (virNetDevSysfsDeviceFile(&physfn_sysfs_path, ifname, "physfn") < 0)
|
|
|
6d3351 |
return ret;
|
|
|
6d3351 |
|
|
|
6d3351 |
- if (virPCIGetNetName(physfn_sysfs_path, pfname) < 0)
|
|
|
6d3351 |
+ if (virPCIGetNetName(physfn_sysfs_path, 0,
|
|
|
6d3351 |
+ NULL, pfname) < 0)
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
|
|
|
6d3351 |
if (!*pfname) {
|
|
|
6d3351 |
@@ -1422,7 +1425,7 @@ virNetDevPFGetVF(const char *pfname, int vf, char **vfname)
|
|
|
6d3351 |
* isn't bound to a netdev driver, it won't have a netdev name,
|
|
|
6d3351 |
* and vfname will be NULL).
|
|
|
6d3351 |
*/
|
|
|
6d3351 |
- ret = virPCIGetNetName(virtfnSysfsPath, vfname);
|
|
|
6d3351 |
+ ret = virPCIGetNetName(virtfnSysfsPath, 0, NULL, vfname);
|
|
|
6d3351 |
|
|
|
6d3351 |
cleanup:
|
|
|
6d3351 |
VIR_FREE(virtfnName);
|
|
|
6d3351 |
diff --git a/src/util/virpci.c b/src/util/virpci.c
|
|
|
6d3351 |
index b2b50c2d3a..e7bb588da1 100644
|
|
|
6d3351 |
--- a/src/util/virpci.c
|
|
|
6d3351 |
+++ b/src/util/virpci.c
|
|
|
6d3351 |
@@ -24,6 +24,7 @@
|
|
|
6d3351 |
#include <config.h>
|
|
|
6d3351 |
|
|
|
6d3351 |
#include "virpci.h"
|
|
|
6d3351 |
+#include "virnetdev.h"
|
|
|
6d3351 |
|
|
|
6d3351 |
#include <dirent.h>
|
|
|
6d3351 |
#include <fcntl.h>
|
|
|
6d3351 |
@@ -2855,16 +2856,30 @@ virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr addr,
|
|
|
6d3351 |
return 0;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
-/*
|
|
|
6d3351 |
- * Returns the network device name of a pci device
|
|
|
6d3351 |
+/**
|
|
|
6d3351 |
+ * virPCIGetNetName:
|
|
|
6d3351 |
+ * @device_link_sysfs_path: sysfs path to the PCI device
|
|
|
6d3351 |
+ * @idx: used to choose which netdev when there are several
|
|
|
6d3351 |
+ * (ignored if physPortID is set)
|
|
|
6d3351 |
+ * @physPortID: match this string in the netdev's phys_port_id
|
|
|
6d3351 |
+ * (or NULL to ignore and use idx instead)
|
|
|
6d3351 |
+ * @netname: used to return the name of the netdev
|
|
|
6d3351 |
+ * (set to NULL (but returns success) if there is no netdev)
|
|
|
6d3351 |
+ *
|
|
|
6d3351 |
+ * Returns 0 on success, -1 on error (error has been logged)
|
|
|
6d3351 |
*/
|
|
|
6d3351 |
int
|
|
|
6d3351 |
-virPCIGetNetName(const char *device_link_sysfs_path, char **netname)
|
|
|
6d3351 |
+virPCIGetNetName(const char *device_link_sysfs_path,
|
|
|
6d3351 |
+ size_t idx,
|
|
|
6d3351 |
+ char *physPortID,
|
|
|
6d3351 |
+ char **netname)
|
|
|
6d3351 |
{
|
|
|
6d3351 |
char *pcidev_sysfs_net_path = NULL;
|
|
|
6d3351 |
int ret = -1;
|
|
|
6d3351 |
DIR *dir = NULL;
|
|
|
6d3351 |
struct dirent *entry = NULL;
|
|
|
6d3351 |
+ char *thisPhysPortID = NULL;
|
|
|
6d3351 |
+ size_t i = 0;
|
|
|
6d3351 |
|
|
|
6d3351 |
if (virBuildPath(&pcidev_sysfs_net_path, device_link_sysfs_path,
|
|
|
6d3351 |
"net") == -1) {
|
|
|
6d3351 |
@@ -2875,21 +2890,48 @@ virPCIGetNetName(const char *device_link_sysfs_path, char **netname)
|
|
|
6d3351 |
if (virDirOpenQuiet(&dir, pcidev_sysfs_net_path) < 0) {
|
|
|
6d3351 |
/* this *isn't* an error - caller needs to check for netname == NULL */
|
|
|
6d3351 |
ret = 0;
|
|
|
6d3351 |
- goto out;
|
|
|
6d3351 |
+ goto cleanup;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
while (virDirRead(dir, &entry, pcidev_sysfs_net_path) > 0) {
|
|
|
6d3351 |
- /* Assume a single directory entry */
|
|
|
6d3351 |
- if (VIR_STRDUP(*netname, entry->d_name) > 0)
|
|
|
6d3351 |
- ret = 0;
|
|
|
6d3351 |
+ /* if the caller sent a physPortID, compare it to the
|
|
|
6d3351 |
+ * physportID of this netdev. If not, look for entry[idx].
|
|
|
6d3351 |
+ */
|
|
|
6d3351 |
+ if (physPortID) {
|
|
|
6d3351 |
+ if (virNetDevGetPhysPortID(entry->d_name, &thisPhysPortID) < 0)
|
|
|
6d3351 |
+ goto cleanup;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ /* if this one doesn't match, keep looking */
|
|
|
6d3351 |
+ if (STRNEQ_NULLABLE(physPortID, thisPhysPortID)) {
|
|
|
6d3351 |
+ VIR_FREE(thisPhysPortID);
|
|
|
6d3351 |
+ continue;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+ } else {
|
|
|
6d3351 |
+ if (i++ < idx)
|
|
|
6d3351 |
+ continue;
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ if (VIR_STRDUP(*netname, entry->d_name) < 0)
|
|
|
6d3351 |
+ goto cleanup;
|
|
|
6d3351 |
+
|
|
|
6d3351 |
+ ret = 0;
|
|
|
6d3351 |
break;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
+ if (ret < 0) {
|
|
|
6d3351 |
+ if (physPortID) {
|
|
|
6d3351 |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
6d3351 |
+ _("Could not find network device with "
|
|
|
6d3351 |
+ "phys_port_id '%s' under PCI device at %s"),
|
|
|
6d3351 |
+ physPortID, device_link_sysfs_path);
|
|
|
6d3351 |
+ } else {
|
|
|
6d3351 |
+ ret = 0; /* no netdev at the given index is *not* an error */
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+ }
|
|
|
6d3351 |
+ cleanup:
|
|
|
6d3351 |
VIR_DIR_CLOSE(dir);
|
|
|
6d3351 |
-
|
|
|
6d3351 |
- out:
|
|
|
6d3351 |
VIR_FREE(pcidev_sysfs_net_path);
|
|
|
6d3351 |
-
|
|
|
6d3351 |
+ VIR_FREE(thisPhysPortID);
|
|
|
6d3351 |
return ret;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
@@ -2917,7 +2959,7 @@ virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path,
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
}
|
|
|
6d3351 |
|
|
|
6d3351 |
- if (virPCIGetNetName(pf_sysfs_device_path, pfname) < 0)
|
|
|
6d3351 |
+ if (virPCIGetNetName(pf_sysfs_device_path, 0, NULL, pfname) < 0)
|
|
|
6d3351 |
goto cleanup;
|
|
|
6d3351 |
|
|
|
6d3351 |
if (!*pfname) {
|
|
|
6d3351 |
@@ -2994,6 +3036,8 @@ virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr dev ATTRIBUTE_UNUSED,
|
|
|
6d3351 |
|
|
|
6d3351 |
int
|
|
|
6d3351 |
virPCIGetNetName(const char *device_link_sysfs_path ATTRIBUTE_UNUSED,
|
|
|
6d3351 |
+ size_t idx ATTRIBUTE_UNUSED,
|
|
|
6d3351 |
+ char *physPortID ATTRIBUTE_UNUSED,
|
|
|
6d3351 |
char **netname ATTRIBUTE_UNUSED)
|
|
|
6d3351 |
{
|
|
|
6d3351 |
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _(unsupported));
|
|
|
6d3351 |
diff --git a/src/util/virpci.h b/src/util/virpci.h
|
|
|
6d3351 |
index 82d4ddc61b..adf336706b 100644
|
|
|
6d3351 |
--- a/src/util/virpci.h
|
|
|
6d3351 |
+++ b/src/util/virpci.h
|
|
|
6d3351 |
@@ -207,7 +207,10 @@ int virPCIGetVirtualFunctionIndex(const char *pf_sysfs_device_link,
|
|
|
6d3351 |
int virPCIDeviceAddressGetSysfsFile(virPCIDeviceAddressPtr addr,
|
|
|
6d3351 |
char **pci_sysfs_device_link);
|
|
|
6d3351 |
|
|
|
6d3351 |
-int virPCIGetNetName(const char *device_link_sysfs_path, char **netname);
|
|
|
6d3351 |
+int virPCIGetNetName(const char *device_link_sysfs_path,
|
|
|
6d3351 |
+ size_t idx,
|
|
|
6d3351 |
+ char *physPortID,
|
|
|
6d3351 |
+ char **netname);
|
|
|
6d3351 |
|
|
|
6d3351 |
int virPCIGetSysfsFile(char *virPCIDeviceName,
|
|
|
6d3351 |
char **pci_sysfs_device_link)
|
|
|
6d3351 |
--
|
|
|
6d3351 |
2.14.1
|
|
|
6d3351 |
|