diff --git a/src/util/virhostdev.c b/src/util/virhostdev.c index 580f0fac06a5dc0a0c2938246f42c246f292d428..102fd85c160f8bf53aa3c84c7bee86555bc27e50 100644 --- a/src/util/virhostdev.c +++ b/src/util/virhostdev.c @@ -307,7 +307,9 @@ virHostdevIsVirtualFunction(virDomainHostdevDefPtr hostdev) static int -virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, +virHostdevNetDevice(virDomainHostdevDefPtr hostdev, + int pfNetDevIdx, + char **linkdev, int *vf) { int ret = -1; @@ -317,9 +319,10 @@ virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev, return ret; if (virPCIIsVirtualFunction(sysfs_path) == 1) { - if (virPCIGetVirtualFunctionInfo(sysfs_path, linkdev, - vf) < 0) + if (virPCIGetVirtualFunctionInfo(sysfs_path, pfNetDevIdx, + linkdev, vf) < 0) { goto cleanup; + } } else { /* In practice this should never happen, since we currently * only support assigning SRIOV VFs via parent.data.net); @@ -545,7 +548,7 @@ virHostdevRestoreNetConfig(virDomainHostdevDefPtr hostdev, return ret; } - if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0) + if (virHostdevNetDevice(hostdev, 0, &linkdev, &vf) < 0) return ret; virtPort = virDomainNetGetActualVirtPortProfile( @@ -565,6 +568,18 @@ virHostdevRestoreNetConfig(virDomainHostdevDefPtr hostdev, ret = virNetDevReadNetConfig(linkdev, vf, oldStateDir, &adminMAC, &vlan, &MAC); + if (ret < 0) { + /* see if the config was saved using the PF's "port 2" + * netdev for the file name. + */ + VIR_FREE(linkdev); + + if (virHostdevNetDevice(hostdev, 1, &linkdev, &vf) >= 0) { + ret = virNetDevReadNetConfig(linkdev, vf, stateDir, + &adminMAC, &vlan, &MAC); + } + } + if (ret == 0) { /* if a MAC was stored for the VF, we should now restore * that as the adminMAC. We have to do it this way because diff --git a/src/util/virpci.c b/src/util/virpci.c index 62a36b3801ce3b7624c148a6a52b5dfdff67317e..5ded77087aeeb1f0c0299ebcafc2ee0db562b035 100644 --- a/src/util/virpci.c +++ b/src/util/virpci.c @@ -2935,10 +2935,14 @@ virPCIGetNetName(const char *device_link_sysfs_path, int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, - char **pfname, int *vf_index) + int pfNetDevIdx, + char **pfname, + int *vf_index) { virPCIDeviceAddressPtr pf_config_address = NULL; char *pf_sysfs_device_path = NULL; + char *vfname = NULL; + char *vfPhysPortID = NULL; int ret = -1; if (virPCIGetPhysicalFunction(vf_sysfs_device_path, &pf_config_address) < 0) @@ -2957,8 +2961,28 @@ virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, goto cleanup; } - if (virPCIGetNetName(pf_sysfs_device_path, 0, NULL, pfname) < 0) + /* If the caller hasn't asked for a specific pfNetDevIdx, and VF + * is bound to a netdev, learn that netdev's phys_port_id (if + * available). This can be used to disambiguate when the PF has + * multiple netdevs. If the VF isn't bound to a netdev, then we + * return netdev[pfNetDevIdx] on the PF, which may or may not be + * correct. + */ + if (pfNetDevIdx == -1) { + if (virPCIGetNetName(vf_sysfs_device_path, 0, NULL, &vfname) < 0) + goto cleanup; + + if (vfname) { + if (virNetDevGetPhysPortID(vfname, &vfPhysPortID) < 0) + goto cleanup; + } + pfNetDevIdx = 0; + } + + if (virPCIGetNetName(pf_sysfs_device_path, + pfNetDevIdx, vfPhysPortID, pfname) < 0) { goto cleanup; + } if (!*pfname) { /* this shouldn't be possible. A VF can't exist unless its @@ -2974,6 +2998,8 @@ virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, cleanup: VIR_FREE(pf_config_address); VIR_FREE(pf_sysfs_device_path); + VIR_FREE(vfname); + VIR_FREE(vfPhysPortID); return ret; } @@ -3044,6 +3070,7 @@ virPCIGetNetName(const char *device_link_sysfs_path ATTRIBUTE_UNUSED, int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path ATTRIBUTE_UNUSED, + int pfNetDevIdx ATTRIBUTE_UNUSED, char **pfname ATTRIBUTE_UNUSED, int *vf_index ATTRIBUTE_UNUSED) { diff --git a/src/util/virpci.h b/src/util/virpci.h index adf336706b7688e0d21c1f5e8668276837b24ae5..f1fbe39e6f17edf70c0f2a0dd2aa674866de424c 100644 --- a/src/util/virpci.h +++ b/src/util/virpci.h @@ -226,7 +226,9 @@ int virPCIGetAddrString(unsigned int domain, int virPCIDeviceAddressParse(char *address, virPCIDeviceAddressPtr bdf); int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path, - char **pfname, int *vf_index); + int pfNetDevIdx, + char **pfname, + int *vf_index); int virPCIDeviceUnbind(virPCIDevicePtr dev); int virPCIDeviceRebind(virPCIDevicePtr dev);