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

Shradha Shah sshah at solarflare.com
Thu Aug 16 15:41:41 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/basictypes.rng            |   46 +++++++++++
 docs/schemas/domaincommon.rng          |   44 -----------
 docs/schemas/network.rng               |   53 ++++++++++---
 src/conf/network_conf.c                |  130 +++++++++++++++++++++++++++-----
 src/conf/network_conf.h                |   26 ++++++-
 src/network/bridge_driver.c            |   18 ++--
 tests/networkxml2xmlin/hostdev-pf.xml  |    7 ++
 tests/networkxml2xmlin/hostdev.xml     |   10 +++
 tests/networkxml2xmlout/hostdev-pf.xml |    7 ++
 tests/networkxml2xmlout/hostdev.xml    |   10 +++
 tests/networkxml2xmltest.c             |    2 +
 11 files changed, 266 insertions(+), 87 deletions(-)

diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
index 9dbda4a..766f9a0 100644
--- a/docs/schemas/basictypes.rng
+++ b/docs/schemas/basictypes.rng
@@ -54,6 +54,31 @@
     </choice>
   </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>
+
   <!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
   <!-- The lowest bit of the 1st byte is the "multicast" bit. a         -->
   <!-- uniMacAddr requires that bit to be 0, and a multiMacAddr         -->
@@ -167,4 +192,25 @@
     <ref name='unsignedLong'/>
   </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/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4903ca6..35e9f82 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2652,30 +2652,6 @@
       </attribute>
     </optional>
   </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="driveaddress">
     <optional>
       <attribute name="controller">
@@ -3376,26 +3352,6 @@
       <param name="pattern">((0x)?[0-9a-fA-F]{1,3}\.){0,3}(0x)?[0-9a-fA-F]{1,3}</param>
     </data>
   </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>
   <define name="driveController">
     <data type="string">
       <param name="pattern">[0-9]{1,2}</param>
diff --git a/docs/schemas/network.rng b/docs/schemas/network.rng
index e55105a..4abfd91 100644
--- a/docs/schemas/network.rng
+++ b/docs/schemas/network.rng
@@ -87,22 +87,51 @@
                   <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>
-                  <optional>
-                    <attribute name="connections">
-                      <data type="unsignedInt"/>
-                    </attribute>
-                  </optional>
-                </element>
-              </zeroOrMore>
+              <choice>
+                <group>
+                  <zeroOrMore>
+                    <element name='interface'>
+                      <attribute name='dev'>
+                        <ref name='deviceName'/>
+                      </attribute>
+                      <optional>
+                        <attribute name="connections">
+                          <data type="unsignedInt"/>
+                        </attribute>
+                      </optional>
+                    </element>
+                  </zeroOrMore>
+                </group>
+                <group>
+                  <zeroOrMore>
+                    <element name='address'>
+                      <attribute name='type'>
+                        <value>pci</value>
+                      </attribute>
+                      <ref name="pciaddress"/>
+                      <optional>
+                        <attribute name="connections">
+                          <data type="unsignedInt"/>
+                        </attribute>
+                      </optional>
+                    </element>
+                  </zeroOrMore>
+                </group>
+              </choice>
               <optional>
                 <element name='pf'>
                   <attribute name='dev'>
diff --git a/src/conf/network_conf.c b/src/conf/network_conf.c
index db8c62f..2be7346 100644
--- a/src/conf/network_conf.c
+++ b/src/conf/network_conf.c
@@ -50,7 +50,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", "netdev")
 
 virNetworkObjPtr virNetworkFindByUUID(const virNetworkObjListPtr nets,
                                       const unsigned char *uuid)
@@ -96,7 +101,8 @@ virPortGroupDefClear(virPortGroupDefPtr def)
 static void
 virNetworkForwardIfDefClear(virNetworkForwardIfDefPtr def)
 {
-    VIR_FREE(def->dev);
+    if (def->type == VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV)
+        VIR_FREE(def->device.dev);
 }
 
 static void
@@ -943,11 +949,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;
     xmlNodePtr vlanNode;
@@ -1100,17 +1109,35 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
         }
 
         forwardDev = virXPathString("string(./@dev)", ctxt);
+        forwardManaged = virXPathString("string(./@managed)", ctxt);
+        if(forwardManaged != NULL) {
+            if (STRCASEEQ(forwardManaged, "yes"))
+                def->managed = 1;
+        }
 
         /* 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"));
+            goto error;
+        }
+
+        if ((nForwardPfs > 0) && ((nForwardIfs > 0) || (nForwardAddrs > 0))) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Address/interface attributes and Physical function are mutually exclusive "));
+            goto error;
+        }
+
         if (nForwardPfs == 1) {
             if (VIR_ALLOC_N(def->forwardPfs, nForwardPfs) < 0) {
                 virReportOOMError();
@@ -1139,7 +1166,53 @@ 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[ii], "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[ii], &(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;
+                }
+                VIR_FREE(type);
+                def->nForwardIfs++;
+            }
+        }
+        else if (nForwardIfs > 0 || forwardDev) {
             int ii;
 
             /* allocate array to hold all the portgroups */
@@ -1149,7 +1222,8 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
             }
 
             if (forwardDev) {
-                def->forwardIfs[0].dev = forwardDev;
+                def->forwardIfs[0].device.dev = forwardDev;
+                def->forwardIfs[0].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
                 forwardDev = NULL;
                 def->nForwardIfs++;
             }
@@ -1167,10 +1241,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;
                     }
@@ -1178,15 +1252,18 @@ virNetworkDefParseXML(xmlXPathContextPtr ctxt)
                     continue;
                 }
 
-                def->forwardIfs[ii].dev = forwardDev;
+                def->forwardIfs[ii].device.dev = forwardDev;
                 forwardDev = NULL;
+                def->forwardIfs[ii].type = VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV;
                 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:
@@ -1211,6 +1288,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')"),
@@ -1502,6 +1580,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) ? "" : "/");
 
@@ -1513,14 +1597,24 @@ 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'",
-                                      def->forwardIfs[ii].dev);
-                if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
-                    (def->forwardIfs[ii].connections > 0)) {
-                    virBufferAsprintf(&buf, " connections='%d'",
-                                      def->forwardIfs[ii].connections);
+                if (def->forwardType != VIR_NETWORK_FORWARD_HOSTDEV) {
+                    virBufferEscapeString(&buf, "    <interface dev='%s'",
+                                          def->forwardIfs[ii].device.dev);
+                    if (!(flags & VIR_NETWORK_XML_INACTIVE) &&
+                        (def->forwardIfs[ii].connections > 0)) {
+                        virBufferAsprintf(&buf, " connections='%d'",
+                                          def->forwardIfs[ii].connections);
+                    }
+                    virBufferAddLit(&buf, "/>\n");  
+                }
+                else {
+                    if (def->forwardIfs[ii].type ==  VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_PCI) {
+                        if (virDevicePCIAddressFormat(&buf,
+                                                      def->forwardIfs[ii].device.pci,
+                                                      true) < 0) 
+                            goto error;
+                    }
                 }
-                virBufferAddLit(&buf, "/>\n");
             }
         }
         if (def->nForwardPfs || def->nForwardIfs)
diff --git a/src/conf/network_conf.h b/src/conf/network_conf.h
index a029f70..6b080f5 100644
--- a/src/conf/network_conf.h
+++ b/src/conf/network_conf.h
@@ -37,6 +37,7 @@
 # include "virnetdevvportprofile.h"
 # include "virnetdevvlan.h"
 # include "virmacaddr.h"
+# include "device_conf.h"
 
 enum virNetworkForwardType {
     VIR_NETWORK_FORWARD_NONE   = 0,
@@ -46,10 +47,20 @@ 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,
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_NETDEV,
+    /* USB Device to be added here when supported */
+    
+    VIR_NETWORK_FORWARD_HOSTDEV_DEVICE_LAST,
+};
+
 typedef struct _virNetworkDHCPRangeDef virNetworkDHCPRangeDef;
 typedef virNetworkDHCPRangeDef *virNetworkDHCPRangeDefPtr;
 struct _virNetworkDHCPRangeDef {
@@ -132,14 +143,20 @@ struct _virNetworkIpDef {
 typedef struct _virNetworkForwardIfDef virNetworkForwardIfDef;
 typedef virNetworkForwardIfDef *virNetworkForwardIfDefPtr;
 struct _virNetworkForwardIfDef {
-    char *dev;      /* name of device */
-    int   connections; /* how many guest interfaces are connected to this 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 connections; /* how many guest interfaces are connected to this device? */
 };
 
 typedef struct _virNetworkForwardPfDef virNetworkForwardPfDef;
 typedef virNetworkForwardPfDef *virNetworkForwardPfDefPtr;
 struct _virNetworkForwardPfDef {
-    char *dev;      /* name of device */
+    char *dev;      /* name of device */ 
+    int connections; /* how many guest interfaces are connected to this device? */
 };
 
 typedef struct _virPortGroupDef virPortGroupDef;
@@ -168,6 +185,7 @@ 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.
@@ -244,7 +262,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 ff17c7f..ddd66e5 100644
--- a/src/network/bridge_driver.c
+++ b/src/network/bridge_driver.c
@@ -2805,8 +2805,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;
         }
@@ -3057,7 +3057,7 @@ networkAllocateActualDevice(virDomainNetDefPtr iface)
                                netdef->name);
                 goto error;
             }
-            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 error;
@@ -3115,7 +3115,7 @@ validate:
         /* we are now assured of success, so mark the allocation */
         dev->connections++;
         VIR_DEBUG("Using physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
     if (netdef) {
@@ -3198,7 +3198,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* find the matching interface and increment its connections */
 
         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;
             }
@@ -3229,7 +3229,7 @@ networkNotifyActualDevice(virDomainNetDefPtr iface)
         /* we are now assured of success, so mark the allocation */
         dev->connections++;
         VIR_DEBUG("Using physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
 success:
@@ -3305,7 +3305,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;
             }
@@ -3320,7 +3320,7 @@ networkReleaseActualDevice(virDomainNetDefPtr iface)
 
         dev->connections--;
         VIR_DEBUG("Releasing physical device %s, %d connections",
-                  dev->dev, dev->connections);
+                  dev->device.dev, dev->connections);
     }
 
 success:
@@ -3410,7 +3410,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..fc82c55
--- /dev/null
+++ b/tests/networkxml2xmlin/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/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 5a5531a..e57d190 100644
--- a/tests/networkxml2xmltest.c
+++ b/tests/networkxml2xmltest.c
@@ -106,6 +106,8 @@ mymain(void)
     DO_TEST("bandwidth-network");
     DO_TEST("openvswitch-net");
     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