[libvirt] [PATCH libvirt 2/2] qemu: implement user mode port <forward>

Hu Tao hutao at cn.fujitsu.com
Thu May 10 10:15:36 UTC 2012


On Thu, May 10, 2012 at 02:10:45AM +0200, Marc-André Lureau wrote:
> Implement port forwarding for user mode networking with QEMU.
> ---
>  src/libvirt_private.syms                          |    3 +
>  src/qemu/qemu_command.c                           |  115 +++++++++++++++++++++
>  tests/qemuargv2xmltest.c                          |    3 +-
>  tests/qemuxml2argvdata/qemuxml2argv-net-user.args |    5 +-
>  4 files changed, 122 insertions(+), 4 deletions(-)
> 
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index afb308d..333284a 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -396,6 +396,9 @@ virDomainNetInsert;
>  virDomainNetRemove;
>  virDomainNetRemoveByMac;
>  virDomainNetTypeToString;
> +virDomainNetForwardDefFree;
> +virDomainNetForwardTypeFromString;
> +virDomainNetForwardTypeToString;
>  virDomainNostateReasonTypeFromString;
>  virDomainNostateReasonTypeToString;
>  virDomainNumatuneMemModeTypeFromString;
> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 720f5b4..82c041c 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -2837,6 +2837,22 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
>              virBufferAsprintf(&buf, ",sndbuf=%lu", net->tune.sndbuf);
>      }
>  
> +    if (netType == VIR_DOMAIN_NET_TYPE_USER) {
> +        int i;
> +        for (i = 0; i < net->data.user.nforward; ++i) {
> +            virDomainNetForwardDefPtr fwd = net->data.user.forwards[i];
> +            const char *type = virDomainNetForwardTypeToString(fwd->type);
> +            if (!type) {
> +                qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                                "%s", _("Invalid forward type"));
> +                return NULL;
> +            }
> +            virBufferAsprintf(&buf, ",hostfwd=%s:%s:%d-%s:%d", type,
> +                              fwd->host_addr ? fwd->host_addr : "", fwd->host_port,
> +                              fwd->guest_addr ? fwd->guest_addr : "", fwd->guest_port);
> +        }
> +    }
> +
>      if (virBufferError(&buf)) {
>          virBufferFreeAndReset(&buf);
>          virReportOOMError();
> @@ -6704,6 +6720,82 @@ qemuFindNICForVLAN(int nnics,
>  }
>  
>  
> +static virDomainNetForwardDefPtr
> +qemuParseNetForward(char *val)
> +{
> +    char *type, *host, *guest, *port;
> +    virDomainNetForwardDefPtr def;
> +
> +    if (VIR_ALLOC(def) < 0) {
> +        virReportOOMError();
> +        return NULL;
> +    }
> +
> +    type = val;
> +    host = strchr(type, ':');
> +    if (!host) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                        _("cannot parse hostfwd host '%s'"), val);
> +        goto error;
> +    }
> +    *host = '\0';
> +    host++;
> +    guest = strchr(host, '-');
> +    if (!guest) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                        _("cannot parse hostfwd guest '%s'"), val);
> +        goto error;
> +    }
> +    *guest = '\0';
> +    guest++;
> +
> +    if (STREQ(type, "")) {
> +        def->type = VIR_DOMAIN_NET_FORWARD_TYPE_TCP;
> +    } else if ((def->type = virDomainNetForwardTypeFromString(type)) < 0) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR,
> +                        _("unknown forward type '%s'"), type);
> +        goto error;
> +    }
> +
> +    port = strchr(host, ':');
> +    if (!port) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("Missing host port"));
> +        goto error;
> +    }
> +    *port = '\0';
> +    port++;
> +    if (!STREQ(host, ""))
> +        def->host_addr = strdup(host);
> +    if (virStrToLong_i(port, NULL, 10, &def->host_port) < 0) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("Cannot parse host port"));
> +        goto error;
> +    }
> +
> +    port = strchr(guest, ':');
> +    if (!port) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("Missing guest port"));
> +        goto error;
> +    }
> +    *port = '\0';
> +    port++;
> +    if (!STREQ(guest, ""))
> +        def->guest_addr = strdup(guest);
> +    if (virStrToLong_i(port, NULL, 10, &def->guest_port) < 0) {
> +        qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> +                        _("Cannot parse guest port"));
> +        goto error;
> +    }
> +
> +    return def;
> +
> +error:
> +    virDomainNetForwardDefFree(def);
> +    return NULL;
> +}
> +
>  /*
>   * Tries to parse a QEMU -net backend argument. Gets given
>   * a list of all known -net frontend arguments to try and
> @@ -6723,6 +6815,7 @@ qemuParseCommandLineNet(virCapsPtr caps,
>      int wantvlan = 0;
>      const char *tmp;
>      int genmac = 1;
> +    int nforward = 0;
>      int i;
>  
>      tmp = strchr(val, ',');
> @@ -6769,9 +6862,31 @@ qemuParseCommandLineNet(virCapsPtr caps,
>                     STREQ(keywords[i], "ifname")) {
>              def->ifname = values[i];
>              values[i] = NULL;
> +        } else if (def->type == VIR_DOMAIN_NET_TYPE_USER &&
> +                   STREQ(keywords[i], "hostfwd")) {
> +            nforward++;
>          }
>      }
>  
> +    if (nforward > 0) {
> +        if (VIR_ALLOC_N(def->data.user.forwards, nforward) < 0) {
> +            virReportOOMError();
> +            goto cleanup;
> +        }
> +
> +        for (i = 0 ; i < nkeywords ; i++) {
> +            virDomainNetForwardDefPtr fwd;
> +            if (def->type != VIR_DOMAIN_NET_TYPE_USER ||
> +                !STREQ(keywords[i], "hostfwd"))
> +                continue;
> +
> +            if ((fwd = qemuParseNetForward(values[i])) == NULL)
> +                goto cleanup;
> +
> +            def->data.user.forwards[def->data.user.nforward] = fwd;
> +            def->data.user.nforward++;
> +        }
> +    }
>  
>      /* Done parsing the nic backend. Now to try and find corresponding
>       * frontend, based off vlan number. NB this assumes a 1-1 mapping
> diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
> index cf2862b..439218e 100644
> --- a/tests/qemuargv2xmltest.c
> +++ b/tests/qemuargv2xmltest.c
> @@ -207,8 +207,7 @@ mymain(void)
>      DO_TEST("misc-acpi");
>      DO_TEST("misc-no-reboot");
>      DO_TEST("misc-uuid");
> -    /* Fixed in following commit */
> -    /* DO_TEST("net-user"); */
> +    DO_TEST("net-user");
>      DO_TEST("net-virtio");
>      DO_TEST("net-eth");
>      DO_TEST("net-eth-ifname");
> diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-user.args b/tests/qemuxml2argvdata/qemuxml2argv-net-user.args
> index 093ff01..db31e95 100644
> --- a/tests/qemuxml2argvdata/qemuxml2argv-net-user.args
> +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user.args
> @@ -1,5 +1,6 @@
>  LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \
>  pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait \
>  -no-acpi -boot c -hda /dev/HostVG/QEMUGuest1 -net nic,\
> -macaddr=00:11:22:33:44:55,vlan=0 -net user,vlan=0 -serial none -parallel none \
> --usb
> +macaddr=00:11:22:33:44:55,vlan=0 \
> +-net user,vlan=0,hostfwd=tcp::2222-:22,hostfwd=udp:127.0.0.1:2242-10.0.2.15:42 \
> +-serial none -parallel none -usb
> -- 
> 1.7.10.1
> 
> --
> libvir-list mailing list
> libvir-list at redhat.com
> https://www.redhat.com/mailman/listinfo/libvir-list

Reviewed-By: Hu Tao <hutao at cn.fujitsu.com>

-- 
Thanks,
Hu Tao




More information about the libvir-list mailing list