Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP1:GA
libvirt.1263
c9a641f1-domain-routes.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File c9a641f1-domain-routes.patch of Package libvirt.1263
From c9a641f1e51def862e7d160b23440252f220149b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com> Date: Thu, 24 Jul 2014 12:16:28 +0200 Subject: [PATCH 12/17] Domain network devices can now have a <route> element Network interfaces devices and host devices with net capabilities can now have IPv4 and/or an IPv6 routes configured. --- docs/formatdomain.html.in | 19 ++++- docs/schemas/domaincommon.rng | 31 ++++++++ src/conf/domain_conf.c | 135 ++++++++++++++++++++++++++++++++++- src/conf/domain_conf.h | 12 ++++ src/util/virnetdev.c | 31 +++++++- src/util/virnetdev.h | 2 +- src/util/virsocketaddr.h | 2 + tests/lxcxml2xmldata/lxc-hostdev.xml | 2 + tests/lxcxml2xmldata/lxc-idmap.xml | 2 + 9 files changed, 230 insertions(+), 6 deletions(-) Index: libvirt-1.2.5/docs/formatdomain.html.in =================================================================== --- libvirt-1.2.5.orig/docs/formatdomain.html.in +++ libvirt-1.2.5/docs/formatdomain.html.in @@ -3935,14 +3935,18 @@ qemu-kvm -net nic,model=? /dev/null <interface type='network'> <source network='default'/> <target dev='vnet0'/> - <b><ip family='ipv4' address='192.168.122.5' prefix='24'/></b> + <b><ip address='192.168.122.5' prefix='24'/></b> + <b><route family='ipv4' address='192.168.122.0' prefix='24' via='192.168.122.1'/></b> + <b><route family='ipv4' via='192.168.122.1'/></b> </interface> ... <hostdev mode='capabilities' type='net'> <source> <interface>eth0</interface> </source> - <b><ip family='ipv4' address='192.168.122.6' prefix='24'/></b> + <b><ip address='192.168.122.6' prefix='24'/></b> + <b><route family='ipv4' address='192.168.122.0' prefix='24' via='192.168.122.1'/></b> + <b><route family='ipv4' via='192.168.122.1'/></b> </hostdev> </devices> @@ -3959,6 +3963,17 @@ 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.12</span> route elements can also be added + to define the network routes to use for the network device. This element + has a <code>family</code> attribute set either to <code>ipv4</code> or + <code>ipv6</code>, a mandatory <code>via</code> attribute defining the + IP address to route throught and optional <code>address</code> and <code>prefix</code> + attributes defining the target network range. If those aren't given, then + a default route will be set. + This is only used by the LXC driver. + </p> + <h4><a name="elementsInput">Input devices</a></h4> <p> Index: libvirt-1.2.5/docs/schemas/domaincommon.rng =================================================================== --- libvirt-1.2.5.orig/docs/schemas/domaincommon.rng +++ libvirt-1.2.5/docs/schemas/domaincommon.rng @@ -2207,6 +2207,11 @@ <empty/> </element> </zeroOrMore> + <zeroOrMore> + <element name="route"> + <ref name="route"/> + </element> + </zeroOrMore> <optional> <element name="script"> <attribute name="path"> @@ -3383,6 +3388,27 @@ </element> </define> + <define name="route"> + <interleave> + <attribute name="family"> + <ref name="addr-family"/> + </attribute> + <attribute name="via"> + <ref name="ipAddr"/> + </attribute> + <optional> + <attribute name="address"> + <ref name="ipAddr"/> + </attribute> + </optional> + <optional> + <attribute name="prefix"> + <ref name="ipPrefix"/> + </attribute> + </optional> + </interleave> + </define> + <define name="hostdev"> <element name="hostdev"> <interleave> @@ -3579,6 +3605,11 @@ <empty/> </element> </zeroOrMore> + <zeroOrMore> + <element name="route"> + <ref name="route"/> + </element> + </zeroOrMore> </interleave> </define> Index: libvirt-1.2.5/src/conf/domain_conf.c =================================================================== --- libvirt-1.2.5.orig/src/conf/domain_conf.c +++ libvirt-1.2.5/src/conf/domain_conf.c @@ -1422,7 +1422,11 @@ void virDomainNetDefFree(virDomainNetDef VIR_FREE(def->ips[i]); VIR_FREE(def->ips); - virDomainDeviceInfoClear(&def->info); + for (i = 0; i < def->nroutes; i++) + VIR_FREE(def->routes[i]); + VIR_FREE(def->routes); + + virDomainDeviceInfoClear(&def->info); VIR_FREE(def->filter); virNWFilterHashTableFree(def->filterparams); @@ -1771,6 +1775,9 @@ void virDomainHostdevDefClear(virDomainH 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); + for (i = 0; i < def->source.caps.u.net.nroutes; i++) + VIR_FREE(def->source.caps.u.net.routes[i]); + VIR_FREE(def->source.caps.u.net.routes); break; } break; @@ -4458,6 +4465,64 @@ virDomainNetIpParseXML(xmlNodePtr node) return NULL; } +static virDomainNetRouteDefPtr +virDomainNetRouteParse(xmlNodePtr node) +{ + virDomainNetRouteDefPtr route = NULL; + char *familyStr = NULL; + int family = AF_UNSPEC; + char *via = NULL; + char *to = NULL; + char *prefixStr = NULL; + + to = virXMLPropString(node, "address"); + if (!(via = virXMLPropString(node, "via"))) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("Missing route 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(via); + + if (VIR_ALLOC(route) < 0) + goto error; + + if (virSocketAddrParse(&route->via, via, family) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Failed to parse IP address: '%s'"), + via); + goto error; + } + + if (to && virSocketAddrParse(&route->to, to, family) < 0) { + virReportError(VIR_ERR_INVALID_ARG, + _("Failed to parse IP address: '%s'"), + to); + goto error; + } + + if (!(prefixStr = virXMLPropString(node, "prefix")) || + (virStrToLong_ui(prefixStr, NULL, 10, &route->prefix) < 0)) { + } + + return route; + + error: + VIR_FREE(familyStr); + VIR_FREE(via); + VIR_FREE(to); + VIR_FREE(prefixStr); + VIR_FREE(route); + + return NULL; +} + static int virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED, xmlXPathContextPtr ctxt, @@ -4467,6 +4532,8 @@ virDomainHostdevDefParseXMLCaps(xmlNodeP xmlNodePtr sourcenode; xmlNodePtr *ipnodes = NULL; int nipnodes; + xmlNodePtr *routenodes = NULL; + int nroutenodes; int ret = -1; /* @type is passed in from the caller rather than read from the @@ -4541,6 +4608,26 @@ virDomainHostdevDefParseXMLCaps(xmlNodeP } } } + + /* Look for possible gateways */ + if ((nroutenodes = virXPathNodeSet("./route", ctxt, &routenodes)) < 0) + goto error; + + if (nroutenodes) { + size_t i; + for (i = 0; i < nroutenodes; i++) { + virDomainNetRouteDefPtr route = virDomainNetRouteParse(routenodes[i]); + + if (!route) + goto error; + + if (VIR_APPEND_ELEMENT(def->source.caps.u.net.routes, + def->source.caps.u.net.nroutes, route) < 0) { + VIR_FREE(route); + goto error; + } + } + } break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -4551,6 +4638,7 @@ virDomainHostdevDefParseXMLCaps(xmlNodeP ret = 0; error: VIR_FREE(ipnodes); + VIR_FREE(routenodes); return ret; } @@ -6756,6 +6844,8 @@ virDomainNetDefParseXML(virDomainXMLOpti size_t i; size_t nips = 0; virDomainNetIpDefPtr *ips = NULL; + size_t nroutes = 0; + virDomainNetRouteDefPtr *routes = NULL; if (VIR_ALLOC(def) < 0) return NULL; @@ -6836,6 +6926,13 @@ virDomainNetDefParseXML(virDomainXMLOpti if (VIR_APPEND_ELEMENT(ips, nips, ip) < 0) goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "route")) { + virDomainNetRouteDefPtr route = NULL; + if (!(route = virDomainNetRouteParse(cur))) + goto error; + + if (VIR_APPEND_ELEMENT(routes, nroutes, route) < 0) + goto error; } else if (!ifname && xmlStrEqual(cur->name, BAD_CAST "target")) { ifname = virXMLPropString(cur, "dev"); @@ -7078,6 +7175,8 @@ virDomainNetDefParseXML(virDomainXMLOpti if (VIR_APPEND_ELEMENT(def->ips, def->nips, ips[i]) < 0) goto error; } + def->nroutes = nroutes; + def->routes = routes; if (script != NULL) { def->script = script; @@ -15682,6 +15781,37 @@ virDomainNetIpsFormat(virBufferPtr buf, } } +static void +virDomainNetRoutesFormat(virBufferPtr buf, + virDomainNetRouteDefPtr *routes, + size_t nroutes) +{ + size_t i; + + for (i = 0; i < nroutes; i++) { + virDomainNetRouteDefPtr route = routes[i]; + const char *familyStr = NULL; + char *via = virSocketAddrFormat(&route->via); + char *to = NULL; + + if (VIR_SOCKET_ADDR_IS_FAMILY(&route->via, AF_INET6)) + familyStr = "ipv6"; + else if (VIR_SOCKET_ADDR_IS_FAMILY(&route->via, AF_INET)) + familyStr = "ipv4"; + virBufferAsprintf(buf, "<route family='%s' via='%s'", familyStr, via); + + if (VIR_SOCKET_ADDR_VALID(&route->to)) { + to = virSocketAddrFormat(&route->to); + virBufferAsprintf(buf, " address='%s'", to); + } + + if (route->prefix > 0) + virBufferAsprintf(buf, " prefix='%d'", route->prefix); + + virBufferAddLit(buf, "/>\n"); + } +} + static int virDomainHostdevDefFormatSubsys(virBufferPtr buf, virDomainHostdevDefPtr def, @@ -15813,6 +15943,8 @@ virDomainHostdevDefFormatCaps(virBufferP 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); + virDomainNetRoutesFormat(buf, def->source.caps.u.net.routes, + def->source.caps.u.net.nroutes); } return 0; @@ -16064,6 +16196,7 @@ virDomainNetDefFormat(virBufferPtr buf, } virDomainNetIpsFormat(buf, def->ips, def->nips); + virDomainNetRoutesFormat(buf, def->routes, def->nroutes); virBufferEscapeString(buf, "<script path='%s'/>\n", def->script); Index: libvirt-1.2.5/src/conf/domain_conf.h =================================================================== --- libvirt-1.2.5.orig/src/conf/domain_conf.h +++ libvirt-1.2.5/src/conf/domain_conf.h @@ -434,6 +434,14 @@ struct _virDomainNetIpDef { unsigned int prefix; /* number of 1 bits in the net mask */ }; +typedef struct _virDomainNetRouteDef virDomainNetRouteDef; +typedef virDomainNetRouteDef *virDomainNetRouteDefPtr; +struct _virDomainNetRouteDef { + virSocketAddr via; + virSocketAddr to; + unsigned int prefix; +}; + typedef struct _virDomainHostdevCaps virDomainHostdevCaps; typedef virDomainHostdevCaps *virDomainHostdevCapsPtr; struct _virDomainHostdevCaps { @@ -449,6 +457,8 @@ struct _virDomainHostdevCaps { char *iface; size_t nips; virDomainNetIpDefPtr *ips; + size_t nroutes; + virDomainNetRouteDefPtr *routes; } net; } u; }; @@ -934,6 +944,8 @@ struct _virDomainNetDef { int linkstate; size_t nips; virDomainNetIpDefPtr *ips; + size_t nroutes; + virDomainNetRouteDefPtr *routes; }; /* Used for prefix of ifname of any network name generated dynamically Index: libvirt-1.2.5/src/util/virnetdev.c =================================================================== --- libvirt-1.2.5.orig/src/util/virnetdev.c +++ libvirt-1.2.5/src/util/virnetdev.c @@ -955,8 +955,33 @@ virNetDevAddRoute(const char *ifname, void *addrData = NULL; size_t addrDataLen; int errCode; + virSocketAddr defaultAddr; + virSocketAddrPtr actualAddr; + char *toStr = NULL; + char *viaStr = NULL; + + actualAddr = addr; + + /* If we have no valid network address, then use the default one */ + if (!addr || !VIR_SOCKET_ADDR_VALID(addr)) { + VIR_DEBUG("computing default address"); + int family = VIR_SOCKET_ADDR_FAMILY(gateway); + if (family == AF_INET) { + if (virSocketAddrParseIPv4(&defaultAddr, VIR_SOCKET_ADDR_IPV4_ALL) < 0) + goto cleanup; + } else { + if (virSocketAddrParseIPv6(&defaultAddr, VIR_SOCKET_ADDR_IPV6_ALL) < 0) + goto cleanup; + } - if (virNetDevGetIPAddressBinary(addr, &addrData, &addrDataLen) < 0 || + actualAddr = &defaultAddr; + } + + toStr = virSocketAddrFormat(actualAddr); + viaStr = virSocketAddrFormat(gateway); + VIR_DEBUG("Adding route %s/%d via %s", toStr, prefix, viaStr); + + if (virNetDevGetIPAddressBinary(actualAddr, &addrData, &addrDataLen) < 0 || virNetDevGetIPAddressBinary(gateway, &gatewayData, &addrDataLen) < 0) goto cleanup; @@ -973,7 +998,7 @@ virNetDevAddRoute(const char *ifname, memset(&rtmsg, 0, sizeof(rtmsg)); - rtmsg.rtm_family = VIR_SOCKET_ADDR_FAMILY(addr); + rtmsg.rtm_family = VIR_SOCKET_ADDR_FAMILY(gateway); rtmsg.rtm_table = RT_TABLE_MAIN; rtmsg.rtm_scope = RT_SCOPE_UNIVERSE; rtmsg.rtm_protocol = RTPROT_BOOT; @@ -1006,6 +1031,8 @@ virNetDevAddRoute(const char *ifname, ret = 0; cleanup: + VIR_FREE(toStr); + VIR_FREE(viaStr); nlmsg_free(nlmsg); return ret; Index: libvirt-1.2.5/src/util/virnetdev.h =================================================================== --- libvirt-1.2.5.orig/src/util/virnetdev.h +++ libvirt-1.2.5/src/util/virnetdev.h @@ -59,7 +59,7 @@ int virNetDevAddRoute(const char *ifname unsigned int prefix, virSocketAddrPtr gateway, unsigned int metric) - ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(4) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4) ATTRIBUTE_RETURN_CHECK; int virNetDevClearIPAddress(const char *ifname, virSocketAddr *addr, Index: libvirt-1.2.5/src/util/virsocketaddr.h =================================================================== --- libvirt-1.2.5.orig/src/util/virsocketaddr.h +++ libvirt-1.2.5/src/util/virsocketaddr.h @@ -55,6 +55,8 @@ typedef struct { ((s)->data.sa.sa_family) # define VIR_SOCKET_ADDR_DEFAULT_PREFIX 24 +# define VIR_SOCKET_ADDR_IPV4_ALL "0.0.0.0" +# define VIR_SOCKET_ADDR_IPV6_ALL "::" typedef virSocketAddr *virSocketAddrPtr; Index: libvirt-1.2.5/tests/lxcxml2xmldata/lxc-hostdev.xml =================================================================== --- libvirt-1.2.5.orig/tests/lxcxml2xmldata/lxc-hostdev.xml +++ libvirt-1.2.5/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'/> + <route family='ipv4' via='192.168.122.1'/> + <route family='ipv6' via='2003:db8:1:0:214:1234:fe0b:3595'/> </hostdev> </devices> </domain> Index: libvirt-1.2.5/tests/lxcxml2xmldata/lxc-idmap.xml =================================================================== --- libvirt-1.2.5.orig/tests/lxcxml2xmldata/lxc-idmap.xml +++ libvirt-1.2.5/tests/lxcxml2xmldata/lxc-idmap.xml @@ -30,6 +30,8 @@ <source bridge='bri0'/> <ip address='192.168.122.12' family='ipv4' prefix='24'/> <ip address='192.168.122.13' family='ipv4' prefix='24'/> + <route family='ipv4' via='192.168.122.1'/> + <route family='ipv4' via='192.168.124.1' address='192.168.124.0' prefix='24'/> <target dev='veth0'/> <guest dev='eth2'/> </interface>
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor