For network devices allocated from a network with <forward
mode='hostdev-hybrid'>, there is a need to add the newly minted hostdev to
the hostdevs array.
In this case we also need to call qemuPrepareHostDevices just for this
one device, as the standard call to initialize all the hostdevs that
were defined directly in the domain's configuration has already been
made by the time we allocate a device from a libvirt network, and thus
have something that needs initializing.
---
src/qemu/qemu_command.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_hostdev.c | 2 +-
src/qemu/qemu_hotplug.c | 24 ++++++++++++++++--
src/qemu/qemu_process.c | 3 +-
4 files changed, 85 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a83d6de..e5388b3 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -27,6 +27,7 @@
#include "qemu_hostdev.h"
#include "qemu_capabilities.h"
#include "qemu_bridge_filter.h"
+#include "qemu_hostdev.h"
#include "cpu/cpu.h"
#include "memory.h"
#include "logging.h"
@@ -4357,10 +4358,16 @@ qemuBuildCommandLine(virConnectPtr conn,
bool emitBootindex = false;
int usbcontroller = 0;
bool usblegacy = false;
+
+ virDomainObjPtr vm = NULL;
+ virDomainObjListPtr doms = &driver->domains;
+
uname_normalize(&ut);
virUUIDFormat(def->uuid, uuid);
+ vm = virHashLookup(doms->objs, uuid);
+
emulator = def->emulator;
/*
@@ -5309,6 +5316,60 @@ qemuBuildCommandLine(virConnectPtr conn,
continue;
}
+ if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK) {
+ virDomainHostdevDefPtr hostdev = virDomainNetGetActualHostdev(net);
+ virDomainHostdevDefPtr found;
+ if (vmop == VIR_NETDEV_VPORT_PROFILE_OP_CREATE) {
+ if (qemuAssignDeviceHostdevAlias(def, hostdev,
+ (def->nhostdevs-1)) < 0) {
+ goto error;
+ }
+
+ if (virDomainHostdevFind(def, hostdev, &found) < 0) {
+ qemuDomainObjPrivatePtr priv = vm->privateData;
+ if (qemuDomainPCIAddressEnsureAddr(priv->pciaddrs,
+ hostdev->info) < 0)
{
+ goto error;
+ }
+ if (virDomainHostdevInsert(def, hostdev) < 0) {
+ virReportOOMError();
+ goto error;
+ }
+ if (qemuPrepareHostdevPCIDevices(driver, def->name,
+ def->uuid, &hostdev,
1) < 0) {
+ goto error;
+ }
+ }
+ else {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("PCI device %04x:%02x:%02x.%x "
+ "allocated from network %s is already
"
+ "in use by domain %s"),
+ hostdev->source.subsys.u.pci.domain,
+ hostdev->source.subsys.u.pci.bus,
+ hostdev->source.subsys.u.pci.slot,
+ hostdev->source.subsys.u.pci.function,
+ net->data.network.name,
+ def->name);
+ goto error;
+ }
+ }
+ }
+
+ int tapfd = qemuPhysIfaceConnect(def, driver, net,
+ qemuCaps, vmop);
+ if (tapfd < 0)
+ goto error;
+
+ last_good_net = i;
+ virCommandTransferFD(cmd, tapfd);
+
+ if (snprintf(tapfd_name, sizeof(tapfd_name), "%d",
+ tapfd) >= sizeof(tapfd_name))
+ goto no_memory;
+ }
+
if (actualType == VIR_DOMAIN_NET_TYPE_NETWORK ||
actualType == VIR_DOMAIN_NET_TYPE_BRIDGE) {
/*
diff --git a/src/qemu/qemu_hostdev.c b/src/qemu/qemu_hostdev.c
index a060a7e..4851e11 100644
--- a/src/qemu/qemu_hostdev.c
+++ b/src/qemu/qemu_hostdev.c
@@ -362,7 +362,7 @@ qemuDomainHostdevNetConfigReplace(virDomainHostdevDefPtr hostdev,
}
}
else if (
hostdev->actualParent.data.net) {
- vlan = virDomainNetGetActualVlan(hostdev->actualParent.data.net);
+ vlan = virDomainNetGetActualVlan(hostdev->actualParent.data.net);
virtPort =
virDomainNetGetActualVirtPortProfile(hostdev->actualParent.data.net);
if (virtPort) {
if (vlan) {
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e8860f3..e26ffc9 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -694,6 +694,21 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
goto cleanup;
}
+ if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
+ ret = qemuDomainAttachHostDevice(driver, vm,
+ virDomainNetGetActualHostdev(net));
+ if (ret < 0)
+ goto cleanup;
+
+ if ((tapfd = qemuPhysIfaceConnect(vm->def, driver, net,
+ priv->qemuCaps,
+ VIR_NETDEV_VPORT_PROFILE_OP_CREATE)) < 0)
+ goto cleanup;
+ iface_connected = true;
+ if (qemuOpenVhostNet(vm->def, net, priv->qemuCaps, &vhostfd) < 0)
+ goto cleanup;
+ }
+
if (actualType == VIR_DOMAIN_NET_TYPE_BRIDGE ||
actualType == VIR_DOMAIN_NET_TYPE_NETWORK) {
/*
@@ -2109,7 +2124,8 @@ int qemuDomainDetachThisHostDevice(struct qemud_driver *driver,
VIR_WARN("Failed to restore host device labelling");
}
virDomainHostdevRemove(vm->def, idx);
- virDomainHostdevDefFree(detach);
+ if (detach->ephemeral == 0)
+ virDomainHostdevDefFree(detach);
}
return ret;
}
@@ -2199,7 +2215,8 @@ qemuDomainDetachNetDevice(struct qemud_driver *driver,
goto cleanup;
}
- if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+ if ((virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+ (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
ret = qemuDomainDetachThisHostDevice(driver, vm,
virDomainNetGetActualHostdev(detach),
-1);
@@ -2272,7 +2289,8 @@ qemuDomainDetachNetDevice(struct qemud_driver *driver,
virDomainConfNWFilterTeardown(detach);
- if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ if ((virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_DIRECT) ||
+ (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
detach->ifname, &detach->mac,
virDomainNetGetActualDirectDev(detach),
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 77d679a..112c113 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4169,7 +4169,8 @@ void qemuProcessStop(struct qemud_driver *driver,
def = vm->def;
for (i = 0; i < def->nnets; i++) {
virDomainNetDefPtr net = def->nets[i];
- if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ if ((virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) ||
+ (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
net->ifname, &net->mac,
virDomainNetGetActualDirectDev(net),
--
1.7.4.4