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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list