[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [RFC 5/7] hostdev: add parse ip and route for bond configure



bond device always need to configure the ip address and
route way address. so here we add the interface.

xml like:
<hostdev mode='subsystem' type='pci' managed='no'>
  <driver name='vfio' type='bond'/>
  <bond>
    <ip address='192.168.122.5' family='ipv4' prefix='24'/>
    <route family='ipv4' address='0.0.0.0' gateway='192.168.122.1'/>
    <interface address='52:54:00:e8:c0:f3'/>
    <interface address='44:33:4c:06:f5:8e'/>
</bond>

Signed-off-by: Chen Fan <chen fan fnst cn fujitsu com>
---
 docs/schemas/domaincommon.rng | 21 +++++++++++
 src/conf/domain_conf.c        | 87 ++++++++++++++++++++++++++++++++++++-------
 src/conf/domain_conf.h        | 24 ++++++++----
 src/conf/networkcommon_conf.c | 17 ---------
 src/conf/networkcommon_conf.h | 17 +++++++++
 src/qemu/qemu_agent.c         | 58 +++++++++++++++++++++++++++--
 6 files changed, 183 insertions(+), 41 deletions(-)

diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 0cf82cb..4056cbd 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3779,6 +3779,27 @@
       <optional>
         <element name="bond">
           <zeroOrMore>
+            <element name="ip">
+              <attribute name="address">
+                <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>
+          </zeroOrMore>
+          <zeroOrMore>
+            <ref name="route"/>
+          </zeroOrMore>
+          <zeroOrMore>
             <element name="interface">
               <ref name="pciinterface"/>
             </element>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 14bcae1..7d1cd3e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -797,6 +797,8 @@ static virClassPtr virDomainXMLOptionClass;
 static void virDomainObjDispose(void *obj);
 static void virDomainObjListDispose(void *obj);
 static void virDomainXMLOptionClassDispose(void *obj);
+static virDomainNetIpDefPtr virDomainNetIpParseXML(xmlNodePtr node);
+
 
 static int virDomainObjOnceInit(void)
 {
@@ -1914,8 +1916,17 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
             }
         } else if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
             virDomainHostdevSubsysPCIPtr pcisrc = &def->source.subsys.u.pci;
-            if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND)
-                VIR_FREE(pcisrc->macs);
+            if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) {
+                for (i = 0; i < pcisrc->net.nmacs; i++)
+                    VIR_FREE(pcisrc->net.macs[i]);
+                VIR_FREE(pcisrc->net.macs);
+                for (i = 0; i < pcisrc->net.nips; i++)
+                    VIR_FREE(pcisrc->net.ips[i]);
+                VIR_FREE(pcisrc->net.ips);
+                for (i = 0; i < pcisrc->net.nroutes; i++)
+                    VIR_FREE(pcisrc->net.routes[i]);
+                VIR_FREE(pcisrc->net.routes);
+            }
         }
         break;
     }
@@ -5102,26 +5113,68 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
         if (device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) {
             xmlNodePtr *macs = NULL;
             int n = 0;
-            int i;
+            size_t i;
             char *macStr = NULL;
+            xmlNodePtr *ipnodes = NULL;
+            int nipnodes;
+            xmlNodePtr *routenodes = NULL;
+            int nroutenodes;
 
             if (!(virXPathNode("./bond", ctxt))) {
                 virReportError(VIR_ERR_XML_ERROR, "%s",
-                               _("missing <nond> node specified by bond type"));
+                               _("missing <bond> node specified by bond type"));
                 goto error;
             }
 
+            if ((nipnodes = virXPathNodeSet("./bond/ip", ctxt, &ipnodes)) < 0)
+                goto error;
+
+            if (nipnodes) {
+                for (i = 0; i < nipnodes; i++) {
+                    virDomainNetIpDefPtr ip = virDomainNetIpParseXML(ipnodes[i]);
+
+                    if (!ip)
+                        goto error;
+
+                    if (VIR_APPEND_ELEMENT(pcisrc->net.ips,
+                                           pcisrc->net.nips, ip) < 0) {
+                        VIR_FREE(ip);
+                        goto error;
+                    }
+                }
+            }
+
+            if ((nroutenodes = virXPathNodeSet("./bond/route", ctxt, &routenodes)) < 0)
+                goto error;
+
+            if (nroutenodes) {
+                for (i = 0; i < nroutenodes; i++) {
+                    virNetworkRouteDefPtr route = NULL;
+
+                    if (!(route = virNetworkRouteDefParseXML(_("Domain hostdev device"),
+                                                             routenodes[i],
+                                                             ctxt)))
+                        goto error;
+
+                    if (VIR_APPEND_ELEMENT(pcisrc->net.routes,
+                                           pcisrc->net.nroutes, route) < 0) {
+                        virNetworkRouteDefFree(route);
+                        goto error;
+                    }
+                }
+            }
+
             if ((n = virXPathNodeSet("./bond/interface", ctxt, &macs)) < 0) {
                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                _("Cannot extract interface nodes"));
                 goto error;
             }
 
-            VIR_FREE(pcisrc->macs);
-            if (VIR_ALLOC_N(pcisrc->macs, n) < 0)
+            VIR_FREE(pcisrc->net.macs);
+            if (VIR_ALLOC_N(pcisrc->net.macs, n) < 0)
                 goto error;
 
-            pcisrc->nmac = n;
+            pcisrc->net.nmacs = n;
             for (i = 0; i < n; i++) {
                 xmlNodePtr cur_node = macs[i];
 
@@ -5132,14 +5185,18 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr node,
                                    "in interface element"));
                     goto error;
                 }
-                if (virMacAddrParse((const char *)macStr, &pcisrc->macs[i]) < 0) {
+
+                if (VIR_ALLOC(pcisrc->net.macs[i]) < 0)
+                    goto error;
+
+                if (virMacAddrParse((const char *)macStr, pcisrc->net.macs[i]) < 0) {
                     virReportError(VIR_ERR_XML_ERROR,
                                    _("unable to parse mac address '%s'"),
                                    (const char *)macStr);
                     VIR_FREE(macStr);
                     goto error;
                 }
-                if (virMacAddrIsMulticast(&pcisrc->macs[i])) {
+                if (virMacAddrIsMulticast(pcisrc->net.macs[i])) {
                     virReportError(VIR_ERR_XML_ERROR,
                                    _("expected unicast mac address, found multicast '%s'"),
                                    (const char *)macStr);
@@ -18501,13 +18558,17 @@ virDomainHostdevDefFormatSubsys(virBufferPtr buf,
             virBufferAddLit(buf, "/>\n");
         }
 
-        if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND &&
-            pcisrc->nmac > 0) {
+        if (pcisrc->device == VIR_DOMAIN_HOSTDEV_PCI_DEVICE_BOND) {
             virBufferAddLit(buf, "<bond>\n");
             virBufferAdjustIndent(buf, 2);
-            for (i = 0; i < pcisrc->nmac; i++) {
+            if (virDomainNetIpsFormat(buf, pcisrc->net.ips, pcisrc->net.nips) < 0)
+                return -1;
+            if (virDomainNetRoutesFormat(buf, pcisrc->net.routes, pcisrc->net.nroutes) < 0)
+                return -1;
+
+            for (i = 0; i < pcisrc->net.nmacs; i++) {
                 virBufferAsprintf(buf, "<interface address='%s'/>\n",
-                                  virMacAddrFormat(&pcisrc->macs[i], macstr));
+                                  virMacAddrFormat(pcisrc->net.macs[i], macstr));
             }
             virBufferAdjustIndent(buf, -2);
             virBufferAddLit(buf, "</bond>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index e62979f..723f07b 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -447,14 +447,28 @@ struct _virDomainHostdevSubsysUSB {
     unsigned product;
 };
 
+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 _virDomainHostdevSubsysPCI virDomainHostdevSubsysPCI;
 typedef virDomainHostdevSubsysPCI *virDomainHostdevSubsysPCIPtr;
 struct _virDomainHostdevSubsysPCI {
     virDevicePCIAddress addr; /* host address */
     int backend; /* enum virDomainHostdevSubsysPCIBackendType */
     int device;  /* enum virDomainHostdevSubsysPCIDeviceType */
-    size_t nmac;
-    virMacAddr* macs;
+
+    struct {
+        size_t nips;
+        virDomainNetIpDefPtr *ips;
+        size_t nroutes;
+        virNetworkRouteDefPtr *routes;
+        size_t nmacs;
+        virMacAddrPtr *macs;
+    } net;
 };
 
 typedef struct _virDomainHostdevSubsysSCSIHost virDomainHostdevSubsysSCSIHost;
@@ -507,12 +521,6 @@ 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;
diff --git a/src/conf/networkcommon_conf.c b/src/conf/networkcommon_conf.c
index 7b7a851..c11baf6 100644
--- a/src/conf/networkcommon_conf.c
+++ b/src/conf/networkcommon_conf.c
@@ -32,23 +32,6 @@
 
 #define VIR_FROM_THIS VIR_FROM_NETWORK
 
-struct _virNetworkRouteDef {
-    char *family;               /* ipv4 or ipv6 - default is ipv4 */
-    virSocketAddr address;      /* Routed Network IP address */
-
-    /* One or the other of the following two will be used for a given
-     * Network address, but never both. The parser guarantees this.
-     * The virSocketAddrGetIpPrefix() can be used to get a
-     * valid prefix.
-     */
-    virSocketAddr netmask;      /* ipv4 - either netmask or prefix specified */
-    unsigned int prefix;        /* ipv6 - only prefix allowed */
-    bool has_prefix;            /* prefix= was specified */
-    unsigned int metric;        /* value for metric (defaults to 1) */
-    bool has_metric;            /* metric= was specified */
-    virSocketAddr gateway;      /* gateway IP address for ip-route */
-};
-
 void
 virNetworkRouteDefFree(virNetworkRouteDefPtr def)
 {
diff --git a/src/conf/networkcommon_conf.h b/src/conf/networkcommon_conf.h
index 1500d0f..a9f58e8 100644
--- a/src/conf/networkcommon_conf.h
+++ b/src/conf/networkcommon_conf.h
@@ -35,6 +35,23 @@
 typedef struct _virNetworkRouteDef virNetworkRouteDef;
 typedef virNetworkRouteDef *virNetworkRouteDefPtr;
 
+struct _virNetworkRouteDef {
+    char *family;               /* ipv4 or ipv6 - default is ipv4 */
+    virSocketAddr address;      /* Routed Network IP address */
+
+    /* One or the other of the following two will be used for a given
+     * Network address, but never both. The parser guarantees this.
+     * The virSocketAddrGetIpPrefix() can be used to get a
+     * valid prefix.
+     */
+    virSocketAddr netmask;      /* ipv4 - either netmask or prefix specified */
+    unsigned int prefix;        /* ipv6 - only prefix allowed */
+    bool has_prefix;            /* prefix= was specified */
+    unsigned int metric;        /* value for metric (defaults to 1) */
+    bool has_metric;            /* metric= was specified */
+    virSocketAddr gateway;      /* gateway IP address for ip-route */
+};
+
 void
 virNetworkRouteDefFree(virNetworkRouteDefPtr def);
 
diff --git a/src/qemu/qemu_agent.c b/src/qemu/qemu_agent.c
index b8eba01..f9823e2 100644
--- a/src/qemu/qemu_agent.c
+++ b/src/qemu/qemu_agent.c
@@ -2208,11 +2208,14 @@ qemuAgentCreateBond(qemuAgentPtr mon,
     virDomainInterfacePtr *interfaceInfo = NULL;
     virDomainInterfacePtr interface;
     virJSONValuePtr new_interface = NULL;
+    virJSONValuePtr ip_interface = NULL;
     virJSONValuePtr subInterfaces = NULL;
     virJSONValuePtr subInterface = NULL;
     int len;
 
-    if (!(pcisrc->nmac || pcisrc->macs))
+    if (!(pcisrc->net.nmacs &&
+          pcisrc->net.nips &&
+          pcisrc->net.nroutes))
         return ret;
 
     len = qemuAgentGetInterfaces(mon, &interfaceInfo);
@@ -2231,11 +2234,60 @@ qemuAgentCreateBond(qemuAgentPtr mon,
     if (virJSONValueObjectAppendString(new_interface, "onboot", "onboot") < 0)
         goto cleanup;
 
+    if (virJSONValueObjectAppendString(new_interface,
+                                       "options",
+                                       "mode=active-backup miimon=100 updelay=10") < 0)
+        goto cleanup;
+
+    if (!(ip_interface = virJSONValueNewObject()))
+        goto cleanup;
+
+    if (pcisrc->net.nips) {
+        /* the first valid */
+        virSocketAddrPtr address = &pcisrc->net.ips[0]->address;
+        char *ipStr = virSocketAddrFormat(address);
+        const char *familyStr = NULL;
+
+        if (virJSONValueObjectAppendString(ip_interface, "ip-address", ipStr) < 0)
+            goto cleanup;
+        VIR_FREE(ipStr);
+
+        if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET6))
+            familyStr = "ipv6";
+        else if (VIR_SOCKET_ADDR_IS_FAMILY(address, AF_INET))
+            familyStr = "ipv4";
+
+        if (familyStr)
+            if (virJSONValueObjectAppendString(ip_interface, "ip-address-type", familyStr) < 0)
+                goto cleanup;
+        if (pcisrc->net.ips[0]->prefix != 0)
+            if (virJSONValueObjectAppendNumberInt(ip_interface, "prefix",
+                                                  pcisrc->net.ips[0]->prefix) < 0)
+                goto cleanup;
+    }
+
+    if (pcisrc->net.nroutes) {
+        /* the first valid */
+        char *addr = NULL;
+        virSocketAddrPtr gateway = &pcisrc->net.routes[0]->gateway;
+
+        if (!(addr = virSocketAddrFormat(gateway)))
+            goto cleanup;
+        if (virJSONValueObjectAppendString(ip_interface, "gateway", addr) < 0)
+            goto cleanup;
+        VIR_FREE(addr);
+    }
+
+    if ((pcisrc->net.nroutes ||
+         pcisrc->net.nips) &&
+        virJSONValueObjectAppend(new_interface, "ip-address", ip_interface) < 0)
+        goto cleanup;
+
     if (!(subInterfaces = virJSONValueNewArray()))
         goto cleanup;
 
-    for (i = 0; i < pcisrc->nmac; i++) {
-        virMacAddrFormat(&pcisrc->macs[i], macstr);
+    for (i = 0; i < pcisrc->net.nmacs; i++) {
+        virMacAddrFormat(pcisrc->net.macs[i], macstr);
         interface = findInterfaceByMac(interfaceInfo, len, macstr);
         if (!interface) {
             goto cleanup;
-- 
1.9.3


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]