[libvirt] [PATCH v2 22/23] qemu-hotplug: handle hotplugging of slirp-helper
Michal Privoznik
mprivozn at redhat.com
Fri Sep 6 11:36:11 UTC 2019
On 8/8/19 4:55 PM, marcandre.lureau at redhat.com wrote:
> From: Marc-André Lureau <marcandre.lureau at redhat.com>
>
> Signed-off-by: Marc-André Lureau <marcandre.lureau at redhat.com>
> ---
> src/qemu/qemu_hotplug.c | 33 ++++++++++++++++++++++++++++++---
> src/qemu/qemu_monitor.c | 13 ++++++++++---
> src/qemu/qemu_monitor.h | 3 ++-
> 3 files changed, 42 insertions(+), 7 deletions(-)
>
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index 43c3f0755b..fcbf7a8aa9 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -1136,6 +1136,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
> 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;
> @@ -1315,7 +1316,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:
> @@ -1391,7 +1411,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;
> @@ -1506,6 +1527,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
> VIR_FREE(charDevAlias);
> virObjectUnref(conn);
> virDomainCCWAddressSetFree(ccwaddrs);
> + VIR_FORCE_CLOSE(slirpfd);
>
> return ret;
>
> @@ -1516,6 +1538,8 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
> virErrorPreserveLast(&originalError);
> if (virAsprintf(&netdev_name, "host%s", net->info.alias) >= 0) {
> qemuDomainObjEnterMonitor(driver, vm);
> + if (QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp)
> + qemuSlirpStop(QEMU_DOMAIN_NETWORK_PRIVATE(net)->slirp, vm, driver, net, true);
This can be done outside of EnterMonitor(). qemuSlirpStop() will enter
the monitor on its own.
> if (charDevPlugged &&
> qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
> VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
> @@ -2201,7 +2225,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)
> @@ -4674,6 +4698,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 a880da3ab6..84af24958a 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
> @@ -2844,15 +2844,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);
>
> @@ -2865,6 +2867,11 @@ qemuMonitorAddNetdev(qemuMonitorPtr mon,
> goto cleanup;
> }
>
> + if (slirpfd != -1) {
> + if (qemuMonitorSendFileHandle(mon, slirpfdName, slirpfd) < 0)
> + goto cleanup;
> + }
> +
> ret = qemuMonitorJSONAddNetdev(mon, netdevstr);
>
> cleanup:
If this function fails, we need to let qemu close the slirpfd:
if (qemuMonitorCloseFileHandle(mon, slirpfdName) < 0)
VIR_WARN("failed to close device handle '%s'", slirpfdName);
Reviewed-by: Michal Privoznik <mprivozn at redhat.com>
Michal
More information about the libvir-list
mailing list