* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Honor vhost
designations, similar to qemu_command code paths.
* src/qemu/qemu_command.h (qemuOpenVhostNet): New prototype.
* src/qemu/qemu_command.c (qemuOpenVhostNet): Export.
---
Hmm, I just realized that it might be nice to have a --driver-name
flag in the virsh attach-interface wrapper command. Oh well, that can
be a separate patch.
src/qemu/qemu_command.c | 3 +-
src/qemu/qemu_command.h | 4 +++
src/qemu/qemu_hotplug.c | 54 ++++++++++++++++++++++++++++++++++++++++++----
3 files changed, 54 insertions(+), 7 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 198a4e2..8cf1737 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -303,12 +303,11 @@ cleanup:
}
-static int
+int
qemuOpenVhostNet(virDomainNetDefPtr net,
virBitmapPtr qemuCaps,
int *vhostfd)
{
-
*vhostfd = -1; /* assume we won't use vhost */
/* If the config says explicitly to not use vhost, return now */
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 1902472..2ae364c 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -129,6 +129,10 @@ int qemuPhysIfaceConnect(virConnectPtr conn,
const unsigned char *vmuuid,
enum virVMOperationType vmop);
+int qemuOpenVhostNet(virDomainNetDefPtr net,
+ virBitmapPtr qemuCaps,
+ int *vhostfd);
+
int qemudCanonicalizeMachine(struct qemud_driver *driver,
virDomainDefPtr def);
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 7895062..e8567ad 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -552,6 +552,8 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
qemuDomainObjPrivatePtr priv = vm->privateData;
char *tapfd_name = NULL;
int tapfd = -1;
+ char *vhostfd_name = NULL;
+ int vhostfd = -1;
char *nicstr = NULL;
char *netstr = NULL;
int ret = -1;
@@ -592,6 +594,24 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
return -1;
}
+ if (net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
+ net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
+ net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
+ /* Attempt to use vhost-net mode for these types of
+ network device */
+ if (qemuOpenVhostNet(net, qemuCaps, &vhostfd) < 0)
+ goto cleanup;
+
+ if (vhostfd >= 0 &&
+ priv->monConfig->type != VIR_DOMAIN_CHR_TYPE_UNIX) {
+ qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+ _("network device type '%s' cannot be attached:
"
+ "qemu is not using a unix socket monitor"),
+ virDomainNetTypeToString(net->type));
+ goto cleanup;
+ }
+ }
+
if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets+1) < 0)
goto no_memory;
@@ -636,15 +656,32 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
}
}
- /* FIXME - need to support vhost-net here (5th arg) */
+ if (vhostfd != -1) {
+ if (virAsprintf(&vhostfd_name, "vhostfd-%s", net->info.alias)
< 0)
+ goto no_memory;
+
+ qemuDomainObjEnterMonitorWithDriver(driver, vm);
+ if (qemuMonitorSendFileHandle(priv->mon, vhostfd_name, vhostfd) < 0) {
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+ goto try_tapfd_close;
+ }
+ qemuDomainObjExitMonitorWithDriver(driver, vm);
+
+ if (!virDomainObjIsActive(vm)) {
+ qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("guest unexpectedly quit"));
+ goto cleanup;
+ }
+ }
+
if (qemuCapsGet(qemuCaps, QEMU_CAPS_NETDEV) &&
qemuCapsGet(qemuCaps, QEMU_CAPS_DEVICE)) {
if (!(netstr = qemuBuildHostNetStr(net, ',',
- -1, tapfd_name, 0)))
+ -1, tapfd_name, vhostfd_name)))
goto try_tapfd_close;
} else {
if (!(netstr = qemuBuildHostNetStr(net, ' ',
- vlan, tapfd_name, 0)))
+ vlan, tapfd_name, vhostfd_name)))
goto try_tapfd_close;
}
@@ -666,6 +703,7 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
qemuDomainObjExitMonitorWithDriver(driver, vm);
VIR_FORCE_CLOSE(tapfd);
+ VIR_FORCE_CLOSE(vhostfd);
if (!virDomainObjIsActive(vm)) {
qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -720,6 +758,8 @@ cleanup:
VIR_FREE(netstr);
VIR_FREE(tapfd_name);
VIR_FORCE_CLOSE(tapfd);
+ VIR_FREE(vhostfd_name);
+ VIR_FORCE_CLOSE(vhostfd);
return ret;
@@ -759,10 +799,14 @@ try_tapfd_close:
if (!virDomainObjIsActive(vm))
goto cleanup;
- if (tapfd_name) {
+ if (tapfd_name || vhostfd_name) {
qemuDomainObjEnterMonitorWithDriver(driver, vm);
- if (qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0)
+ if (tapfd_name &&
+ qemuMonitorCloseFileHandle(priv->mon, tapfd_name) < 0)
VIR_WARN("Failed to close tapfd with '%s'", tapfd_name);
+ if (vhostfd_name &&
+ qemuMonitorCloseFileHandle(priv->mon, vhostfd_name) < 0)
+ VIR_WARN("Failed to close vhostfd with '%s'",
vhostfd_name);
qemuDomainObjExitMonitorWithDriver(driver, vm);
}
--
1.7.4