From: Laine Stump Date: Thu, 9 Jun 2016 19:35:08 +0000 (-0400) Subject: conf: support host-side IP/route information in X-Git-Tag: v2.1.0-rc1~260 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=98fa8f3ef6b3ef4751021505a804bfa4647634b5;p=thirdparty%2Flibvirt.git conf: support host-side IP/route information in This is place as a sub-element of , where other aspects of the host-side connection to the network device are located (network or bridge name, udp listen port, etc). It's a bit odd that the interface we're configuring with this info is itself named in , but that ship sailed long ago: In practice, this will likely only be useful for type='ethernet', so its presence in any other type of interface is currently forbidden in the generic device Validate function (but it's been put into the general population of virDomainNetDef rather than the ethernet-specific union member so that 1) we can more easily add the capability to other types if needed, and 2) we can retain the info when set to an invalid interface type all the way through to validation and report a proper error, rather than just ignoring it (which is currently what happens for many other type-specific settings). (NB: The already-existing configuration of IP info for the guest-side of interfaces is in subelements directly under , and the name of the guest-side interface (when configurable) is in ). (This patch had been pushed earlier in commit fe6a77898a38f491403a70cc49925a584101daee, but was reverted in commit d658456530c1010a49f45865613ed361a0fcc5b4 because it had been accidentally pushed during the freeze for release 2.0.0) --- diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 2347ed9b40..ee6d5e875f 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -5015,6 +5015,32 @@ qemu-kvm -net nic,model=? /dev/null definitions. This is used by the LXC driver.

+
+  ...
+  <devices>
+    <interface type='ethernet'>
+      <source/>
+        <ip address='192.168.123.1' prefix='24'/>
+        <ip address='10.0.0.10' prefix='24' peer='192.168.122.5'/>
+        <route family='ipv4' address='192.168.42.0' prefix='24' gateway='192.168.123.4'/>
+      <source/>
+      ...
+    </interface>
+    ...
+  </devices>
+  ...
+
+ +

+ Since 2.1.0 network devices of type + "ethernet" can optionally be provided one or more IP addresses + and one or more routes to set on the host side of the + network device. These are configured as subelements of + the <source> element of the interface, and + have the same attributes as the similarly named elements used to + configure the guest side of the interface (described above). +

+
vhost-user interface

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 59c1155e2c..cba2d1223e 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2142,7 +2142,7 @@ - + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 27bf7b9287..9f7b90688a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -1798,6 +1798,7 @@ virDomainNetDefClear(virDomainNetDefPtr def) VIR_FREE(def->ifname_guest_actual); virNetDevIPInfoClear(&def->guestIP); + virNetDevIPInfoClear(&def->hostIP); virDomainDeviceInfoClear(&def->info); VIR_FREE(def->filter); @@ -4552,6 +4553,23 @@ virDomainRedirdevDefValidate(const virDomainDef *def, } +static int +virDomainNetDefValidate(const virDomainNetDef *net) +{ + if ((net->hostIP.nroutes || net->hostIP.nips) && + net->type != VIR_DOMAIN_NET_TYPE_ETHERNET) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Invalid attempt to set network interface " + "host-side IP route and/or address info on " + "interface of type '%s'. This is only supported " + "on interfaces of type 'ethernet'"), + virDomainNetTypeToString(net->type)); + return -1; + } + return 0; +} + + static int virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, const virDomainDef *def) @@ -4563,9 +4581,11 @@ virDomainDeviceDefValidateInternal(const virDomainDeviceDef *dev, case VIR_DOMAIN_DEVICE_REDIRDEV: return virDomainRedirdevDefValidate(def, dev->data.redirdev); + case VIR_DOMAIN_DEVICE_NET: + return virDomainNetDefValidate(dev->data.net); + case VIR_DOMAIN_DEVICE_LEASE: case VIR_DOMAIN_DEVICE_FS: - case VIR_DOMAIN_DEVICE_NET: case VIR_DOMAIN_DEVICE_INPUT: case VIR_DOMAIN_DEVICE_SOUND: case VIR_DOMAIN_DEVICE_VIDEO: @@ -8945,6 +8965,15 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt, cur = node->children; while (cur != NULL) { if (cur->type == XML_ELEMENT_NODE) { + if (xmlStrEqual(cur->name, BAD_CAST "source")) { + xmlNodePtr tmpnode = ctxt->node; + + ctxt->node = cur; + if (virDomainNetIPInfoParseXML(_("interface host IP"), + ctxt, &def->hostIP) < 0) + goto error; + ctxt->node = tmpnode; + } if (!macaddr && xmlStrEqual(cur->name, BAD_CAST "mac")) { macaddr = virXMLPropString(cur, "address"); } else if (!network && @@ -20643,6 +20672,7 @@ virDomainNetDefFormat(virBufferPtr buf, { unsigned int actualType = virDomainNetGetActualType(def); bool publicActual = false; + int sourceLines = 0; const char *typeStr; virDomainHostdevDefPtr hostdef = NULL; char macstr[VIR_MAC_STRING_BUFLEN]; @@ -20712,15 +20742,7 @@ virDomainNetDefFormat(virBufferPtr buf, def->data.network.name); virBufferEscapeString(buf, " portgroup='%s'", def->data.network.portgroup); - virBufferAddLit(buf, "/>\n"); - - /* ONLY for internal status storage - format the ActualNetDef - * as a subelement of so that no persistent config - * data is overwritten. - */ - if ((flags & VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET) && - (virDomainActualNetDefFormat(buf, def, flags) < 0)) - return -1; + sourceLines++; break; case VIR_DOMAIN_NET_TYPE_ETHERNET: @@ -20734,13 +20756,16 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, " mode='%s'", def->data.vhostuser->data.nix.listen ? "server" : "client"); - virBufferAddLit(buf, "/>\n"); + sourceLines++; } break; case VIR_DOMAIN_NET_TYPE_BRIDGE: - virBufferEscapeString(buf, "\n", - def->data.bridge.brname); + if (def->data.bridge.brname) { + virBufferEscapeString(buf, "data.bridge.brname); + sourceLines++; + } break; case VIR_DOMAIN_NET_TYPE_SERVER: @@ -20755,25 +20780,27 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferAsprintf(buf, "data.socket.port); } + sourceLines++; - if (def->type != VIR_DOMAIN_NET_TYPE_UDP) { - virBufferAddLit(buf, "/>\n"); + if (def->type != VIR_DOMAIN_NET_TYPE_UDP) break; - } virBufferAddLit(buf, ">\n"); + sourceLines++; virBufferAdjustIndent(buf, 2); virBufferAsprintf(buf, "\n", def->data.socket.localaddr, def->data.socket.localport); virBufferAdjustIndent(buf, -2); - virBufferAddLit(buf, "\n"); break; case VIR_DOMAIN_NET_TYPE_INTERNAL: - virBufferEscapeString(buf, "\n", - def->data.internal.name); + if (def->data.internal.name) { + virBufferEscapeString(buf, "data.internal.name); + sourceLines++; + } break; case VIR_DOMAIN_NET_TYPE_DIRECT: @@ -20781,7 +20808,7 @@ virDomainNetDefFormat(virBufferPtr buf, def->data.direct.linkdev); virBufferAsprintf(buf, " mode='%s'", virNetDevMacVLanModeTypeToString(def->data.direct.mode)); - virBufferAddLit(buf, "/>\n"); + sourceLines++; break; case VIR_DOMAIN_NET_TYPE_HOSTDEV: @@ -20796,12 +20823,44 @@ virDomainNetDefFormat(virBufferPtr buf, break; } + /* if sourceLines == 0 - no info at all so far + * sourceLines == 1 - first line written, no terminating ">" + * sourceLines > 1 - multiple lines, including subelements + */ + if (def->hostIP.nips || def->hostIP.nroutes) { + if (sourceLines == 0) { + virBufferAddLit(buf, "\n"); + sourceLines += 2; + } else if (sourceLines == 1) { + virBufferAddLit(buf, ">\n"); + sourceLines++; + } + virBufferAdjustIndent(buf, 2); + if (virDomainNetIPInfoFormat(buf, &def->hostIP) < 0) + return -1; + virBufferAdjustIndent(buf, -2); + } + if (sourceLines == 1) + virBufferAddLit(buf, "/>\n"); + else if (sourceLines > 1) + virBufferAddLit(buf, "\n"); + if (virNetDevVlanFormat(&def->vlan, buf) < 0) return -1; if (virNetDevVPortProfileFormat(def->virtPortProfile, buf) < 0) return -1; if (virNetDevBandwidthFormat(def->bandwidth, buf) < 0) return -1; + + /* ONLY for internal status storage - format the ActualNetDef + * as a subelement of so that no persistent config + * data is overwritten. + */ + if (def->type == VIR_DOMAIN_NET_TYPE_NETWORK && + (flags & VIR_DOMAIN_DEF_FORMAT_ACTUAL_NET) && + (virDomainActualNetDefFormat(buf, def, flags) < 0)) + return -1; + } if (virDomainNetIPInfoFormat(buf, &def->guestIP) < 0) @@ -20810,6 +20869,7 @@ virDomainNetDefFormat(virBufferPtr buf, virBufferEscapeString(buf, "