[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