static int
-virHostdevNetDevice(virDomainHostdevDefPtr hostdev, char **linkdev,
+virHostdevNetDevice(virDomainHostdevDefPtr hostdev,
+ int pfNetDevIdx,
+ char **linkdev,
int *vf)
{
int ret = -1;
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 <interface
goto cleanup;
}
- if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
+ if (virHostdevNetDevice(hostdev, -1, &linkdev, &vf) < 0)
goto cleanup;
if (virNetDevSaveNetConfig(linkdev, vf, stateDir, true) < 0)
if (!virHostdevIsPCINetDevice(hostdev))
return 0;
- if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
+ if (virHostdevNetDevice(hostdev, -1, &linkdev, &vf) < 0)
goto cleanup;
vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
return ret;
}
- if (virHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
+ if (virHostdevNetDevice(hostdev, 0, &linkdev, &vf) < 0)
return ret;
virtPort = virDomainNetGetActualVirtPortProfile(
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
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)
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
cleanup:
VIR_FREE(pf_config_address);
VIR_FREE(pf_sysfs_device_path);
+ VIR_FREE(vfname);
+ VIR_FREE(vfPhysPortID);
return ret;
}
int
virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path ATTRIBUTE_UNUSED,
+ int pfNetDevIdx ATTRIBUTE_UNUSED,
char **pfname ATTRIBUTE_UNUSED,
int *vf_index ATTRIBUTE_UNUSED)
{