[libvirt] [PATCH libvirt 1/2] domain: add <forward> element for user mode networking
Hu Tao
hutao at cn.fujitsu.com
Thu May 10 10:15:20 UTC 2012
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 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