[libvirt] [PATCH v4 02/17] Domain conf: allow more than one IP address for net devices
Dmitry Guryanov
dguryanov at parallels.com
Tue Dec 2 13:43:15 UTC 2014
On Thursday 13 November 2014 10:33:01 Cédric Bosdonnat wrote:
> Add the possibility to have more than one IP address configured for a
> domain network interface. IP addresses can also have a prefix to define
> the corresponding netmask.
I totally agree with this patch. IP configuration must be separated from
device type and connection configuration.
ACK
> ---
> docs/formatdomain.html.in | 22 ++++
> docs/schemas/domaincommon.rng | 16 ++-
> src/conf/domain_conf.c | 149
> ++++++++++++++++++++---- src/conf/domain_conf.h |
> 15 ++-
> src/libvirt_private.syms | 1 +
> src/openvz/openvz_conf.c | 2 +-
> src/openvz/openvz_driver.c | 7 +-
> src/qemu/qemu_driver.c | 29 ++++-
> src/qemu/qemu_hotplug.c | 5 +-
> src/uml/uml_conf.c | 2 +-
> src/vbox/vbox_common.c | 6 +-
> src/xenconfig/xen_common.c | 21 ++--
> src/xenconfig/xen_sxpr.c | 18 ++-
> tests/lxcxml2xmldata/lxc-idmap.xml | 2 +
> tests/openvzutilstest.c | 2 +-
> tests/sexpr2xmldata/sexpr2xml-bridge-ipaddr.xml | 2 +-
> tests/sexpr2xmldata/sexpr2xml-net-routed.xml | 2 +-
> 17 files changed, 242 insertions(+), 59 deletions(-)
>
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index d4189e6..d414371 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -4283,6 +4283,28 @@ qemu-kvm -net nic,model=? /dev/null
> <span class="since">Since 0.9.5</span>
> </p>
>
> + <h5><a name="ipconfig">IP configuration</a></h5>
> +<pre>
> + ...
> + <devices>
> + <interface type='network'>
> + <source network='default'/>
> + <target dev='vnet0'/>
> + <b><ip address='192.168.122.5' prefix='24'/></b>
> + </interface>
> + </devices>
> + ...
> +</pre>
> +
> + <p>
> + <span class="since">Since 1.2.10</span> the network devices can be
> provided + zero or more IP addresses to set
> + on the target device. Note that some hypervisors or network device
> types + will simply ignore them or only use the first one. The
> <code>address</code> + attribute can hold either an IPv4 or IPv6
> address. The <code>prefix</code> + is not mandatory since some
> hypervisors do not handle it.
> + </p>
> +
> <h5><a name="elementVhostuser">vhost-user interface</a></h5>
>
> <p>
> diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
> index 6863ec6..cd82461 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -2295,14 +2295,24 @@
> <empty/>
> </element>
> </optional>
> - <optional>
> + <zeroOrMore>
> <element name="ip">
> <attribute name="address">
> - <ref name="ipv4Addr"/>
> + <ref name="ipAddr"/>
> </attribute>
> + <optional>
> + <attribute name="family">
> + <ref name="addr-family"/>
> + </attribute>
> + </optional>
> + <optional>
> + <attribute name="prefix">
> + <ref name="ipPrefix"/>
> + </attribute>
> + </optional>
> <empty/>
> </element>
> - </optional>
> + </zeroOrMore>
> <optional>
> <element name="script">
> <attribute name="path">
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 8c00dd1..44741a9 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -1367,6 +1367,8 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr
> def)
>
> void virDomainNetDefFree(virDomainNetDefPtr def)
> {
> + size_t i;
> +
> if (!def)
> return;
>
> @@ -1375,7 +1377,6 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
> switch (def->type) {
> case VIR_DOMAIN_NET_TYPE_ETHERNET:
> VIR_FREE(def->data.ethernet.dev);
> - VIR_FREE(def->data.ethernet.ipaddr);
> break;
>
> case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> @@ -1396,7 +1397,6 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
>
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> VIR_FREE(def->data.bridge.brname);
> - VIR_FREE(def->data.bridge.ipaddr);
> break;
>
> case VIR_DOMAIN_NET_TYPE_INTERNAL:
> @@ -1424,6 +1424,10 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
> VIR_FREE(def->ifname_guest);
> VIR_FREE(def->ifname_guest_actual);
>
> + for (i = 0; i < def->nips; i++)
> + VIR_FREE(def->ips[i]);
> + VIR_FREE(def->ips);
> +
> virDomainDeviceInfoClear(&def->info);
>
> VIR_FREE(def->filter);
> @@ -4667,6 +4671,58 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
> return ret;
> }
>
> +static virDomainNetIpDefPtr
> +virDomainNetIpParseXML(xmlNodePtr node)
> +{
> + /* Parse the prefix in every case */
> + virDomainNetIpDefPtr ip = NULL;
> + char *prefixStr = NULL;
> + unsigned int prefixValue = 0;
> + char *familyStr = NULL;
> + int family = AF_UNSPEC;
> + char *address = NULL;
> +
> + if (!(prefixStr = virXMLPropString(node, "prefix")) ||
> + (virStrToLong_ui(prefixStr, NULL, 10, &prefixValue) < 0)) {
> + // Don't shout, just warn as some old config may not have a prefix
> + VIR_WARN("Missing or invalid network prefix");
> + }
> +
> + if (!(address = virXMLPropString(node, "address"))) {
> + virReportError(VIR_ERR_INVALID_ARG, "%s",
> + _("Missing network address"));
> + goto error;
> + }
> +
> + familyStr = virXMLPropString(node, "family");
> + if (familyStr && STREQ(familyStr, "ipv4"))
> + family = AF_INET;
> + else if (familyStr && STREQ(familyStr, "ipv6"))
> + family = AF_INET6;
> + else
> + family = virSocketAddrNumericFamily(address);
> +
> + if (VIR_ALLOC(ip) < 0)
> + goto error;
> +
> + if (virSocketAddrParse(&ip->address, address, family) < 0) {
> + virReportError(VIR_ERR_INVALID_ARG,
> + _("Failed to parse IP address: '%s'"),
> + address);
> + goto error;
> + }
> + ip->prefix = prefixValue;
> +
> + return ip;
> +
> + error:
> + VIR_FREE(prefixStr);
> + VIR_FREE(familyStr);
> + VIR_FREE(address);
> + VIR_FREE(ip);
> + return NULL;
> +}
> +
> static int
> virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
> xmlXPathContextPtr ctxt,
> @@ -7077,6 +7133,31 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
> #define NET_MODEL_CHARS \
> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
>
> +
> +int
> +virDomainNetAppendIpAddress(virDomainNetDefPtr def,
> + const char *address,
> + int family,
> + unsigned int prefix)
> +{
> + virDomainNetIpDefPtr ipDef = NULL;
> + if (VIR_ALLOC(ipDef) < 0)
> + return -1;
> +
> + if (virSocketAddrParse(&ipDef->address, address, family) < 0)
> + goto error;
> + ipDef->prefix = prefix;
> +
> + if (VIR_APPEND_ELEMENT(def->ips, def->nips, ipDef) < 0)
> + goto error;
> +
> + return 0;
> +
> + error:
> + VIR_FREE(ipDef);
> + return -1;
> +}
> +
> /* Parse the XML definition for a network interface
> * @param node XML nodeset to parse for net definition
> * @return 0 on success, -1 on failure
> @@ -7124,6 +7205,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> virDomainActualNetDefPtr actual = NULL;
> xmlNodePtr oldnode = ctxt->node;
> int ret, val;
> + size_t i;
> + size_t nips = 0;
> + virDomainNetIpDefPtr *ips = NULL;
>
> if (VIR_ALLOC(def) < 0)
> return NULL;
> @@ -7212,11 +7296,14 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr
> xmlopt, xmlStrEqual(cur->name, BAD_CAST "source")) { address =
> virXMLPropString(cur, "address");
> port = virXMLPropString(cur, "port");
> - } else if (!address &&
> - (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
> - def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
> - xmlStrEqual(cur->name, BAD_CAST "ip")) {
> - address = virXMLPropString(cur, "address");
> + } else if (xmlStrEqual(cur->name, BAD_CAST "ip")) {
> + virDomainNetIpDefPtr ip = NULL;
> +
> + if (!(ip = virDomainNetIpParseXML(cur)))
> + goto error;
> +
> + if (VIR_APPEND_ELEMENT(ips, nips, ip) < 0)
> + goto error;
> } else if (!ifname &&
> xmlStrEqual(cur->name, BAD_CAST "target")) {
> ifname = virXMLPropString(cur, "dev");
> @@ -7416,10 +7503,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> def->data.ethernet.dev = dev;
> dev = NULL;
> }
> - if (address != NULL) {
> - def->data.ethernet.ipaddr = address;
> - address = NULL;
> - }
> break;
>
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> @@ -7431,10 +7514,6 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> }
> def->data.bridge.brname = bridge;
> bridge = NULL;
> - if (address != NULL) {
> - def->data.bridge.ipaddr = address;
> - address = NULL;
> - }
> break;
>
> case VIR_DOMAIN_NET_TYPE_CLIENT:
> @@ -7531,6 +7610,11 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> break;
> }
>
> + for (i = 0; i < nips; i++) {
> + if (VIR_APPEND_ELEMENT(def->ips, def->nips, ips[i]) < 0)
> + goto error;
> + }
> +
> if (script != NULL) {
> def->script = script;
> script = NULL;
> @@ -7793,6 +7877,7 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
> VIR_FREE(linkstate);
> VIR_FREE(addrtype);
> VIR_FREE(trustGuestRxFilters);
> + VIR_FREE(ips);
> virNWFilterHashTableFree(filterparams);
>
> return def;
> @@ -16753,6 +16838,30 @@ virDomainFSDefFormat(virBufferPtr buf,
> return 0;
> }
>
> +static void
> +virDomainNetIpsFormat(virBufferPtr buf, virDomainNetIpDefPtr *ips, size_t
> nips) +{
> + size_t i;
> +
> + /* Output IP addresses */
> + for (i = 0; i < nips; i++) {
> + virSocketAddrPtr address = &ips[i]->address;
> + char *ipStr = virSocketAddrFormat(address);
> + const char *familyStr = NULL;
> + if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET6))
> + familyStr = "ipv6";
> + else if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET))
> + familyStr = "ipv4";
> + virBufferAsprintf(buf, "<ip address='%s'",
> + ipStr);
> + if (familyStr)
> + virBufferAsprintf(buf, " family='%s'", familyStr);
> + if (ips[i]->prefix != 0)
> + virBufferAsprintf(buf, " prefix='%u'", ips[i]->prefix);
> + virBufferAddLit(buf, "/>\n");
> + }
> +}
> +
> static int
> virDomainHostdevDefFormatSubsys(virBufferPtr buf,
> virDomainHostdevDefPtr def,
> @@ -16980,7 +17089,6 @@ virDomainActualNetDefContentsFormat(virBufferPtr
> buf, return 0;
> }
>
> -
> /* virDomainActualNetDefFormat() - format the ActualNetDef
> * info inside an <actual> element, as required for internal storage
> * of domain status
> @@ -17217,9 +17325,6 @@ virDomainNetDefFormat(virBufferPtr buf,
> case VIR_DOMAIN_NET_TYPE_ETHERNET:
> virBufferEscapeString(buf, "<source dev='%s'/>\n",
> def->data.ethernet.dev);
> - if (def->data.ethernet.ipaddr)
> - virBufferAsprintf(buf, "<ip address='%s'/>\n",
> - def->data.ethernet.ipaddr);
> break;
>
> case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> @@ -17237,10 +17342,6 @@ virDomainNetDefFormat(virBufferPtr buf,
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> virBufferEscapeString(buf, "<source bridge='%s'/>\n",
> def->data.bridge.brname);
> - if (def->data.bridge.ipaddr) {
> - virBufferAsprintf(buf, "<ip address='%s'/>\n",
> - def->data.bridge.ipaddr);
> - }
> break;
>
> case VIR_DOMAIN_NET_TYPE_SERVER:
> @@ -17288,6 +17389,8 @@ virDomainNetDefFormat(virBufferPtr buf,
> return -1;
> }
>
> + virDomainNetIpsFormat(buf, def->ips, def->nips);
> +
> virBufferEscapeString(buf, "<script path='%s'/>\n",
> def->script);
> if (def->ifname &&
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index 530a3ca..fbf6067 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -471,6 +471,13 @@ typedef enum {
> VIR_DOMAIN_HOSTDEV_CAPS_TYPE_LAST
> } virDomainHostdevCapsType;
>
> +typedef struct _virDomainNetIpDef virDomainNetIpDef;
> +typedef virDomainNetIpDef *virDomainNetIpDefPtr;
> +struct _virDomainNetIpDef {
> + virSocketAddr address; /* ipv4 or ipv6 address */
> + unsigned int prefix; /* number of 1 bits in the net mask */
> +};
> +
> typedef struct _virDomainHostdevCaps virDomainHostdevCaps;
> typedef virDomainHostdevCaps *virDomainHostdevCapsPtr;
> struct _virDomainHostdevCaps {
> @@ -932,7 +939,6 @@ struct _virDomainNetDef {
> union {
> struct {
> char *dev;
> - char *ipaddr;
> } ethernet;
> virDomainChrSourceDefPtr vhostuser;
> struct {
> @@ -954,7 +960,6 @@ struct _virDomainNetDef {
> } network;
> struct {
> char *brname;
> - char *ipaddr;
> } bridge;
> struct {
> char *name;
> @@ -984,6 +989,8 @@ struct _virDomainNetDef {
> virNetDevVlan vlan;
> int trustGuestRxFilters; /* enum virTristateBool */
> int linkstate;
> + size_t nips;
> + virDomainNetIpDefPtr *ips;
> };
>
> /* Used for prefix of ifname of any network name generated dynamically
> @@ -2522,6 +2529,10 @@ virNetDevBandwidthPtr
> virDomainNetGetActualBandwidth(virDomainNetDefPtr iface);
> virNetDevVlanPtr virDomainNetGetActualVlan(virDomainNetDefPtr iface);
> bool virDomainNetGetActualTrustGuestRxFilters(virDomainNetDefPtr iface);
> +int virDomainNetAppendIpAddress(virDomainNetDefPtr def,
> + const char *address,
> + int family,
> + unsigned int prefix);
>
> int virDomainControllerInsert(virDomainDefPtr def,
> virDomainControllerDefPtr controller)
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> index 0864618..8d02438 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -321,6 +321,7 @@ virDomainLockFailureTypeFromString;
> virDomainLockFailureTypeToString;
> virDomainMemballoonModelTypeFromString;
> virDomainMemballoonModelTypeToString;
> +virDomainNetAppendIpAddress;
> virDomainNetDefFormat;
> virDomainNetDefFree;
> virDomainNetFind;
> diff --git a/src/openvz/openvz_conf.c b/src/openvz/openvz_conf.c
> index 856c9f5..b6fdc37 100644
> --- a/src/openvz/openvz_conf.c
> +++ b/src/openvz/openvz_conf.c
> @@ -230,7 +230,7 @@ openvzReadNetworkConf(virDomainDefPtr def,
> goto error;
>
> net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
> - if (VIR_STRDUP(net->data.ethernet.ipaddr, token) < 0)
> + if (virDomainNetAppendIpAddress(net, token, AF_UNSPEC, 0) < 0)
> goto error;
>
> if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
> diff --git a/src/openvz/openvz_driver.c b/src/openvz/openvz_driver.c
> index a0346b4..273bac1 100644
> --- a/src/openvz/openvz_driver.c
> +++ b/src/openvz/openvz_driver.c
> @@ -855,7 +855,7 @@ openvzDomainSetNetwork(virConnectPtr conn, const char
> *vpsid,
>
> if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
> (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
> - net->data.ethernet.ipaddr == NULL)) {
> + net->nips == 0)) {
> virBuffer buf = VIR_BUFFER_INITIALIZER;
> int veid = openvzGetVEID(vpsid);
>
> @@ -906,9 +906,10 @@ openvzDomainSetNetwork(virConnectPtr conn, const char
> *vpsid, virCommandAddArg(cmd, "--netif_add");
> virCommandAddArgBuffer(cmd, &buf);
> } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
> - net->data.ethernet.ipaddr != NULL) {
> + net->nips > 0) {
> /* --ipadd ip */
> - virCommandAddArgList(cmd, "--ipadd", net->data.ethernet.ipaddr,
> NULL); + char *ipStr = virSocketAddrFormat(&net->ips[0]->address); +
> virCommandAddArgList(cmd, "--ipadd", ipStr, NULL);
> }
>
> /* TODO: processing NAT and physical device */
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index acf2b9a..2863db4 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -6352,6 +6352,8 @@ static char
> *qemuConnectDomainXMLToNative(virConnectPtr conn, (brname =
> virDomainNetGetActualBridgeName(net))) {
>
> char *brnamecopy;
> + size_t j;
> +
> if (VIR_STRDUP(brnamecopy, brname) < 0)
> goto cleanup;
>
> @@ -6362,20 +6364,31 @@ static char
> *qemuConnectDomainXMLToNative(virConnectPtr conn, net->type =
> VIR_DOMAIN_NET_TYPE_ETHERNET;
> net->script = NULL;
> net->data.ethernet.dev = brnamecopy;
> - net->data.ethernet.ipaddr = NULL;
> + for (j = 0; j < net->nips; j++) {
> + VIR_FREE(net->ips[j]);
> + }
> + VIR_FREE(net->ips);
> + net->nips = 0;
> +
> } else {
> /* actualType is either NETWORK or DIRECT. In either
> * case, the best we can do is NULL everything out.
> */
> + size_t j;
> virDomainActualNetDefFree(net->data.network.actual);
> memset(net, 0, sizeof(*net));
>
> net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
> net->script = NULL;
> net->data.ethernet.dev = NULL;
> - net->data.ethernet.ipaddr = NULL;
> + for (j = 0; j < net->nips; j++) {
> + VIR_FREE(net->ips[j]);
> + }
> + VIR_FREE(net->ips);
> + net->nips = 0;
> }
> } else if (net->type == VIR_DOMAIN_NET_TYPE_DIRECT) {
> + size_t j;
> VIR_FREE(net->data.direct.linkdev);
>
> memset(net, 0, sizeof(*net));
> @@ -6383,18 +6396,24 @@ static char
> *qemuConnectDomainXMLToNative(virConnectPtr conn, net->type =
> VIR_DOMAIN_NET_TYPE_ETHERNET;
> net->script = NULL;
> net->data.ethernet.dev = NULL;
> - net->data.ethernet.ipaddr = NULL;
> + for (j = 0; j < net->nips; j++) {
> + VIR_FREE(net->ips[j]);
> + }
> + VIR_FREE(net->ips);
> + net->nips = 0;
> } else if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
> char *script = net->script;
> char *brname = net->data.bridge.brname;
> - char *ipaddr = net->data.bridge.ipaddr;
> + size_t nips = net->nips;
> + virDomainNetIpDefPtr *ips = net->ips;
>
> memset(net, 0, sizeof(*net));
>
> net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
> net->script = script;
> net->data.ethernet.dev = brname;
> - net->data.ethernet.ipaddr = ipaddr;
> + net->nips = nips;
> + net->ips = ips;
> }
>
> VIR_FREE(net->virtPortProfile);
> diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
> index 13bcd88..60a6fd9 100644
> --- a/src/qemu/qemu_hotplug.c
> +++ b/src/qemu/qemu_hotplug.c
> @@ -2101,8 +2101,9 @@ qemuDomainChangeNet(virQEMUDriverPtr driver,
> case VIR_DOMAIN_NET_TYPE_ETHERNET:
> if (STRNEQ_NULLABLE(olddev->data.ethernet.dev,
> newdev->data.ethernet.dev) ||
> - STRNEQ_NULLABLE(olddev->data.ethernet.ipaddr,
> - newdev->data.ethernet.ipaddr)) {
> + olddev->nips == 0 || newdev->nips == 0 ||
> + !virSocketAddrEqual(&olddev->ips[0]->address,
> + &newdev->ips[0]->address)) {
> needReconnect = true;
> }
> break;
> diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
> index a99e8e9..ac6a7da 100644
> --- a/src/uml/uml_conf.c
> +++ b/src/uml/uml_conf.c
> @@ -175,7 +175,7 @@ umlBuildCommandLineNet(virConnectPtr conn,
> if (def->ifname) {
> virBufferAdd(&buf, def->ifname, -1);
> }
> - if (def->data.ethernet.ipaddr) {
> + if (def->nips > 0) {
> virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> _("IP address not supported for ethernet
> interface")); goto error;
> diff --git a/src/vbox/vbox_common.c b/src/vbox/vbox_common.c
> index cd5b478..fa1e12d 100644
> --- a/src/vbox/vbox_common.c
> +++ b/src/vbox/vbox_common.c
> @@ -1307,7 +1307,11 @@ vboxAttachNetwork(virDomainDefPtr def, vboxGlobalData
> *data, IMachine *machine) } else if (def->nets[i]->type ==
> VIR_DOMAIN_NET_TYPE_BRIDGE) { VIR_DEBUG("NIC(%zu): brname: %s", i,
> def->nets[i]->data.bridge.brname); VIR_DEBUG("NIC(%zu): script: %s", i,
> def->nets[i]->script); - VIR_DEBUG("NIC(%zu): ipaddr: %s", i,
> def->nets[i]->data.bridge.ipaddr); + if (def->nets[i]->nips > 0)
> {
> + char *ipStr =
> virSocketAddrFormat(&def->nets[i]->ips[0]->address); +
> VIR_DEBUG("NIC(%zu): ipaddr: %s", i, ipStr);
> + VIR_FREE(ipStr);
> + }
> }
>
> gVBoxAPI.UIMachine.GetNetworkAdapter(machine, i, &adapter);
> diff --git a/src/xenconfig/xen_common.c b/src/xenconfig/xen_common.c
> index 32954f3..bcb3bd3 100644
> --- a/src/xenconfig/xen_common.c
> +++ b/src/xenconfig/xen_common.c
> @@ -922,12 +922,9 @@ xenParseVif(virConfPtr conf, virDomainDefPtr def)
> if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
> if (bridge[0] && VIR_STRDUP(net->data.bridge.brname,
> bridge) < 0) goto cleanup;
> - if (ip[0] && VIR_STRDUP(net->data.bridge.ipaddr, ip) < 0)
> - goto cleanup;
> - } else {
> - if (ip[0] && VIR_STRDUP(net->data.ethernet.ipaddr, ip) < 0)
> - goto cleanup;
> }
> + if (ip[0] && virDomainNetAppendIpAddress(net, ip, AF_INET, 0) <
> 0) + goto cleanup;
>
> if (script && script[0] &&
> VIR_STRDUP(net->script, script) < 0)
> @@ -1225,16 +1222,22 @@ xenFormatNet(virConnectPtr conn,
> switch (net->type) {
> case VIR_DOMAIN_NET_TYPE_BRIDGE:
> virBufferAsprintf(&buf, ",bridge=%s", net->data.bridge.brname);
> - if (net->data.bridge.ipaddr)
> - virBufferAsprintf(&buf, ",ip=%s", net->data.bridge.ipaddr);
> + if (net->nips > 0) {
> + char *ipStr = virSocketAddrFormat(&net->ips[0]->address);
> + virBufferAsprintf(&buf, ",ip=%s", ipStr);
> + VIR_FREE(ipStr);
> + }
> virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
> break;
>
> case VIR_DOMAIN_NET_TYPE_ETHERNET:
> if (net->script)
> virBufferAsprintf(&buf, ",script=%s", net->script);
> - if (net->data.ethernet.ipaddr)
> - virBufferAsprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr);
> + if (net->nips > 0) {
> + char *ipStr = virSocketAddrFormat(&net->ips[0]->address);
> + virBufferAsprintf(&buf, ",ip=%s", ipStr);
> + VIR_FREE(ipStr);
> + }
> break;
>
> case VIR_DOMAIN_NET_TYPE_NETWORK:
> diff --git a/src/xenconfig/xen_sxpr.c b/src/xenconfig/xen_sxpr.c
> index 6623ea8..caeb464 100644
> --- a/src/xenconfig/xen_sxpr.c
> +++ b/src/xenconfig/xen_sxpr.c
> @@ -565,14 +565,14 @@ xenParseSxprNets(virDomainDefPtr def,
> VIR_STRDUP(net->script, tmp2) < 0)
> goto cleanup;
> tmp = sexpr_node(node, "device/vif/ip");
> - if (VIR_STRDUP(net->data.bridge.ipaddr, tmp) < 0)
> + if (tmp && virDomainNetAppendIpAddress(net, tmp, AF_UNSPEC,
> 0) < 0) goto cleanup;
> } else {
> net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
> if (VIR_STRDUP(net->script, tmp2) < 0)
> goto cleanup;
> tmp = sexpr_node(node, "device/vif/ip");
> - if (VIR_STRDUP(net->data.ethernet.ipaddr, tmp) < 0)
> + if (tmp && virDomainNetAppendIpAddress(net, tmp, AF_UNSPEC,
> 0) < 0) goto cleanup;
> }
>
> @@ -1898,8 +1898,11 @@ xenFormatSxprNet(virConnectPtr conn,
> script = def->script;
>
> virBufferEscapeSexpr(buf, "(script '%s')", script);
> - if (def->data.bridge.ipaddr != NULL)
> - virBufferEscapeSexpr(buf, "(ip '%s')",
> def->data.bridge.ipaddr); + if (def->nips > 0) {
> + char *ipStr = virSocketAddrFormat(&def->ips[0]->address);
> + virBufferEscapeSexpr(buf, "(ip '%s')", ipStr);
> + VIR_FREE(ipStr);
> + }
> break;
>
> case VIR_DOMAIN_NET_TYPE_NETWORK:
> @@ -1932,8 +1935,11 @@ xenFormatSxprNet(virConnectPtr conn,
> if (def->script)
> virBufferEscapeSexpr(buf, "(script '%s')",
> def->script);
> - if (def->data.ethernet.ipaddr != NULL)
> - virBufferEscapeSexpr(buf, "(ip '%s')",
> def->data.ethernet.ipaddr); + if (def->nips > 0) {
> + char *ipStr = virSocketAddrFormat(&def->ips[0]->address);
> + virBufferEscapeSexpr(buf, "(ip '%s')", ipStr);
> + VIR_FREE(ipStr);
> + }
> break;
>
> case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
> diff --git a/tests/lxcxml2xmldata/lxc-idmap.xml
> b/tests/lxcxml2xmldata/lxc-idmap.xml index 946d363..d011927 100644
> --- a/tests/lxcxml2xmldata/lxc-idmap.xml
> +++ b/tests/lxcxml2xmldata/lxc-idmap.xml
> @@ -28,6 +28,8 @@
> <interface type='bridge'>
> <mac address='00:16:3e:0f:ef:8a'/>
> <source bridge='bri0'/>
> + <ip address='192.168.122.12' family='ipv4' prefix='24'/>
> + <ip address='192.168.122.13' family='ipv4' prefix='24'/>
> <target dev='veth0'/>
> <guest dev='eth2'/>
> </interface>
> diff --git a/tests/openvzutilstest.c b/tests/openvzutilstest.c
> index ed2c098..bcf48db 100644
> --- a/tests/openvzutilstest.c
> +++ b/tests/openvzutilstest.c
> @@ -95,7 +95,7 @@ testReadNetworkConf(const void *data ATTRIBUTE_UNUSED)
> " <devices>\n"
> " <interface type='ethernet'>\n"
> " <mac address='00:00:00:00:00:00'/>\n"
> - " <ip address='194.44.18.88'/>\n"
> + " <ip address='194.44.18.88' family='ipv4'/>\n"
> " </interface>\n"
> " <interface type='bridge'>\n"
> " <mac address='00:18:51:c1:05:ee'/>\n"
> diff --git a/tests/sexpr2xmldata/sexpr2xml-bridge-ipaddr.xml
> b/tests/sexpr2xmldata/sexpr2xml-bridge-ipaddr.xml index 9b5cc3a..25a29fd
> 100644
> --- a/tests/sexpr2xmldata/sexpr2xml-bridge-ipaddr.xml
> +++ b/tests/sexpr2xmldata/sexpr2xml-bridge-ipaddr.xml
> @@ -24,7 +24,7 @@
> <interface type='bridge'>
> <mac address='00:11:22:33:44:55'/>
> <source bridge='xenbr2'/>
> - <ip address='192.0.2.1'/>
> + <ip address='192.0.2.1' family='ipv4'/>
> <script path='vif-bridge'/>
> <target dev='vif6.0'/>
> </interface>
> diff --git a/tests/sexpr2xmldata/sexpr2xml-net-routed.xml
> b/tests/sexpr2xmldata/sexpr2xml-net-routed.xml index 0ab3b6d..c03e40b
> 100644
> --- a/tests/sexpr2xmldata/sexpr2xml-net-routed.xml
> +++ b/tests/sexpr2xmldata/sexpr2xml-net-routed.xml
> @@ -23,7 +23,7 @@
> </disk>
> <interface type='ethernet'>
> <mac address='00:11:22:33:44:55'/>
> - <ip address='172.14.5.6'/>
> + <ip address='172.14.5.6' family='ipv4'/>
> <script path='vif-routed'/>
> <target dev='vif6.0'/>
> </interface>
--
Dmitry Guryanov
More information about the libvir-list
mailing list