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@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/libvir-list Reviewed-By: Hu Tao <hutao@xxxxxxxxxxxxxx> -- Thanks, Hu Tao -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list