Network interfaces devices and host devices with net capabilities can
now have an IPv4 and/or an IPv6 address configured.
---
docs/formatdomain.html.in | 9 +++++
docs/schemas/domaincommon.rng | 21 ++++++++++++
src/conf/domain_conf.c | 66 ++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 4 +++
tests/lxcxml2xmldata/lxc-hostdev.xml | 2 ++
tests/lxcxml2xmldata/lxc-idmap.xml | 1 +
6 files changed, 103 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 0984145..8500f81 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4291,6 +4291,7 @@ qemu-kvm -net nic,model=? /dev/null
<source network='default'/>
<target dev='vnet0'/>
<b><ip address='192.168.122.5'
prefix='24'/></b>
+ <b><gateway ipv4='192.168.122.1'/></b>
</interface>
...
<hostdev mode='capabilities' type='net'>
@@ -4298,6 +4299,7 @@ qemu-kvm -net nic,model=? /dev/null
<interface>eth0</interface>
</source>
<b><ip address='192.168.122.6'
prefix='24'/></b>
+ <b><gateway ipv4='192.168.122.1'/></b>
</hostdev>
</devices>
@@ -4313,6 +4315,13 @@ qemu-kvm -net nic,model=? /dev/null
is not mandatory since some hypervisors do not handle it.
</p>
+ <p>
+ <span class="since">Since 1.2.10</span> a gateway element can
also be added
+ to provide the default gateway to use for the network device. This element
+ can have either or both <code>ipv4</code> or
<code>ipv6</code> attributes.
+ This is only used by the LXC driver.
+ </p>
+
<h5><a name="elementVhostuser">vhost-user
interface</a></h5>
<p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 227491f..2c6bc94 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2313,6 +2313,11 @@
<empty/>
</element>
</zeroOrMore>
+ <zeroOrMore>
+ <element name="gateway">
+ <ref name="gateway"/>
+ </element>
+ </zeroOrMore>
<optional>
<element name="script">
<attribute name="path">
@@ -3568,6 +3573,17 @@
</element>
</define>
+ <define name="gateway">
+ <interleave>
+ <attribute name="family">
+ <ref name="addr-family"/>
+ </attribute>
+ <attribute name="address">
+ <ref name="ipAddr"/>
+ </attribute>
+ </interleave>
+ </define>
+
<define name="hostdev">
<element name="hostdev">
<interleave>
@@ -3803,6 +3819,11 @@
<empty/>
</element>
</zeroOrMore>
+ <zeroOrMore>
+ <element name="gateway">
+ <ref name="gateway"/>
+ </element>
+ </zeroOrMore>
</interleave>
</define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 2477ebe..388a193 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1428,6 +1428,9 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
VIR_FREE(def->ips[i]);
VIR_FREE(def->ips);
+ VIR_FREE(def->gateway_ipv4);
+ VIR_FREE(def->gateway_ipv6);
+
virDomainDeviceInfoClear(&def->info);
VIR_FREE(def->filter);
@@ -1800,6 +1803,8 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
for (i = 0; i < def->source.caps.u.net.nips; i++)
VIR_FREE(def->source.caps.u.net.ips[i]);
VIR_FREE(def->source.caps.u.net.ips);
+ VIR_FREE(def->source.caps.u.net.gateway_ipv4);
+ VIR_FREE(def->source.caps.u.net.gateway_ipv6);
break;
}
break;
@@ -4728,6 +4733,22 @@ virDomainNetIpParseXML(xmlNodePtr node)
return NULL;
}
+static void
+virDomainNetGatewayParse(xmlNodePtr node, char **ipv4, char **ipv6) {
+ char *family = virXMLPropString(node, "family");
+ if (!*ipv4 &&
+ STREQ_NULLABLE(family, "ipv4")) {
+ char *address = virXMLPropString(node, "address");
+ *ipv4 = address;
+ }
+ if (!*ipv6 &&
+ STREQ_NULLABLE(family, "ipv6")) {
+ char *address = virXMLPropString(node, "address");
+ *ipv6 = address;
+ }
+ VIR_FREE(family);
+}
+
static int
virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
xmlXPathContextPtr ctxt,
@@ -4737,6 +4758,8 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
xmlNodePtr sourcenode;
xmlNodePtr *ipnodes = NULL;
int nipnodes;
+ xmlNodePtr *gwnodes = NULL;
+ int ngwnodes;
int ret = -1;
/* @type is passed in from the caller rather than read from the
@@ -4811,6 +4834,20 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
}
}
}
+
+ /* Look for possible gateways */
+ if ((ngwnodes = virXPathNodeSet("./gateway", ctxt, &gwnodes)) <
0)
+ goto error;
+
+ if (ngwnodes) {
+ size_t i;
+ for (i = 0; i < ngwnodes; i++) {
+
+ virDomainNetGatewayParse(gwnodes[i],
+ &def->source.caps.u.net.gateway_ipv4,
+ &def->source.caps.u.net.gateway_ipv6);
+ }
+ }
break;
default:
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4821,6 +4858,7 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
ret = 0;
error:
VIR_FREE(ipnodes);
+ VIR_FREE(gwnodes);
return ret;
}
@@ -7236,6 +7274,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
size_t i;
size_t nips = 0;
virDomainNetIpDefPtr *ips = NULL;
+ char *gateway_ipv4 = NULL;
+ char *gateway_ipv6 = NULL;
if (VIR_ALLOC(def) < 0)
return NULL;
@@ -7332,6 +7372,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (VIR_APPEND_ELEMENT(ips, nips, ip) < 0)
goto error;
+ } else if (xmlStrEqual(cur->name, BAD_CAST "gateway")) {
+ virDomainNetGatewayParse(cur, &gateway_ipv4, &gateway_ipv6);
} else if (!ifname &&
xmlStrEqual(cur->name, BAD_CAST "target")) {
ifname = virXMLPropString(cur, "dev");
@@ -7642,6 +7684,10 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
if (VIR_APPEND_ELEMENT(def->ips, def->nips, ips[i]) < 0)
goto error;
}
+ def->gateway_ipv4 = gateway_ipv4;
+ gateway_ipv4 = NULL;
+ def->gateway_ipv6 = gateway_ipv6;
+ gateway_ipv6 = NULL;
if (script != NULL) {
def->script = script;
@@ -7907,6 +7953,8 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
VIR_FREE(trustGuestRxFilters);
VIR_FREE(ips);
virNWFilterHashTableFree(filterparams);
+ VIR_FREE(gateway_ipv4);
+ VIR_FREE(gateway_ipv6);
return def;
@@ -16890,6 +16938,21 @@ virDomainNetIpsFormat(virBufferPtr buf, virDomainNetIpDefPtr
*ips, size_t nips)
}
}
+static void
+virDomainNetGatewayFormat(virBufferPtr buf,
+ const char* gateway_ipv4,
+ const char* gateway_ipv6)
+{
+ if (gateway_ipv4) {
+ virBufferAsprintf(buf, "<gateway family='ipv4'
address='%s'/>\n",
+ gateway_ipv4);
+ }
+ if (gateway_ipv6) {
+ virBufferAsprintf(buf, "<gateway family='ipv6'
address='%s'/>\n",
+ gateway_ipv6);
+ }
+}
+
static int
virDomainHostdevDefFormatSubsys(virBufferPtr buf,
virDomainHostdevDefPtr def,
@@ -17045,6 +17108,8 @@ virDomainHostdevDefFormatCaps(virBufferPtr buf,
if (def->source.caps.type == VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET) {
virDomainNetIpsFormat(buf, def->source.caps.u.net.ips,
def->source.caps.u.net.nips);
+ virDomainNetGatewayFormat(buf, def->source.caps.u.net.gateway_ipv4,
+ def->source.caps.u.net.gateway_ipv6);
}
return 0;
@@ -17424,6 +17489,7 @@ virDomainNetDefFormat(virBufferPtr buf,
}
virDomainNetIpsFormat(buf, def->ips, def->nips);
+ virDomainNetGatewayFormat(buf, def->gateway_ipv4, def->gateway_ipv6);
virBufferEscapeString(buf, "<script path='%s'/>\n",
def->script);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bbbc8da..5678960 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -493,6 +493,8 @@ struct _virDomainHostdevCaps {
char *iface;
size_t nips;
virDomainNetIpDefPtr *ips;
+ char *gateway_ipv4;
+ char *gateway_ipv6;
} net;
} u;
};
@@ -993,6 +995,8 @@ struct _virDomainNetDef {
int linkstate;
size_t nips;
virDomainNetIpDefPtr *ips;
+ char *gateway_ipv4;
+ char *gateway_ipv6;
};
/* Used for prefix of ifname of any network name generated dynamically
diff --git a/tests/lxcxml2xmldata/lxc-hostdev.xml b/tests/lxcxml2xmldata/lxc-hostdev.xml
index 0596789..6e4c8cf 100644
--- a/tests/lxcxml2xmldata/lxc-hostdev.xml
+++ b/tests/lxcxml2xmldata/lxc-hostdev.xml
@@ -37,6 +37,8 @@
</source>
<ip address='192.168.122.2' family='ipv4'/>
<ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6'
prefix='24'/>
+ <gateway family='ipv4' address='192.168.122.1'/>
+ <gateway family='ipv6'
address='2003:db8:1:0:214:1234:fe0b:3595'/>
</hostdev>
</devices>
</domain>
diff --git a/tests/lxcxml2xmldata/lxc-idmap.xml b/tests/lxcxml2xmldata/lxc-idmap.xml
index d011927..150a7d6 100644
--- a/tests/lxcxml2xmldata/lxc-idmap.xml
+++ b/tests/lxcxml2xmldata/lxc-idmap.xml
@@ -30,6 +30,7 @@
<source bridge='bri0'/>
<ip address='192.168.122.12' family='ipv4'
prefix='24'/>
<ip address='192.168.122.13' family='ipv4'
prefix='24'/>
+ <gateway family='ipv4' address='192.168.122.1'/>
<target dev='veth0'/>
<guest dev='eth2'/>
</interface>
--
2.1.2