In this mode the guest contains a Virtual network device along with a
SRIOV VF passed through to the guest as a pci device.
---
src/conf/domain_conf.c | 38 ++++++++++++++++++++++++++++++++++++--
src/conf/domain_conf.h | 5 +++++
src/libvirt_private.syms | 1 +
src/util/pci.c | 2 +-
src/util/pci.h | 2 ++
src/util/virnetdev.c | 40 ++++++++++++++++++++++++++++++++++++++++
src/util/virnetdev.h | 6 ++++++
7 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d8ab40c..c59ea00 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1022,6 +1022,7 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
virDomainHostdevDefClear(&def->data.hostdev.def);
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+ VIR_FREE(def->data.hostdev.linkdev);
virDomainHostdevDefClear(&def->data.hostdev.def);
break;
default:
@@ -1077,6 +1078,7 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
break;
case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+ VIR_FREE(def->data.hostdev.linkdev);
virDomainHostdevDefClear(&def->data.hostdev.def);
break;
@@ -4687,6 +4689,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
char *mode = NULL;
char *linkstate = NULL;
char *addrtype = NULL;
+ char *pfname = NULL;
virNWFilterHashTablePtr filterparams = NULL;
virDomainActualNetDefPtr actual = NULL;
xmlNodePtr oldnode = ctxt->node;
@@ -5024,6 +5027,27 @@ virDomainNetDefParseXML(virCapsPtr caps,
hostdev, flags) < 0) {
goto error;
}
+
+ if (hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
+ if
(virNetDevGetPhysicalFunctionFromVfPciAddr(hostdev->source.subsys.u.pci.domain,
+
hostdev->source.subsys.u.pci.bus,
+
hostdev->source.subsys.u.pci.slot,
+
hostdev->source.subsys.u.pci.function,
+ &pfname) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Could not get Physical Function of the
hostdev"));
+ goto error;
+ }
+ }
+ if (pfname != NULL)
+ def->data.hostdev.linkdev = strdup(pfname);
+ else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Linkdev is required in %s mode"),
+ virDomainNetTypeToString(def->type));
+ goto error;
+ }
+ def->data.hostdev.mode = VIR_NETDEV_MACVLAN_MODE_BRIDGE;
break;
case VIR_DOMAIN_NET_TYPE_USER:
@@ -14664,11 +14688,16 @@ virDomainNetGetActualDirectDev(virDomainNetDefPtr iface)
{
if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
return iface->data.direct.linkdev;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)
+ return iface->data.hostdev.linkdev;
if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
return NULL;
if (!iface->data.network.actual)
return NULL;
- return iface->data.network.actual->data.direct.linkdev;
+ if (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)
+ return iface->data.network.actual->data.hostdev.linkdev;
+ else
+ return iface->data.network.actual->data.direct.linkdev;
}
int
@@ -14676,11 +14705,16 @@ virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
{
if (iface->type == VIR_DOMAIN_NET_TYPE_DIRECT)
return iface->data.direct.mode;
+ if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)
+ return iface->data.hostdev.mode;
if (iface->type != VIR_DOMAIN_NET_TYPE_NETWORK)
return 0;
if (!iface->data.network.actual)
return 0;
- return iface->data.network.actual->data.direct.mode;
+ if (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)
+ return iface->data.network.actual->data.hostdev.mode;
+ else
+ return iface->data.network.actual->data.direct.mode;
}
virDomainHostdevDefPtr
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 156eb32..171dd70 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -44,6 +44,7 @@
# include "virnetdevopenvswitch.h"
# include "virnetdevbandwidth.h"
# include "virnetdevvlan.h"
+# include "virnetdev.h"
# include "virobject.h"
# include "device_conf.h"
@@ -778,6 +779,8 @@ struct _virDomainActualNetDef {
int mode; /* enum virMacvtapMode from util/macvtap.h */
} direct;
struct {
+ char *linkdev;
+ int mode;
virDomainHostdevDef def;
} hostdev;
} data;
@@ -833,6 +836,8 @@ struct _virDomainNetDef {
int mode; /* enum virMacvtapMode from util/macvtap.h */
} direct;
struct {
+ char *linkdev;
+ int mode;
virDomainHostdevDef def;
} hostdev;
} data;
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 10af063..2d06cc3 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1399,6 +1399,7 @@ virNetDevGetMTU;
virNetDevGetPhysicalFunction;
virNetDevGetVLanID;
virNetDevGetVirtualFunctionIndex;
+virNetDevGetPhysicalFunctionFromVfPciAddr;
virNetDevGetVirtualFunctionInfo;
virNetDevGetVirtualFunctions;
virNetDevIsOnline;
diff --git a/src/util/pci.c b/src/util/pci.c
index 0742d07..ba8fffc 100644
--- a/src/util/pci.c
+++ b/src/util/pci.c
@@ -802,7 +802,7 @@ pciDriverFile(char **buffer, const char *driver, const char *file)
return 0;
}
-static int
+int
pciDeviceFile(char **buffer, const char *device, const char *file)
{
VIR_FREE(*buffer);
diff --git a/src/util/pci.h b/src/util/pci.h
index 8bbab07..936fee4 100644
--- a/src/util/pci.h
+++ b/src/util/pci.h
@@ -116,6 +116,8 @@ int pciConfigAddressToSysfsFile(struct pci_config_address *dev,
int pciDeviceNetName(char *device_link_sysfs_path, char **netname);
+int pciDeviceFile(char **buffer, const char *device, const char *file);
+
int pciSysfsFile(char *pciDeviceName, char **pci_sysfs_device_link)
ATTRIBUTE_RETURN_CHECK;
diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
index f622f5d..4d4fcb1 100644
--- a/src/util/virnetdev.c
+++ b/src/util/virnetdev.c
@@ -1097,6 +1097,46 @@ virNetDevGetVirtualFunctionIndex(const char *pfname, const char
*vfname,
}
/**
+ * virNetDevGetPhyscialFunctionFromVfPciAddr
+ *
+ * @domain : Domain part of VF PCI addr
+ * @bus : Bus part of VF PCI addr
+ * @slot : Slot part of VF PCI addr
+ * @function : Function part of VF PCI addr
+ * @pfname : Contains sriov physical function for Vf upon
+ * successful return
+ *
+ * Returns 0 on success, -1 on failure
+ *
+ */
+int
+virNetDevGetPhysicalFunctionFromVfPciAddr(unsigned domain,
+ unsigned bus,
+ unsigned slot,
+ unsigned function,
+ char **pfname)
+{
+ char *pciConfigAddr = NULL;
+ char *physfn_sysfs_path = NULL;
+ int ret = -1;
+
+ if (pciGetDeviceAddrString(domain, bus, slot, function,
+ &pciConfigAddr) < 0) {
+ goto cleanup;
+ }
+ if (pciDeviceFile(&physfn_sysfs_path, pciConfigAddr, "physfn") < 0)
{
+ goto cleanup;
+ }
+ ret = pciDeviceNetName(physfn_sysfs_path, pfname);
+
+cleanup:
+ VIR_FREE(pciConfigAddr);
+ VIR_FREE(physfn_sysfs_path);
+
+ return ret;
+}
+
+/**
* virNetDevGetPhysicalFunction
*
* @ifname : name of the physical function interface name
diff --git a/src/util/virnetdev.h b/src/util/virnetdev.h
index 705ad9c..2e102f2 100644
--- a/src/util/virnetdev.h
+++ b/src/util/virnetdev.h
@@ -99,6 +99,12 @@ int virNetDevGetVirtualFunctionIndex(const char *pfname, const char
*vfname,
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
ATTRIBUTE_RETURN_CHECK;
+int virNetDevGetPhysicalFunctionFromVfPciAddr(unsigned domain, unsigned bus,
+ unsigned slot, unsigned function,
+ char **pfname)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3)
+ ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK;
+
int virNetDevGetPhysicalFunction(const char *ifname, char **pfname)
ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
--
1.7.4.4