[libvirt] [PATCH 03/15] RNG updates, new xml parser/formatter code to support forward mode=hostdev

Shradha Shah sshah at solarflare.com
Fri Aug 10 16:23:30 UTC 2012


This patch introduces the new forward mode='hostdev' along with attribute managed
Includes updates to the network RNG and new xml parser/formatter code.

Signed-off-by: Shradha Shah <sshah at solarflare.com>
---
 docs/schemas/network.rng               |   82 +++++++++++++++++++--
 src/conf/network_conf.c                |  127 ++++++++++++++++++++++++++++----
 src/conf/network_conf.h                |   29 +++++++-
 src/network/bridge_driver.c            |   18 ++--
 tests/networkxml2xmlin/hostdev-pf.xml  |   11 +++
 tests/networkxml2xmlin/hostdev.xml     |   10 +++
 tests/networkxml2xmlout/hostdev-pf.xml |    7 ++
 tests/networkxml2xmlout/hostdev.xml    |   10 +++
 tests/networkxml2xmltest.c             |    2 +
 9 files changed, 263 insertions(+), 33 deletions(-)

diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index 2ae879e..d1297cd 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -82,17 +82,41 @@
                   <value>passthrough</value>
                   <value>private</value>
                   <value>vepa</value>
+                  <value>hostdev</value>
+                </choice>
+              </attribute>
+            </optional>
+
+            <optional>
+              <attribute name="managed">
+                <choice>
+                  <value>yes</value>
+                  <value>no</value>
                 </choice>
               </attribute>
             </optional>
             <interleave>
-              <zeroOrMore>
-                <element name='interface'>
-                  <attribute name='dev'>
-                    <ref name='deviceName'/>
-                  </attribute>
-                </element>
-              </zeroOrMore>
+              <choice>
+                <group>
+                  <zeroOrMore>
+                    <element name='interface'>
+                      <attribute name='dev'>
+                        <ref name='deviceName'/>
+                      </attribute>
+                    </element>
+                  </zeroOrMore>
+                </group>
+                <group>
+                  <zeroOrMore>
+                    <element name='address'>
+                      <attribute name='type'>
+                        <value>pci</value>
+                      </attribute>
+                      <ref name="pciaddress"/>
+                    </element>
+                  </zeroOrMore>
+                </group>
+              </choice>
               <optional>
                 <element name='pf'>
                   <attribute name='dev'>
@@ -238,4 +262,48 @@
       </interleave>
     </element>
   </define>
+  <define name="pciaddress">
+    <optional>
+      <attribute name="domain">
+        <ref name="pciDomain"/>
+      </attribute>
+    </optional>
+    <attribute name="bus">
+      <ref name="pciBus"/>
+    </attribute>
+    <attribute name="slot">
+      <ref name="pciSlot"/>
+    </attribute>
+    <attribute name="function">
+      <ref name="pciFunc"/>
+    </attribute>
+    <optional>
+      <attribute name="multifunction">
+        <choice>
+          <value>on</value>
+          <value>off</value>
+        </choice>
+      </attribute>
+    </optional>
+  </define>
+  <define name="pciDomain">
+    <data type="string">
+      <param name="pattern">(0x)?[0-9a-fA-F]{1,4}</param>
+    </data>
+  </define>
+  <define name="pciBus">
+    <data type="string">
+      <param name="pattern">(0x)?[0-9a-fA-F]{1,2}</param>
+    </data>
+  </define>
+  <define name="pciSlot">
+    <data type="string">
+      <param name="pattern">(0x)?[0-1]?[0-9a-fA-F]</param>
+    </data>
+  </define>
+  <define name="pciFunc">
+    <data type="string">
+      <param name="pattern">(0x)?[0-7]</param>
+    </data>
+  </define>
 </grammar>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index a3714d9..294939d 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -49,7 +49,12 @@
 
 VIR_ENUM_IMPL(virNetworkForward,
               VIR_NETWORK_FORWARD_LAST,
-              "none", "nat", "route", "bridge", "private", "vepa", "passthrough" )
+              "none", "nat", "route", "bridge", "private", "vepa", "passthrough", "hostdev")
+
+VIR_ENUM_DECL(virNetworkForwardHostdevDevice)
+VIR_ENUM_IMPL(virNetworkForwardHostdevDevice,
+              VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
+              "none", "pci")
 
 virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
                                       const unsigned char *uuid)
@@ -94,6 +99,12 @@ virPortGroupDefClear(virPortGroupDefPtr def)
 static void
 virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
 {
+    VIR_FREE(def->device.dev);
+}
+
+static void
+virNetworkForwardPfDefClear(virNetworkForwardPfDefPtr def)
+{
     VIR_FREE(def->dev);
 }
 
@@ -157,12 +168,13 @@ void virNetworkDefFree(virNetworkDefPtr def)
     VIR_FREE(def->domain);
 
     for (ii = 0 ; ii < def->nForwardPfs && def->forwardPfs ; ii++) {
-        virNetworkForwardIfDefClear(&def->forwardPfs[ii]);
+        virNetworkForwardPfDefClear(&def->forwardPfs[ii]);
     }
     VIR_FREE(def->forwardPfs);
 
     for (ii = 0 ; ii < def->nForwardIfs && def->forwardIfs ; ii++) {
-        virNetworkForwardIfDefClear(&def->forwardIfs[ii]);
+        if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV)
+            virNetworkForwardIfDefClear(&def->forwardIfs[ii]);
     }
     VIR_FREE(def->forwardIfs);
 
@@ -929,11 +941,14 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
     xmlNodePtr *portGroupNodes = NULL;
     xmlNodePtr *forwardIfNodes = NULL;
     xmlNodePtr *forwardPfNodes = NULL;
+    xmlNodePtr *forwardAddrNodes = NULL;
     xmlNodePtr dnsNode = NULL;
     xmlNodePtr virtPortNode = NULL;
     xmlNodePtr forwardNode = NULL;
-    int nIps, nPortGroups, nForwardIfs, nForwardPfs;
+    int nIps, nPortGroups, nForwardIfs, nForwardPfs, nForwardAddrs;
     char *forwardDev = NULL;
+    char *forwardManaged = NULL;
+    char *type = NULL;
     xmlNodePtr save = ctxt->node;
     xmlNodePtr bandwidthNode = NULL;
 
@@ -1079,17 +1094,30 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         }
 
         forwardDev = virXPathString("string(./@dev)", ctxt);
+        forwardManaged = virXPathString("string(./@managed)", ctxt);
+        if(forwardManaged != NULL) {
+            if (STREQ(forwardManaged, "yes"))
+                def->managed = 1;
+            else
+                def->managed = 0;
+        }
 
         /* all of these modes can use a pool of physical interfaces */
         nForwardIfs = virXPathNodeSet("./interface", ctxt, &forwardIfNodes);
         nForwardPfs = virXPathNodeSet("./pf", ctxt, &forwardPfNodes);
+        nForwardAddrs = virXPathNodeSet("./address", ctxt, &forwardAddrNodes);
 
-        if (nForwardIfs < 0 || nForwardPfs < 0) {
+        if (nForwardIfs < 0 || nForwardPfs < 0 || nForwardAddrs < 0) {
             virReportError(VIR_ERR_XML_ERROR, "%s",
                            _("No interface pool or SRIOV physical device given"));
             goto error;
         }
 
+        if ((nForwardIfs > 0) && (nForwardAddrs > 0)) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Address and interface attributes are mutually exclusive"));
+        }
+
         if (nForwardPfs == 1) {
             if (VIR_ALLOC_N(def->forwardPfs, nForwardPfs) < 0) {
                 virReportOOMError();
@@ -1119,7 +1147,55 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                            _("Use of more than one physical interface is not allowed"));
             goto error;
         }
-        if (nForwardIfs > 0 || forwardDev) {
+        if (nForwardAddrs > 0) {
+            int ii;
+            
+            if (VIR_ALLOC_N(def->forwardIfs, nForwardAddrs) < 0) {
+                virReportOOMError();
+                goto error;
+            }
+
+            if (forwardDev) {
+                virReportError(VIR_ERR_XML_ERROR, "%s",
+                               _("A forward Dev should not be used when using address attribute"));
+                goto error;
+            }
+            
+            for (ii = 0; ii < nForwardAddrs; ii++) {
+                type = virXMLPropString(*forwardAddrNodes, "type");
+                
+                if (type) {
+                    if ((def->forwardIfs[ii].type = virNetworkForwardHostdevDeviceTypeFromString(type)) < 0) {
+                        virReportError(VIR_ERR_XML_ERROR, 
+                                       _("unknown address type '%s'"), type);
+                        goto error;
+                    }
+                } else {
+                    virReportError(VIR_ERR_XML_ERROR,
+                                   "%s", _("No type specified for device address"));
+                    goto error;
+                }
+
+                switch (def->forwardIfs[ii].type) {
+                case VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI:
+                    if (virDevicePCIAddressParseXML(*forwardAddrNodes, &(def->forwardIfs[ii].device.pci)) < 0)
+                        goto error;
+                    break;
+                
+                /* Add USB case here */
+                    
+                default:
+                    virReportError(VIR_ERR_XML_ERROR, 
+                                   _("unknown address type '%s'"), type);
+                    goto error;
+                }
+
+                def->forwardIfs[ii].usageCount = 0;
+                type = NULL;
+                def->nForwardIfs++;
+            }
+        }
+        else if (nForwardIfs > 0 || forwardDev) {
             int ii;
 
             /* allocate array to hold all the portgroups */
@@ -1130,7 +1206,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
 
             if (forwardDev) {
                 def->forwardIfs[0].usageCount = 0;
-                def->forwardIfs[0].dev = forwardDev;
+                def->forwardIfs[0].device.dev = forwardDev;
+                def->forwardIfs[0].type = 0;
                 forwardDev = NULL;
                 def->nForwardIfs++;
             }
@@ -1148,10 +1225,10 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                 if ((ii == 0) && (def->nForwardIfs == 1)) {
                     /* both forwardDev and an interface element are present.
                      * If they don't match, it's an error. */
-                    if (STRNEQ(forwardDev, def->forwardIfs[0].dev)) {
-                        virReportError(VIR_ERR_XML_ERROR,
+                    if (STRNEQ(forwardDev, def->forwardIfs[0].device.dev)) {
+                        virReportError(VIR_ERR_XML_ERROR, 
                                        _("forward dev '%s' must match first interface element dev '%s' in network '%s'"),
-                                       def->forwardIfs[0].dev,
+                                       def->forwardIfs[0].device.dev,
                                        forwardDev, def->name);
                         goto error;
                     }
@@ -1159,16 +1236,19 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                     continue;
                 }
 
-                def->forwardIfs[ii].dev = forwardDev;
+                def->forwardIfs[ii].device.dev = forwardDev;
                 forwardDev = NULL;
                 def->forwardIfs[ii].usageCount = 0;
+                def->forwardIfs[ii].type = 0;
                 def->nForwardIfs++;
             }
         }
+        VIR_FREE(type);
         VIR_FREE(forwardDev);
+        VIR_FREE(forwardManaged);
         VIR_FREE(forwardPfNodes);
         VIR_FREE(forwardIfNodes);
-
+        VIR_FREE(forwardAddrNodes);
         switch (def->forwardType) {
         case VIR_NETWORK_FORWARD_ROUTE:
         case VIR_NETWORK_FORWARD_NAT:
@@ -1193,6 +1273,7 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         case VIR_NETWORK_FORWARD_PRIVATE:
         case VIR_NETWORK_FORWARD_VEPA:
         case VIR_NETWORK_FORWARD_PASSTHROUGH:
+        case VIR_NETWORK_FORWARD_HOSTDEV:
             if (def->bridge) {
                 virReportError(VIR_ERR_XML_ERROR,
                                _("bridge name not allowed in %s mode (network '%s')"),
@@ -1478,6 +1559,12 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
         }
         virBufferAddLit(&buf, "  <forward");
         virBufferEscapeString(&buf, " dev='%s'", dev);
+        if (def->forwardType == VIR_NETWORK_FORWARD_HOSTDEV) {
+            if (def->managed == 1)
+                virBufferAddLit(&buf, " managed='yes'");
+            else
+                virBufferAddLit(&buf, " managed='no'");
+        }
         virBufferAsprintf(&buf, " mode='%s'%s>\n", mode,
                           (def->nForwardIfs || def->nForwardPfs) ? "" : "/");
 
@@ -1489,8 +1576,20 @@ char *virNetworkDefFormat(const virNetworkDefPtr def, unsigned int flags)
         if (def->nForwardIfs &&
             (!def->nForwardPfs || !(flags & VIR_NETWORK_XML_INACTIVE))) {
             for (ii = 0; ii < def->nForwardIfs; ii++) {
-                virBufferEscapeString(&buf, "    <interface dev='%s'/>\n",
-                                      def->forwardIfs[ii].dev);
+                if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) 
+                    virBufferEscapeString(&buf, "    <interface dev='%s'/>\n",
+                                          def->forwardIfs[ii].device.dev);
+                else {
+                    if (def->forwardIfs[ii].type ==  VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
+                        if (virDevicePCIAddressFormat(&buf,
+                                                      def->forwardIfs[ii].device.pci,
+                                                      true) < 0) {
+                            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                                           _("PCI address format failed"));
+                            goto error;
+                        }
+                    }
+                }
             }
         }
         if (def->nForwardPfs || def->nForwardIfs)
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index a95b382..a57db36 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -36,6 +36,7 @@
 # include "virnetdevbandwidth.h"
 # include "virnetdevvportprofile.h"
 # include "virmacaddr.h"
+# include "device_conf.h"
 
 enum virNetworkForwardType {
     VIR_NETWORK_FORWARD_NONE   = 0,
@@ -45,10 +46,19 @@ enum virNetworkForwardType {
     VIR_NETWORK_FORWARD_PRIVATE,
     VIR_NETWORK_FORWARD_VEPA,
     VIR_NETWORK_FORWARD_PASSTHROUGH,
+    VIR_NETWORK_FORWARD_HOSTDEV,
 
     VIR_NETWORK_FORWARD_LAST,
 };
 
+enum virNetworkForwardHostdevDeviceType {
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NONE = 0,
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI,
+    /* USB Device to be added here when supported */
+    
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
+};
+
 typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef;
 typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr;
 struct _virNetworkDHCPRangeDef {
@@ -131,7 +141,19 @@ struct _virNetworkIpDef {
 typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
 typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
 struct _virNetworkForwardIfDef {
-    char *dev;      /* name of device */
+    int type;
+    union {
+        virDevicePCIAddress pci; /*PCI Address of device */
+        /* when USB devices are supported a new variable to be added here */
+        char *dev;      /* name of device */
+    }device;
+    int usageCount; /* how many guest interfaces are bound to this device? */
+};
+
+typedef struct _virNetworkForwardPfDef virNetworkForwardPfDef;
+typedef virNetworkForwardPfDef *virNetworkForwardPfDefPtr;
+struct _virNetworkForwardPfDef {
+    char *dev;      /* name of device */ 
     int usageCount; /* how many guest interfaces are bound to this device? */
 };
 
@@ -159,12 +181,13 @@ struct _virNetworkDef {
     bool mac_specified;
 
     int forwardType;    /* One of virNetworkForwardType constants */
+    int managed;        /* managed attribute for hostdev mode */
 
     /* If there are multiple forward devices (i.e. a pool of
      * interfaces), they will be listed here.
      */
     size_t nForwardPfs;
-    virNetworkForwardIfDefPtr forwardPfs;
+    virNetworkForwardPfDefPtr forwardPfs;
 
     size_t nForwardIfs;
     virNetworkForwardIfDefPtr forwardIfs;
@@ -234,7 +257,7 @@ static inline const char *
 virNetworkDefForwardIf(const virNetworkDefPtr def, size_t n)
 {
     return ((def->forwardIfs && (def->nForwardIfs > n))
-            ? def->forwardIfs[n].dev : NULL);
+            ? def->forwardIfs[n].device.dev : NULL);
 }
 
 virPortGroupDefPtr virPortGroupFindByName(virNetworkDefPtr net,
diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
index f128bd0..df3cc25 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2762,8 +2762,8 @@ networkCreateInterfacePool(virNetworkDefPtr netdef) {
     netdef->nForwardIfs = num_virt_fns;
     
     for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-        netdef->forwardIfs[ii].dev = strdup(vfname[ii]);
-        if (!netdef->forwardIfs[ii].dev) {
+        netdef->forwardIfs[ii].device.dev = strdup(vfname[ii]);
+        if (!netdef->forwardIfs[ii].device.dev) {
             virReportOOMError();
             goto finish;
         }
@@ -2985,7 +2985,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
                                netdef->name);
                 goto cleanup;
             }
-            iface->data.network.actual->data.direct.linkdev = strdup(dev->dev);
+            iface->data.network.actual->data.direct.linkdev = strdup(dev->device.dev);
             if (!iface->data.network.actual->data.direct.linkdev) {
                 virReportOOMError();
                 goto cleanup;
@@ -2993,7 +2993,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
             /* we are now assured of success, so mark the allocation */
             dev->usageCount++;
             VIR_DEBUG("Using physical device %s, usageCount %d",
-                      dev->dev, dev->usageCount);
+                      dev->device.dev, dev->usageCount);
         }
     }
 
@@ -3068,7 +3068,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* find the matching interface in the pool and increment its usageCount */
 
         for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-            if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+            if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) {
                 dev = &netdef->forwardIfs[ii];
                 break;
             }
@@ -3099,7 +3099,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* we are now assured of success, so mark the allocation */
         dev->usageCount++;
         VIR_DEBUG("Using physical device %s, usageCount %d",
-                  dev->dev, dev->usageCount);
+                  dev->device.dev, dev->usageCount);
     }
 
     ret = 0;
@@ -3169,7 +3169,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
         virNetworkForwardIfDefPtr dev = NULL;
 
         for (ii = 0; ii < netdef->nForwardIfs; ii++) {
-            if (STREQ(actualDev, netdef->forwardIfs[ii].dev)) {
+            if (STREQ(actualDev, netdef->forwardIfs[ii].device.dev)) {
                 dev = &netdef->forwardIfs[ii];
                 break;
             }
@@ -3184,7 +3184,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
 
         dev->usageCount--;
         VIR_DEBUG("Releasing physical device %s, usageCount %d",
-                  dev->dev, dev->usageCount);
+                  dev->device.dev, dev->usageCount);
     }
 
     ret = 0;
@@ -3265,7 +3265,7 @@ networkGetNetworkAddress(const char *netname, char **netaddr)
     case VIR_NETWORK_FORWARD_VEPA:
     case VIR_NETWORK_FORWARD_PASSTHROUGH:
         if ((netdef->nForwardIfs > 0) && netdef->forwardIfs)
-            dev_name = netdef->forwardIfs[0].dev;
+            dev_name = netdef->forwardIfs[0].device.dev;
 
         if (!dev_name) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
diff --git a/tests/networkxml2xmlin/hostdev-pf.xml b/tests/networkxml2xmlin/hostdev-pf.xml
new file mode 100644
index 0000000..e07db69
--- /dev/null
+++ b/tests/networkxml2xmlin/hostdev-pf.xml
@@ -0,0 +1,11 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode="hostdev" managed="yes">
+    <pf dev='eth2'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='1'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='2'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='3'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='4'/>
+  </forward>
+</network>
diff --git a/tests/networkxml2xmlin/hostdev.xml b/tests/networkxml2xmlin/hostdev.xml
new file mode 100644
index 0000000..0ec52d2
--- /dev/null
+++ b/tests/networkxml2xmlin/hostdev.xml
@@ -0,0 +1,10 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode="hostdev" managed="yes">
+    <address type='pci' domain='0' bus='3' slot='0' function='1'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='2'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='3'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='4'/>
+  </forward>
+</network>
diff --git a/tests/networkxml2xmlout/hostdev-pf.xml b/tests/networkxml2xmlout/hostdev-pf.xml
new file mode 100644
index 0000000..e955312
--- /dev/null
+++ b/tests/networkxml2xmlout/hostdev-pf.xml
@@ -0,0 +1,7 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode="hostdev" managed="yes">
+    <pf dev='eth2'/>
+   </forward>
+</network>
diff --git a/tests/networkxml2xmlout/hostdev.xml b/tests/networkxml2xmlout/hostdev.xml
new file mode 100644
index 0000000..0ec52d2
--- /dev/null
+++ b/tests/networkxml2xmlout/hostdev.xml
@@ -0,0 +1,10 @@
+<network>
+  <name>hostdev</name>
+  <uuid>81ff0d90-c91e-6742-64da-4a736edb9a9b</uuid>
+  <forward mode="hostdev" managed="yes">
+    <address type='pci' domain='0' bus='3' slot='0' function='1'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='2'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='3'/>
+    <address type='pci' domain='0' bus='3' slot='0' function='4'/>
+  </forward>
+</network>
diff --git a/tests/networkxml2xmltest.c b/tests/networkxml2xmltest.c
index 8641c41..c9c8311 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -105,6 +105,8 @@ mymain(void)
     DO_TEST("vepa-net");
     DO_TEST("bandwidth-network");
     DO_TEST_FULL("passthrough-pf", VIR_NETWORK_XML_INACTIVE);
+    DO_TEST("hostdev");
+    DO_TEST_FULL("hostdev-pf", VIR_NETWORK_XML_INACTIVE);
 
     return ret==0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
1.7.4.4





More information about the libvir-list mailing list