The parent type for hostdev hybrid needs to be VIR_DOMAIN_DEVICE_NONE as the device is
passed into
the guest as a PCI Device.
In order to store the information of the NETDEV that is the parent of the HOSTDEV in
question we
use a new variable actualParent. This variable also helps during VF MAC address, vlan and
virtportprofile configuration.
ActualParent = Parent in case of forward mode="hostdev"
---
src/conf/domain_conf.c | 9 +++
src/conf/domain_conf.h | 1 +
src/qemu/qemu_hostdev.c | 152 +++++++++++++++++++++++++++++++++--------------
src/qemu/qemu_hotplug.c | 2 +-
4 files changed, 118 insertions(+), 46 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index c59ea00..52c00db 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4587,6 +4587,8 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
hostdev->parent.data.net = parent;
+ hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+
hostdev->actualParent.data.net = parent;
hostdev->info = &parent->info;
/* The helper function expects type to already be found and
* passed in as a string, since it is in a different place in
@@ -4607,6 +4609,9 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+ hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+
hostdev->actualParent.data.net = parent;
+
if (VIR_ALLOC(hostdev->info) < 0) {
virReportOOMError();
goto error;
@@ -4990,6 +4995,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
hostdev = &def->data.hostdev.def;
hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
hostdev->parent.data.net = def;
+ hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+
hostdev->actualParent.data.net = def;
hostdev->info = &def->info;
/* The helper function expects type to already be found and
* passed in as a string, since it is in a different place in
@@ -5011,6 +5018,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
hostdev = &def->data.hostdev.def;
hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+ hostdev->actualParent.type = VIR_DOMAIN_DEVICE_NET;
+
hostdev->actualParent.data.net = def;
if (VIR_ALLOC(hostdev->info) < 0) {
virReportOOMError();
goto error;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 171dd70..adbb777 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -377,6 +377,7 @@ struct _virDomainHostdevSubsys {
/* basic device for direct passthrough */
struct _virDomainHostdevDef {
virDomainDeviceDef parent; /* higher level Def containing this */
+ virDomainDeviceDef actualParent; /*used only in the case of hybrid hostdev*/
int mode; /* enum virDomainHostdevMode */
unsigned int managed : 1;
unsigned int ephemeral : 1;
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index 46c84b5..a060a7e 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -320,43 +320,87 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
return ret;
- vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
- virtPort = virDomainNetGetActualVirtPortProfile(
-
hostdev->parent.data.net);
- if (virtPort) {
- if (vlan) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("direct setting of the vlan tag is not allowed "
- "for hostdev devices using %s mode"),
- virNetDevVPortTypeToString(virtPort->virtPortType));
- goto cleanup;
- }
- ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
- virtPort, &hostdev->parent.data.net->mac, uuid,
- port_profile_associate);
- } else {
- /* Set only mac and vlan */
- if (vlan) {
- if (vlan->nTags != 1 || vlan->trunk) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("vlan trunking is not supported "
- "by SR-IOV network devices"));
+ if (
hostdev->parent.data.net) {
+ vlan = virDomainNetGetActualVlan(hostdev->parent.data.net);
+ virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net);
+ if (virtPort) {
+ if (vlan) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("direct setting of the vlan tag is not allowed
"
+ "for hostdev devices using %s mode"),
+ virNetDevVPortTypeToString(virtPort->virtPortType));
goto cleanup;
}
- if (vf == -1) {
+ ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
+ virtPort,
+
&hostdev->parent.data.net->mac,
+ uuid,
+ port_profile_associate);
+ } else {
+ /* Set only mac and vlan */
+ if (vlan) {
+ if (vlan->nTags != 1 || vlan->trunk) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("vlan trunking is not supported "
+ "by SR-IOV network devices"));
+ goto cleanup;
+ }
+ if (vf == -1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("vlan can only be set for SR-IOV VFs, but
"
+ "%s is not a VF"), linkdev);
+ goto cleanup;
+ }
+ vlanid = vlan->tag[0];
+ } else if (vf >= 0) {
+ vlanid = 0; /* assure any current vlan tag is reset */
+ }
+
+ ret = virNetDevReplaceNetConfig(linkdev, vf,
+ &hostdev->parent.data.net->mac,
+ vlanid, stateDir);
+ }
+ }
+ else if (
hostdev->actualParent.data.net) {
+ vlan = virDomainNetGetActualVlan(hostdev->actualParent.data.net);
+ virtPort =
virDomainNetGetActualVirtPortProfile(hostdev->actualParent.data.net);
+ if (virtPort) {
+ if (vlan) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("vlan can only be set for SR-IOV VFs, but "
- "%s is not a VF"), linkdev);
+ _("direct setting of the vlan tag is not allowed
"
+ "for hostdev devices using %s mode"),
+ virNetDevVPortTypeToString(virtPort->virtPortType));
goto cleanup;
}
- vlanid = vlan->tag[0];
- } else if (vf >= 0) {
- vlanid = 0; /* assure any current vlan tag is reset */
- }
+ ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf,
+ virtPort,
+
&hostdev->actualParent.data.net->mac,
+ uuid,
+ port_profile_associate);
+ } else {
+ /* Set only mac and vlan */
+ if (vlan) {
+ if (vlan->nTags != 1 || vlan->trunk) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("vlan trunking is not supported "
+ "by SR-IOV network devices"));
+ goto cleanup;
+ }
+ if (vf == -1) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("vlan can only be set for SR-IOV VFs, but
"
+ "%s is not a VF"), linkdev);
+ goto cleanup;
+ }
+ vlanid = vlan->tag[0];
+ } else if (vf >= 0) {
+ vlanid = 0; /* assure any current vlan tag is reset */
+ }
- ret = virNetDevReplaceNetConfig(linkdev, vf,
- &hostdev->parent.data.net->mac,
- vlanid, stateDir);
+ ret = virNetDevReplaceNetConfig(linkdev, vf,
+
&hostdev->actualParent.data.net->mac,
+ vlanid, stateDir);
+ }
}
cleanup:
VIR_FREE(linkdev);
@@ -385,14 +429,26 @@ qemuDomainHostdevNetConfigRestore(virDomainHostdevDefPtr hostdev,
if (qemuDomainHostdevNetDevice(hostdev, &linkdev, &vf) < 0)
return ret;
- virtPort = virDomainNetGetActualVirtPortProfile(
-
hostdev->parent.data.net);
- if (virtPort)
- ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
- &hostdev->parent.data.net->mac,
NULL,
- port_profile_associate);
- else
- ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+ if (
hostdev->parent.data.net) {
+ virtPort = virDomainNetGetActualVirtPortProfile(hostdev->parent.data.net);
+ if (virtPort)
+ ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
+
&hostdev->parent.data.net->mac,
+ NULL,
+ port_profile_associate);
+ else
+ ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+ }
+ if (
hostdev->actualParent.data.net) {
+ virtPort =
virDomainNetGetActualVirtPortProfile(hostdev->actualParent.data.net);
+ if (virtPort)
+ ret = qemuDomainHostdevNetConfigVirtPortProfile(linkdev, vf, virtPort,
+
&hostdev->actualParent.data.net->mac,
+ NULL,
+ port_profile_associate);
+ else
+ ret = virNetDevRestoreNetConfig(linkdev, vf, stateDir);
+ }
VIR_FREE(linkdev);
@@ -478,8 +534,10 @@ int qemuPrepareHostdevPCIDevices(struct qemud_driver *driver,
continue;
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-
hostdev->parent.data.net) {
+ if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+
hostdev->parent.data.net) ||
+ (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+ hostdev->actualParent.data.net)) {
if (qemuDomainHostdevNetConfigReplace(hostdev, uuid,
driver->stateDir) < 0) {
goto resetvfnetconfig;
@@ -568,8 +626,10 @@ inactivedevs:
resetvfnetconfig:
for (i = 0; i < last_processed_hostdev_vf; i++) {
virDomainHostdevDefPtr hostdev = hostdevs[i];
- if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-
hostdev->parent.data.net) {
+ if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+
hostdev->parent.data.net) ||
+ (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+ hostdev->actualParent.data.net)) {
qemuDomainHostdevNetConfigRestore(hostdev, driver->stateDir);
}
}
@@ -827,8 +887,10 @@ void qemuDomainReAttachHostdevDevices(struct qemud_driver *driver,
continue;
if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
continue;
- if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
-
hostdev->parent.data.net) {
+ if ((hostdev->parent.type == VIR_DOMAIN_DEVICE_NET &&
+
hostdev->parent.data.net) ||
+ (hostdev->actualParent.type == VIR_DOMAIN_DEVICE_NET &&
+ hostdev->actualParent.data.net)) {
qemuDomainHostdevNetConfigRestore(hostdev, driver->stateDir);
}
}
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index a8a904c..e8860f3 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1996,7 +1996,7 @@ qemuDomainDetachHostPciDevice(struct qemud_driver *driver,
* For SRIOV net host devices, unset mac and port profile before
* reset and reattach device
*/
- if (
detach->parent.data.net)
+ if (
detach->parent.data.net ||
detach->actualParent.data.net)
qemuDomainHostdevNetConfigRestore(detach, driver->stateDir);
pci = pciGetDevice(subsys->u.pci.domain, subsys->u.pci.bus,
--
1.7.4.4