From 8021b53f476d7a1321adc2ed32f23e5a4f8818c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Thu, 8 Aug 2019 18:55:13 +0400 Subject: [PATCH] qemu-hotplug: handle hotplugging of slirp-helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Signed-off-by: Michal Privoznik Reviewed-by: Michal Privoznik --- src/qemu/qemu_hotplug.c | 36 ++++++++++++++++++++++++++++++++---- src/qemu/qemu_monitor.c | 14 +++++++++++--- src/qemu/qemu_monitor.h | 3 ++- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c index 69eeb50a2d..7d31b712fb 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -1147,6 +1147,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, qemuDomainObjPrivatePtr priv = vm->privateData; virDomainDeviceDef dev = { VIR_DOMAIN_DEVICE_NET, { .net = net } }; virErrorPtr originalError = NULL; + VIR_AUTOFREE(char *) slirpfdName = NULL; + int slirpfd = -1; char **tapfdName = NULL; int *tapfd = NULL; size_t tapfdSize = 0; @@ -1326,7 +1328,26 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, break; case VIR_DOMAIN_NET_TYPE_USER: - /* No preparation needed. */ + if (!priv->disableSlirp && + virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NET_SOCKET_DGRAM)) { + qemuSlirpPtr slirp = qemuInterfacePrepareSlirp(driver, net); + + if (!slirp) + break; + + QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp = slirp; + + if (qemuSlirpOpen(slirp, driver, vm->def) < 0 || + qemuSlirpStart(slirp, vm, driver, net, true, NULL) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Failed to start slirp")); + goto cleanup; + } + + slirpfd = qemuSlirpGetFD(slirp); + if (virAsprintf(&slirpfdName, "slirpfd-%s", net->info.alias) < 0) + goto cleanup; + } break; case VIR_DOMAIN_NET_TYPE_SERVER: @@ -1386,7 +1407,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, if (!(netstr = qemuBuildHostNetStr(net, driver, tapfdName, tapfdSize, vhostfdName, vhostfdSize, - NULL))) + slirpfdName))) goto cleanup; qemuDomainObjEnterMonitor(driver, vm); @@ -1402,7 +1423,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, if (qemuMonitorAddNetdev(priv->mon, netstr, tapfd, tapfdName, tapfdSize, - vhostfd, vhostfdName, vhostfdSize) < 0) { + vhostfd, vhostfdName, vhostfdSize, + slirpfd, slirpfdName) < 0) { ignore_value(qemuDomainObjExitMonitor(driver, vm)); virDomainAuditNet(vm, NULL, net, "attach", false); goto try_remove; @@ -1517,6 +1539,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, VIR_FREE(charDevAlias); virObjectUnref(conn); virDomainCCWAddressSetFree(ccwaddrs); + VIR_FORCE_CLOSE(slirpfd); return ret; @@ -1526,6 +1549,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, virErrorPreserveLast(&originalError); if (virAsprintf(&netdev_name, "host%s", net->info.alias) >= 0) { + if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp) + qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net, true); qemuDomainObjEnterMonitor(driver, vm); if (charDevPlugged && qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0) @@ -2196,7 +2221,7 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver, if (guestfwd) { if (qemuMonitorAddNetdev(priv->mon, devstr, - NULL, NULL, 0, NULL, NULL, 0) < 0) + NULL, NULL, 0, NULL, NULL, 0, -1, NULL) < 0) goto exit_monitor; } else { if (qemuMonitorAddDevice(priv->mon, devstr) < 0) @@ -4669,6 +4694,9 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver, if (qemuDomainObjExitMonitor(driver, vm) < 0) goto cleanup; + if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp) + qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net, true); + virDomainAuditNet(vm, net, NULL, "detach", true); for (i = 0; i < vm->def->nnets; i++) { diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 58ad109680..aa230b3306 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2846,15 +2846,17 @@ int qemuMonitorAddNetdev(qemuMonitorPtr mon, const char *netdevstr, int *tapfd, char **tapfdName, int tapfdSize, - int *vhostfd, char **vhostfdName, int vhostfdSize) + int *vhostfd, char **vhostfdName, int vhostfdSize, + int slirpfd, char *slirpfdName) { int ret = -1; size_t i = 0, j = 0; VIR_DEBUG("netdevstr=%s tapfd=%p tapfdName=%p tapfdSize=%d" - "vhostfd=%p vhostfdName=%p vhostfdSize=%d", + "vhostfd=%p vhostfdName=%p vhostfdSize=%d" + "slirpfd=%d slirpfdName=%s", netdevstr, tapfd, tapfdName, tapfdSize, - vhostfd, vhostfdName, vhostfdSize); + vhostfd, vhostfdName, vhostfdSize, slirpfd, slirpfdName); QEMU_CHECK_MONITOR(mon); @@ -2867,6 +2869,10 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon, goto cleanup; } + if (slirpfd > 0 && + qemuMonitorSendFileHandle(mon, slirpfdName, slirpfd) < 0) + goto cleanup; + ret = qemuMonitorJSONAddNetdev(mon, netdevstr); cleanup: @@ -2879,6 +2885,8 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon, if (qemuMonitorCloseFileHandle(mon, vhostfdName[j]) < 0) VIR_WARN("failed to close device handle '%s'", vhostfdName[j]); } + if (qemuMonitorCloseFileHandle(mon, slirpfdName) < 0) + VIR_WARN("failed to close device handle '%s'", slirpfdName); } return ret; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index de85a3ba0d..70000a1c72 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -886,7 +886,8 @@ int qemuMonitorRemoveFd(qemuMonitorPtr mon, int fdset, int fd); int qemuMonitorAddNetdev(qemuMonitorPtr mon, const char *netdevstr, int *tapfd, char **tapfdName, int tapfdSize, - int *vhostfd, char **vhostfdName, int vhostfdSize); + int *vhostfd, char **vhostfdName, int vhostfdSize, + int slirpfd, char *slirpfdName); int qemuMonitorRemoveNetdev(qemuMonitorPtr mon, const char *alias); -- GitLab