From 2811cc611e3c336e1dc5001a6077e5cf9d964dbc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= <cbosdonnat@suse.com>
Date: Wed, 23 Jul 2014 17:14:00 +0200
Subject: [PATCH 10/17] Allow network capabilities hostdev to configure IP
 addresses

---
 docs/formatdomain.html.in            |  8 ++++++++
 docs/schemas/domaincommon.rng        | 28 ++++++++++++++++++++++++----
 src/conf/domain_conf.c               | 34 ++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h               |  2 ++
 tests/lxcxml2xmldata/lxc-hostdev.xml |  2 ++
 5 files changed, 70 insertions(+), 4 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index a17cd8b..3f203a5 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -4330,6 +4330,14 @@ qemu-kvm -net nic,model=? /dev/null
       &lt;target dev='vnet0'/&gt;
       <b>&lt;ip family='ipv4' address='192.168.122.5' prefix='24'/&gt;</b>
     &lt;/interface&gt;
+    ...
+    &lt;hostdev mode='capabilities' type='net'&gt;
+      &lt;source&gt;
+        &lt;interface&gt;eth0&lt;/interface&gt;
+      &lt;/source&gt;
+      <b>&lt;ip family='ipv4' address='192.168.122.6' prefix='24'/&gt;</b>
+    &lt;/hostdev&gt;
+
   &lt;/devices&gt;
   ...
 </pre>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index b3e0940..c12aedf 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -3808,11 +3808,31 @@
     <attribute name="type">
       <value>net</value>
     </attribute>
-    <element name="source">
-      <element name="interface">
-        <ref name="deviceName"/>
+    <interleave>
+      <element name="source">
+        <element name="interface">
+          <ref name="deviceName"/>
+        </element>
       </element>
-    </element>
+      <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>
+    </interleave>
   </define>
 
   <define name="usbproduct">
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5a106d2..9447ed6 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1818,6 +1818,8 @@ virDomainHostdevSubsysSCSIiSCSIClear(virDomainHostdevSubsysSCSIiSCSIPtr iscsisrc
 
 void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
 {
+    size_t i;
+
     if (!def)
         return;
 
@@ -1842,6 +1844,9 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def)
             break;
         case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET:
             VIR_FREE(def->source.caps.u.net.iface);
+            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);
             break;
         }
         break;
@@ -4833,6 +4838,8 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
                                 virDomainHostdevDefPtr def)
 {
     xmlNodePtr sourcenode;
+    xmlNodePtr *ipnodes = NULL;
+    int nipnodes;
     int ret = -1;
 
     /* @type is passed in from the caller rather than read from the
@@ -4887,6 +4894,26 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
                            _("Missing <interface> element in hostdev net device"));
             goto error;
         }
+
+        /* Parse possible IP addresses */
+        if ((nipnodes = virXPathNodeSet("./ip", ctxt, &ipnodes)) < 0)
+            goto error;
+
+        if (nipnodes) {
+            size_t i;
+            for (i = 0; i < nipnodes; i++) {
+                virDomainNetIpDefPtr ip = virDomainNetIpParseXML(ipnodes[i]);
+
+                if (!ip)
+                    goto error;
+
+                if (VIR_APPEND_ELEMENT(def->source.caps.u.net.ips,
+                                       def->source.caps.u.net.nips, ip) < 0) {
+                    VIR_FREE(ip);
+                    goto error;
+                }
+            }
+        }
         break;
     default:
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
@@ -4896,6 +4923,7 @@ virDomainHostdevDefParseXMLCaps(xmlNodePtr node ATTRIBUTE_UNUSED,
     }
     ret = 0;
  error:
+    VIR_FREE(ipnodes);
     return ret;
 }
 
@@ -17302,6 +17330,12 @@ virDomainHostdevDefFormatCaps(virBufferPtr buf,
 
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</source>\n");
+
+    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);
+    }
+
     return 0;
 }
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 7d177f9..9292613 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -498,6 +498,8 @@ struct _virDomainHostdevCaps {
         } misc;
         struct {
             char *iface;
+            size_t nips;
+            virDomainNetIpDefPtr *ips;
         } net;
     } u;
 };
diff --git a/tests/lxcxml2xmldata/lxc-hostdev.xml b/tests/lxcxml2xmldata/lxc-hostdev.xml
index befe0db..0596789 100644
--- a/tests/lxcxml2xmldata/lxc-hostdev.xml
+++ b/tests/lxcxml2xmldata/lxc-hostdev.xml
@@ -35,6 +35,8 @@
       <source>
         <interface>eth0</interface>
       </source>
+      <ip address='192.168.122.2' family='ipv4'/>
+      <ip address='2003:db8:1:0:214:1234:fe0b:3596' family='ipv6' prefix='24'/>
     </hostdev>
   </devices>
 </domain>
-- 
2.1.2

