On Thu, May 10, 2012 at 02:10:44AM +0200, Marc-André Lureau wrote: > Add element <forward> to add TCP or UDP port redirection from host to > guest in user mode networking. > --- > docs/formatdomain.html.in | 21 ++++ > docs/schemas/domaincommon.rng | 29 +++++ > src/conf/domain_conf.c | 140 ++++++++++++++++++++++ > src/conf/domain_conf.h | 23 ++++ > tests/qemuargv2xmltest.c | 3 +- > tests/qemuxml2argvdata/qemuxml2argv-net-user.xml | 2 + > 6 files changed, 217 insertions(+), 1 deletion(-) > > diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in > index d6e90f1..9c9bbf5 100644 > --- a/docs/formatdomain.html.in > +++ b/docs/formatdomain.html.in > @@ -2268,6 +2268,27 @@ > VMs to have outgoing access. > </p> > > + <p> > + Port redirections from host to guest can be added by > + providing <code>forward</code> elements that takes the > + following attributes: > + </p> > + > + <dl> > + <dt><code>type</code></dt> > + <dd>Either <code>tcp</code> (default) or <code>udp</code>.</dd> > + > + <dt><code>host_port</code></dt> > + <dd>Host port to redirect.</dd> > + > + <dt><code>guest_port</code></dt> > + <dd>Guest port to redirect to.</dd> > + > + <dt><code>host</code></dt> > + <dd>IPv4 address to bound the redirection to a specific host > + interface.</dd> > + </dl> > + > <pre> > ... > <devices> > diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng > index 34f63c3..740f5af 100644 > --- a/docs/schemas/domaincommon.rng > +++ b/docs/schemas/domaincommon.rng > @@ -1408,6 +1408,35 @@ > <value>user</value> > </attribute> > <interleave> > + <zeroOrMore> > + <element name="forward"> > + <attribute name="host_port"> > + <ref name="PortNumber"/> > + </attribute> > + <attribute name="guest_port"> > + <ref name="PortNumber"/> > + </attribute> > + <optional> > + <attribute name="type"> > + <choice> > + <value>tcp</value> > + <value>udp</value> > + </choice> > + </attribute> > + </optional> > + <optional> > + <attribute name="host"> > + <ref name="ipv4Addr"/> > + </attribute> > + </optional> > + <optional> > + <attribute name="guest"> > + <ref name="ipv4Addr"/> > + </attribute> > + </optional> > + <empty/> > + </element> > + </zeroOrMore> > <ref name="interface-options"/> > </interleave> > </group> > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 51d6cb9..4b9b644 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -650,6 +650,10 @@ VIR_ENUM_IMPL(virDomainNumatuneMemPlacementMode, > "static", > "auto"); > > +VIR_ENUM_IMPL(virDomainNetForward, VIR_DOMAIN_NET_FORWARD_TYPE_LAST, > + "tcp", > + "udp") > + > #define virDomainReportError(code, ...) \ > virReportErrorHelper(VIR_FROM_DOMAIN, code, __FILE__, \ > __FUNCTION__, __LINE__, __VA_ARGS__) > @@ -1019,8 +1023,22 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def) > VIR_FREE(def); > } > > +void > +virDomainNetForwardDefFree(virDomainNetForwardDefPtr def) > +{ > + if (!def) > + return; > + > + VIR_FREE(def->host_addr); > + VIR_FREE(def->guest_addr); > + > + VIR_FREE(def); > +} > + > void virDomainNetDefFree(virDomainNetDefPtr def) > { > + int i; > + > if (!def) > return; > > @@ -1066,6 +1084,11 @@ void virDomainNetDefFree(virDomainNetDefPtr def) > break; > > case VIR_DOMAIN_NET_TYPE_USER: > + for (i = 0; i < def->data.user.nforward; i++) > + virDomainNetForwardDefFree(def->data.user.forwards[i]); > + VIR_FREE(def->data.user.forwards); > + break; > + > case VIR_DOMAIN_NET_TYPE_LAST: > break; > } > @@ -4351,6 +4374,60 @@ error: > return ret; > } > > +static virDomainNetForwardDefPtr > +virDomainNetForwardDefParseXML(const xmlNodePtr node) > +{ > + char *type = NULL; > + char *host_port = NULL; > + char *guest_port = NULL; > + virDomainNetForwardDefPtr def; > + > + if (VIR_ALLOC(def) < 0) { > + virReportOOMError(); > + return NULL; > + } > + > + type = virXMLPropString(node, "type"); > + if (type == NULL) { > + def->type = VIR_DOMAIN_NET_FORWARD_TYPE_TCP; > + } else if ((def->type = virDomainNetForwardTypeFromString(type)) < 0) { > + virDomainReportError(VIR_ERR_INTERNAL_ERROR, > + _("unknown forward type '%s'"), type); > + goto error; > + } > + > + host_port = virXMLPropString(node, "host_port"); > + if (!host_port || > + virStrToLong_i(host_port, NULL, 10, &def->host_port) < 0) { > + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Cannot parse <forward> 'host_port' attribute")); > + goto error; > + } > + > + guest_port = virXMLPropString(node, "guest_port"); > + if (!guest_port || > + virStrToLong_i(guest_port, NULL, 10, &def->guest_port) < 0) { > + virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("Cannot parse <forward> 'guest_port' attribute")); > + goto error; > + } > + > + def->host_addr = virXMLPropString(node, "host"); > + def->guest_addr = virXMLPropString(node, "guest"); > + > +cleanup: > + VIR_FREE(type); > + VIR_FREE(host_port); > + VIR_FREE(guest_port); > + > + return def; > + > +error: > + virDomainNetForwardDefFree(def); > + def = NULL; > + goto cleanup; > +} > + > #define NET_MODEL_CHARS \ > "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ091234567890_-" > > @@ -4394,6 +4471,8 @@ virDomainNetDefParseXML(virCapsPtr caps, > virDomainActualNetDefPtr actual = NULL; > xmlNodePtr oldnode = ctxt->node; > int ret; > + int nforwards; > + xmlNodePtr *forwardNodes = NULL; > > if (VIR_ALLOC(def) < 0) { > virReportOOMError(); > @@ -4683,6 +4762,28 @@ virDomainNetDefParseXML(virCapsPtr caps, > break; > > case VIR_DOMAIN_NET_TYPE_USER: > + /* parse the <forward> elements */ > + nforwards = virXPathNodeSet("./forward", ctxt, &forwardNodes); > + if (nforwards < 0) > + goto error; > + > + if (nforwards > 0) { > + int i; > + if (VIR_ALLOC_N(def->data.user.forwards, nforwards) < 0) { > + virReportOOMError(); > + goto error; > + } > + for (i = 0; i < nforwards; i++) { > + virDomainNetForwardDefPtr fwd = > + virDomainNetForwardDefParseXML(forwardNodes[i]); > + if (fwd == NULL) > + goto error; > + def->data.user.forwards[def->data.user.nforward++] = fwd; > + } > + VIR_FREE(forwardNodes); > + } > + break; > + > case VIR_DOMAIN_NET_TYPE_LAST: > break; > } > @@ -11413,11 +11514,42 @@ error: > } > > static int > +virDomainNetForwardDefFormat(virBufferPtr buf, > + virDomainNetForwardDefPtr def) > +{ > + const char *type; > + if (!def) > + return 0; > + > + type = virDomainNetForwardTypeToString(def->type); > + if (!type) { > + virDomainReportError(VIR_ERR_INTERNAL_ERROR, > + _("unexpected net type %d"), def->type); > + return -1; > + } > + virBufferAsprintf(buf, "<forward type='%s'", type); > + > + if (def->host_addr) > + virBufferAsprintf(buf, " host='%s'", def->host_addr); > + > + virBufferAsprintf(buf, " host_port='%d'", def->host_port); > + > + if (def->guest_addr) > + virBufferAsprintf(buf, " guest='%s'", def->guest_addr); > + > + virBufferAsprintf(buf, " guest_port='%d'", def->guest_port); > + > + virBufferAddLit(buf, "/>\n"); > + return 0; > +} > + > +static int > virDomainNetDefFormat(virBufferPtr buf, > virDomainNetDefPtr def, > unsigned int flags) > { > const char *type = virDomainNetTypeToString(def->type); > + int i; > > if (!type) { > virDomainReportError(VIR_ERR_INTERNAL_ERROR, > @@ -11517,6 +11649,14 @@ virDomainNetDefFormat(virBufferPtr buf, > break; > > case VIR_DOMAIN_NET_TYPE_USER: > + virBufferAdjustIndent(buf, 6); > + for (i = 0; i < def->data.user.nforward; i++) { > + if (virDomainNetForwardDefFormat(buf, def->data.user.forwards[i]) < 0) > + return -1; > + } > + virBufferAdjustIndent(buf, -6); > + break; > + > case VIR_DOMAIN_NET_TYPE_LAST: > break; > } > diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h > index 70129fe..7fde05e 100644 > --- a/src/conf/domain_conf.h > +++ b/src/conf/domain_conf.h > @@ -768,6 +768,23 @@ struct _virDomainActualNetDef { > virNetDevBandwidthPtr bandwidth; > }; > > +enum virDomainNetForwardType { > + VIR_DOMAIN_NET_FORWARD_TYPE_TCP, > + VIR_DOMAIN_NET_FORWARD_TYPE_UDP, > + > + VIR_DOMAIN_NET_FORWARD_TYPE_LAST, > +}; > + > +typedef struct _virDomainNetForwardDef virDomainNetForwardDef; > +typedef virDomainNetForwardDef *virDomainNetForwardDefPtr; > +struct _virDomainNetForwardDef { > + int type; /* enum virDomainNetForwardType */ > + char *host_addr; > + int host_port; > + char *guest_addr; > + int guest_port; > +}; > + > /* Stores the virtual network interface configuration */ > struct _virDomainNetDef { > enum virDomainNetType type; > @@ -821,6 +838,10 @@ struct _virDomainNetDef { > virDomainHostdevDef def; > virNetDevVPortProfilePtr virtPortProfile; > } hostdev; > + struct { > + int nforward; > + virDomainNetForwardDefPtr *forwards; > + } user; > } data; > struct { > bool sndbuf_specified; > @@ -1856,6 +1877,7 @@ int virDomainDiskFindControllerModel(virDomainDefPtr def, > void virDomainControllerDefFree(virDomainControllerDefPtr def); > void virDomainFSDefFree(virDomainFSDefPtr def); > void virDomainActualNetDefFree(virDomainActualNetDefPtr def); > +void virDomainNetForwardDefFree(virDomainNetForwardDefPtr def); > void virDomainNetDefFree(virDomainNetDefPtr def); > void virDomainSmartcardDefFree(virDomainSmartcardDefPtr def); > void virDomainChrDefFree(virDomainChrDefPtr def); > @@ -2170,6 +2192,7 @@ VIR_ENUM_DECL(virDomainFSAccessMode) > VIR_ENUM_DECL(virDomainFSWrpolicy) > VIR_ENUM_DECL(virDomainNet) > VIR_ENUM_DECL(virDomainNetBackend) > +VIR_ENUM_DECL(virDomainNetForward) > VIR_ENUM_DECL(virDomainNetVirtioTxMode) > VIR_ENUM_DECL(virDomainNetInterfaceLinkState) > VIR_ENUM_DECL(virDomainChrDevice) > diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c > index 439218e..cf2862b 100644 > --- a/tests/qemuargv2xmltest.c > +++ b/tests/qemuargv2xmltest.c > @@ -207,7 +207,8 @@ mymain(void) > DO_TEST("misc-acpi"); > DO_TEST("misc-no-reboot"); > DO_TEST("misc-uuid"); > - DO_TEST("net-user"); > + /* Fixed in following commit */ > + /* 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.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml > index 37e5edf..ecefdeb 100644 > --- a/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml > +++ b/tests/qemuxml2argvdata/qemuxml2argv-net-user.xml > @@ -23,6 +23,8 @@ > <controller type='ide' index='0'/> > <interface type='user'> > <mac address='00:11:22:33:44:55'/> > + <forward type='tcp' host_port='2222' guest_port='22'/> > + <forward type='udp' host='127.0.0.1' host_port='2242' guest='10.0.2.15' guest_port='42'/> > </interface> > <memballoon model='virtio'/> > </devices> > -- > 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