From a117652917ed9755ebf7bec1603b0cb048b8d5a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Wed, 14 Jan 2015 16:15:57 +0100
Subject: [PATCH 4/7] Use the network route definitions for domains

---
 docs/formatdomain.html.in                         |   9 +-
 docs/schemas/domaincommon.rng                     |  29 +-----
 docs/schemas/network.rng                          |   2 +-
 docs/schemas/networkcommon.rng                    |   2 +-
 src/conf/domain_conf.c                            | 121 +++++-----------------
 src/conf/domain_conf.h                            |  14 +--
 src/conf/networkcommon_conf.c                     |   6 +-
 src/conf/networkcommon_conf.h                     |   6 +-
 src/lxc/lxc_container.c                           |  22 ++--
 src/lxc/lxc_native.c                              |  25 +++--
 tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml |   4 +-
 tests/lxcconf2xmldata/lxcconf2xml-simple.xml      |   4 +-
 tests/lxcxml2xmldata/lxc-hostdev.xml              |   4 +-
 tests/lxcxml2xmldata/lxc-idmap.xml                |   4 +-
 14 files changed, 79 insertions(+), 173 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
@@ -3965,12 +3965,9 @@ qemu-kvm -net nic,model=? /dev/null
 
     <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.
+    to define the network routes to use for the network device. The attributes
+    of this element are described in the documentation for the <code>route</code>
+    element in <a href="formatnetwork.html#elementsStaticroute">network definitions</a>.
     This is only used by the LXC driver.
     </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
@@ -2208,9 +2208,7 @@
         </element>
       </zeroOrMore>
       <zeroOrMore>
-        <element name="route">
-          <ref name="route"/>
-        </element>
+        <ref name="route"/>
       </zeroOrMore>
       <optional>
         <element name="script">
@@ -3388,27 +3386,6 @@
     </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>
@@ -3606,9 +3583,7 @@
         </element>
       </zeroOrMore>
       <zeroOrMore>
-        <element name="route">
-          <ref name="route"/>
-        </element>
+        <ref name="route"/>
       </zeroOrMore>
     </interleave>
   </define>
Index: libvirt-1.2.5/docs/schemas/network.rng
===================================================================
--- libvirt-1.2.5.orig/docs/schemas/network.rng
+++ libvirt-1.2.5/docs/schemas/network.rng
@@ -367,7 +367,7 @@
         </zeroOrMore>
         <!-- <route> element -->
         <zeroOrMore>
-          <ref name="routex"/>
+          <ref name="route"/>
         </zeroOrMore>
       </interleave>
     </element>
Index: libvirt-1.2.5/docs/schemas/networkcommon.rng
===================================================================
--- libvirt-1.2.5.orig/docs/schemas/networkcommon.rng
+++ libvirt-1.2.5/docs/schemas/networkcommon.rng
@@ -228,7 +228,7 @@
   <!-- The (static) route element specifies a network address and gateway
        address to access that network. Both the network address and
        the gateway address must be specified. -->
-  <define name='routex'>
+  <define name='route'>
     <element name="route">
       <optional>
         <attribute name="family"><ref name="addr-family"/></attribute>
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
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2006-2014 Red Hat, Inc.
  * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -1423,10 +1424,10 @@ void virDomainNetDefFree(virDomainNetDef
     VIR_FREE(def->ips);
 
     for (i = 0; i < def->nroutes; i++)
-        VIR_FREE(def->routes[i]);
+        virNetworkRouteDefFree(def->routes[i]);
     VIR_FREE(def->routes);
 
-        virDomainDeviceInfoClear(&def->info);
+    virDomainDeviceInfoClear(&def->info);
 
     VIR_FREE(def->filter);
     virNWFilterHashTableFree(def->filterparams);
@@ -4465,64 +4466,6 @@ 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,
@@ -4616,14 +4559,17 @@ virDomainHostdevDefParseXMLCaps(xmlNodeP
         if (nroutenodes) {
             size_t i;
             for (i = 0; i < nroutenodes; i++) {
-                virDomainNetRouteDefPtr route = virDomainNetRouteParse(routenodes[i]);
+                virNetworkRouteDefPtr route = NULL;
 
-                if (!route)
+                if (!(route = virNetworkRouteDefParseXML(_("Domain hostdev device"),
+                                                         routenodes[i],
+                                                         ctxt)))
                     goto error;
 
+
                 if (VIR_APPEND_ELEMENT(def->source.caps.u.net.routes,
                                        def->source.caps.u.net.nroutes, route) < 0) {
-                    VIR_FREE(route);
+                    virNetworkRouteDefFree(route);
                     goto error;
                 }
             }
@@ -6845,7 +6791,7 @@ virDomainNetDefParseXML(virDomainXMLOpti
     size_t nips = 0;
     virDomainNetIpDefPtr *ips = NULL;
     size_t nroutes = 0;
-    virDomainNetRouteDefPtr *routes = NULL;
+    virNetworkRouteDefPtr *routes = NULL;
 
     if (VIR_ALLOC(def) < 0)
         return NULL;
@@ -6927,12 +6873,15 @@ 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)))
+                virNetworkRouteDefPtr route = NULL;
+                if (!(route = virNetworkRouteDefParseXML(_("Domain interface"),
+                                                         cur, ctxt)))
                     goto error;
 
-                if (VIR_APPEND_ELEMENT(routes, nroutes, route) < 0)
+                if (VIR_APPEND_ELEMENT(routes, nroutes, route) < 0) {
+                    virNetworkRouteDefFree(route);
                     goto error;
+                }
             } else if (!ifname &&
                        xmlStrEqual(cur->name, BAD_CAST "target")) {
                 ifname = virXMLPropString(cur, "dev");
@@ -15781,35 +15730,17 @@ virDomainNetIpsFormat(virBufferPtr buf,
     }
 }
 
-static void
+static int
 virDomainNetRoutesFormat(virBufferPtr buf,
-                         virDomainNetRouteDefPtr *routes,
+                         virNetworkRouteDefPtr *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");
-    }
+    for (i = 0; i < nroutes; i++)
+        if (virNetworkRouteDefFormat(buf, routes[i]) < 0)
+            return -1;
+    return 0;
 }
 
 static int
@@ -15943,8 +15874,9 @@ 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);
+        if (virDomainNetRoutesFormat(buf, def->source.caps.u.net.routes,
+                                     def->source.caps.u.net.nroutes) < 0)
+            return -1;
     }
 
     return 0;
@@ -16196,7 +16128,8 @@ virDomainNetDefFormat(virBufferPtr buf,
     }
 
     virDomainNetIpsFormat(buf, def->ips, def->nips);
-    virDomainNetRoutesFormat(buf, def->routes, def->nroutes);
+    if (virDomainNetRoutesFormat(buf, def->routes, def->nroutes) < 0)
+        return -1;
 
     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
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2006-2014 Red Hat, Inc.
  * Copyright (C) 2006-2008 Daniel P. Berrange
+ * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -35,6 +36,7 @@
 # include "virthread.h"
 # include "virhash.h"
 # include "virsocketaddr.h"
+# include "networkcommon_conf.h"
 # include "nwfilter_params.h"
 # include "virnetdevmacvlan.h"
 # include "virsysinfo.h"
@@ -434,14 +436,6 @@ 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 {
@@ -458,7 +452,7 @@ struct _virDomainHostdevCaps {
             size_t nips;
             virDomainNetIpDefPtr *ips;
             size_t nroutes;
-            virDomainNetRouteDefPtr *routes;
+            virNetworkRouteDefPtr *routes;
         } net;
     } u;
 };
@@ -945,7 +939,7 @@ struct _virDomainNetDef {
     size_t nips;
     virDomainNetIpDefPtr *ips;
     size_t nroutes;
-    virDomainNetRouteDefPtr *routes;
+    virNetworkRouteDefPtr *routes;
 };
 
 /* Used for prefix of ifname of any network name generated dynamically
Index: libvirt-1.2.5/src/conf/networkcommon_conf.c
===================================================================
--- libvirt-1.2.5.orig/src/conf/networkcommon_conf.c
+++ libvirt-1.2.5/src/conf/networkcommon_conf.c
@@ -61,9 +61,9 @@ virNetworkRouteDefFree(virNetworkRouteDe
 virNetworkRouteDefPtr
 virNetworkRouteDefCreate(const char *errorDetail,
                          char *family,
-                         char *address,
-                         char *netmask,
-                         char *gateway,
+                         const char *address,
+                         const char *netmask,
+                         const char *gateway,
                          unsigned int prefix,
                          bool hasPrefix,
                          unsigned int metric,
Index: libvirt-1.2.5/src/conf/networkcommon_conf.h
===================================================================
--- libvirt-1.2.5.orig/src/conf/networkcommon_conf.h
+++ libvirt-1.2.5/src/conf/networkcommon_conf.h
@@ -41,9 +41,9 @@ virNetworkRouteDefFree(virNetworkRouteDe
 virNetworkRouteDefPtr
 virNetworkRouteDefCreate(const char *networkName,
                          char *family,
-                         char *address,
-                         char *netmask,
-                         char *gateway,
+                         const char *address,
+                         const char *netmask,
+                         const char *gateway,
                          unsigned int prefix,
                          bool hasPrefix,
                          unsigned int metric,
Index: libvirt-1.2.5/src/lxc/lxc_container.c
===================================================================
--- libvirt-1.2.5.orig/src/lxc/lxc_container.c
+++ libvirt-1.2.5/src/lxc/lxc_container.c
@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2008-2013 Red Hat, Inc.
  * Copyright (C) 2008 IBM Corp.
+ * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
  *
  * lxc_container.c: file description
  *
@@ -544,20 +545,13 @@ static int lxcContainerRenameAndEnableIn
 
             /* Set the routes */
             for (j = 0; j < netDef->nroutes; j++) {
-                virDomainNetRouteDefPtr route = netDef->routes[j];
-                if (VIR_SOCKET_ADDR_VALID(&route->to))
-                    toStr = virSocketAddrFormat(&route->to);
-                else
-                    if (VIR_STRDUP(toStr, "default") < 0)
-                        goto error_out;
-                viaStr = virSocketAddrFormat(&route->via);
-                VIR_DEBUG("Adding route %s/%d via %s", toStr, route->prefix, viaStr);
-
-                if (virNetDevAddRoute(newname, &route->to, route->prefix,
-                                      &route->via, 0) < 0) {
-                    virReportError(VIR_ERR_SYSTEM_ERROR,
-                                   _("Failed to add route %s/%d via %s"),
-                                   toStr, route->prefix, viaStr);
+                virNetworkRouteDefPtr route = netDef->routes[j];
+
+                if (virNetDevAddRoute(newname,
+                                      virNetworkRouteDefGetAddress(route),
+                                      virNetworkRouteDefGetPrefix(route),
+                                      virNetworkRouteDefGetGateway(route),
+                                      virNetworkRouteDefGetMetric(route)) < 0) {
                     goto error_out;
                 }
                 VIR_FREE(toStr);
Index: libvirt-1.2.5/src/lxc/lxc_native.c
===================================================================
--- libvirt-1.2.5.orig/src/lxc/lxc_native.c
+++ libvirt-1.2.5/src/lxc/lxc_native.c
@@ -2,6 +2,7 @@
  * lxc_native.c: LXC native configuration import
  *
  * Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (c) 2013-2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -432,24 +433,37 @@ typedef struct {
 static int
 lxcAddNetworkRouteDefinition(const char *address,
                              int family,
-                             virDomainNetRouteDefPtr **routes,
+                             virNetworkRouteDefPtr **routes,
                              size_t *nroutes)
 {
-    virDomainNetRouteDefPtr route = NULL;
+    virNetworkRouteDefPtr route = NULL;
+    char *familyStr = NULL;
+    char *zero = NULL;
 
-    if (VIR_ALLOC(route) < 0)
+    if (VIR_STRDUP(zero, family == AF_INET ? VIR_SOCKET_ADDR_IPV4_ALL
+                   : VIR_SOCKET_ADDR_IPV6_ALL) < 0)
         goto error;
 
-    if (virSocketAddrParse(&route->via, address, family) < 0)
+    if (VIR_STRDUP(familyStr, family == AF_INET ? "ipv4" : "ipv6") < 0)
+        goto error;
+
+    if (!(route = virNetworkRouteDefCreate(_("Domain interface"), familyStr,
+                                          zero, NULL, address, 0, false,
+                                          0, false)))
         goto error;
 
     if (VIR_APPEND_ELEMENT(*routes, *nroutes, route) < 0)
         goto error;
 
+    VIR_FREE(familyStr);
+    VIR_FREE(zero);
+
     return 0;
 
  error:
-    VIR_FREE(route);
+    VIR_FREE(familyStr);
+    VIR_FREE(zero);
+    virNetworkRouteDefFree(route);
     return -1;
 }
 
Index: libvirt-1.2.5/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
===================================================================
--- libvirt-1.2.5.orig/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
+++ libvirt-1.2.5/tests/lxcconf2xmldata/lxcconf2xml-physnetwork.xml
@@ -27,8 +27,8 @@
       </source>
       <ip address='192.168.122.2' family='ipv4' prefix='24'/>
       <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6' prefix='64'/>
-      <route family='ipv4' via='192.168.122.1'/>
-      <route family='ipv6' via='2003:db8:1:0:214:1234:fe0b:3595'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv6' address='::' gateway='2003:db8:1:0:214:1234:fe0b:3595'/>
     </hostdev>
   </devices>
 </domain>
Index: libvirt-1.2.5/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
===================================================================
--- libvirt-1.2.5.orig/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
+++ libvirt-1.2.5/tests/lxcconf2xmldata/lxcconf2xml-simple.xml
@@ -39,8 +39,8 @@
       <source bridge='virbr0'/>
       <ip address='192.168.122.2' family='ipv4' prefix='24'/>
       <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6' prefix='64'/>
-      <route family='ipv4' via='192.168.122.1'/>
-      <route family='ipv6' via='2003:db8:1:0:214:1234:fe0b:3595'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv6' address='::' gateway='2003:db8:1:0:214:1234:fe0b:3595'/>
       <guest dev='eth0'/>
       <link state='up'/>
     </interface>
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,8 +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'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv6' address='::' gateway='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,8 +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'/>
+      <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
+      <route family='ipv4' address='192.168.124.0' prefix='24' gateway='192.168.124.1'/>
       <target dev='veth0'/>
       <guest dev='eth2'/>
     </interface>
