[libvirt] [PATCH 1/8] RNG updates, new xml parser/formatter code for interface type=hostdev-hybrid

Shradha Shah sshah at solarflare.com
Fri Sep 7 16:14:51 UTC 2012


This patch introduces the new interface type='hostdev-hybrid' along with
attribute managed
Includes updates to the domain RNG and new xml parser/formatter code.
Also introduces a ephemeral tag for hybrid hostdevs.
The ephemeral tag for hybrid hostdevs will be useful for live migration
support at a later stage.
---
 docs/formatdomain.html.in                          |   29 ++++++
 docs/schemas/domaincommon.rng                      |   50 ++++++++++
 src/conf/domain_conf.c                             |   96 +++++++++++++++++---
 src/conf/domain_conf.h                             |    2 +
 src/uml/uml_conf.c                                 |    5 +
 src/xenxs/xen_sxpr.c                               |    1 +
 .../qemuxml2argv-net-hostdevhybrid.args            |    8 ++
 .../qemuxml2argv-net-hostdevhybrid.xml             |   35 +++++++
 tests/qemuxml2argvtest.c                           |    2 +
 .../qemuxml2xmlout-net-hostdevhybrid.xml           |   40 ++++++++
 tests/qemuxml2xmltest.c                            |    1 +
 11 files changed, 256 insertions(+), 13 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 503685f..70cf362 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2659,6 +2659,20 @@
       guest instead of <interface type='hostdev'/>.
     </p>
 
+    <p>
+      Libvirt later than 0.10.0 also supports "intelligent passthrough"
+      of VF in the hybrid mode. This is done by using the <interface
+      type='hostdev-hybrid'/> functionality. Similar to <interface
+      type='hostdev'/> the device's MAC address is first optionally
+      configured and the device is optionally associated with an 802.1Qbh
+      capable switch using an optionally specified <virtualport>
+      element (see the examples of virtualport given above for
+      type='direct' network devices). The Vf is passed into the guest as
+      a PCI device and at the same time a virtual interface with
+      type='direct' mode='bridge' is created in the guest. This hybrid mode
+      of intelligent passthrough makes Live migration possible.
+    </p>
+
 <pre>
   ...
   <devices>
@@ -2674,6 +2688,21 @@
   </devices>
   ...</pre>
 
+<pre>
+  ...
+  <devices>
+    <interface type='hostdev-hybrid'>
+      <source>
+        <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
+      </source>
+      <mac address='52:54:00:6d:90:02'>
+      <virtualport type='802.1Qbh'>
+        <parameters profileid='finance'/>
+      </virtualport>
+    </interface>
+  </devices>
+  ...</pre>
+
 
     <h5><a name="elementsNICSMulticast">Multicast tunnel</a></h5>
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c2c6184..eedc255 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1677,6 +1677,56 @@
             <ref name="interface-options"/>
           </interleave>
         </group>
+        <group>
+          <attribute name="type">
+            <value>hostdev-hybrid</value>
+          </attribute>
+          <optional>
+            <attribute name="managed">
+              <choice>
+                <value>yes</value>
+                <value>no</value>
+              </choice>
+            </attribute>
+          </optional>
+          <interleave>
+            <element name="source">
+              <choice>
+                <group>
+                  <ref name="usbproduct"/>
+                  <optional>
+                    <ref name="usbaddress"/>
+                  </optional>
+                </group>
+                <element name="address">
+                  <choice>
+                    <group>
+                      <attribute name="type">
+                        <value>pci</value>
+                      </attribute>
+                      <ref name="pciaddress"/>
+                    </group>
+                    <group>
+                      <attribute name="type">
+                        <value>usb</value>
+                      </attribute>
+                      <attribute name="bus">
+                        <ref name="usbAddr"/>
+                      </attribute>
+                      <attribute name="device">
+                        <ref name="usbPort"/>
+                      </attribute>
+                    </group>
+                  </choice>
+                </element>
+              </choice>
+            </element>
+            <optional>
+              <ref name="virtualPortProfile"/>
+            </optional>
+            <ref name="interface-options"/>
+          </interleave>
+        </group>
       </choice>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 8952b69..d8ab40c 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -293,7 +293,8 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
               "bridge",
               "internal",
               "direct",
-              "hostdev")
+              "hostdev",
+              "hostdev-hybrid")
 
 VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
               "default",
@@ -1020,6 +1021,9 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
         virDomainHostdevDefClear(&def->data.hostdev.def);
         break;
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        virDomainHostdevDefClear(&def->data.hostdev.def);
+        break;
     default:
         break;
     }
@@ -1072,6 +1076,10 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
         virDomainHostdevDefClear(&def->data.hostdev.def);
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        virDomainHostdevDefClear(&def->data.hostdev.def);
+        break;
+
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
@@ -1563,8 +1571,10 @@ void virDomainDefFree(virDomainDefPtr def)
      * so the original object must still be available during the call
      * to virDomainHostdevDefFree().
      */
-    for (i = 0 ; i < def->nhostdevs ; i++)
-        virDomainHostdevDefFree(def->hostdevs[i]);
+    for (i = 0 ; i < def->nhostdevs ; i++) {
+        if (def->hostdevs[i]->ephemeral == 0)
+            virDomainHostdevDefFree(def->hostdevs[i]);
+    }
     VIR_FREE(def->hostdevs);
 
     for (i = 0 ; i < def->nleases ; i++)
@@ -4525,6 +4535,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
     if (actual->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
         actual->type != VIR_DOMAIN_NET_TYPE_DIRECT &&
         actual->type != VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+        actual->type != VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID &&
         actual->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
         virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("unsupported type '%s' in interface's <actual> element"),
@@ -4536,7 +4547,8 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
     if (virtPortNode) {
         if (actual->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
             actual->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
-            actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+            actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+            actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
             /* the virtualport in <actual> should always already
              * have an instanceid/interfaceid if its required,
              * so don't let the parser generate one */
@@ -4589,6 +4601,30 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
                                        hostdev, flags) < 0) {
             goto error;
         }
+    } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
+        virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
+
+        hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+        if (VIR_ALLOC(hostdev->info) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+        hostdev->ephemeral = 1;
+        /* The helper function expects type to already be found and
+         * passed in as a string, since it is in a different place in
+         * NetDef vs HostdevDef.
+         */
+        addrtype = virXPathString("string(./source/address/@type)", ctxt);
+        /* if not explicitly stated, source/vendor implies usb device */
+        if (!addrtype && virXPathNode("./source/vendor", ctxt) &&
+            (addrtype = strdup("usb")) == NULL) {
+            virReportOOMError();
+            goto error;
+        }
+        if (virDomainHostdevPartsParse(node, ctxt, NULL, addrtype,
+                                       hostdev, flags) < 0) {
+            goto error;
+        }
     }
 
     bandwidth_node = virXPathNode("./bandwidth", ctxt);
@@ -4708,7 +4744,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
                     }
                 } else if (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
                            def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
-                           def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+                           def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+                           def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
                     if (!(def->virtPortProfile
                           = virNetDevVPortProfileParse(cur,
                                                        VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS|
@@ -4968,6 +5005,27 @@ virDomainNetDefParseXML(virCapsPtr caps,
         }
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        hostdev = &def->data.hostdev.def;
+        hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+        if (VIR_ALLOC(hostdev->info) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+        hostdev->ephemeral = 1;
+        addrtype = virXPathString("string(./source/address/@type)", ctxt);
+        /* if not explicitly stated, source/vendor implies usb device */
+        if (!addrtype && virXPathNode("./source/vendor", ctxt) &&
+            ((addrtype = strdup("usb")) == NULL)) {
+            virReportOOMError();
+            goto error;
+        }
+        if (virDomainHostdevPartsParse(node, ctxt, NULL, addrtype,
+                                       hostdev, flags) < 0) {
+            goto error;
+        }
+        break;
+
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
@@ -7609,7 +7667,8 @@ int virDomainNetInsert(virDomainDefPtr def, virDomainNetDefPtr net)
         return -1;
     def->nets[def->nnets]  = net;
     def->nnets++;
-    if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+    if ((net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
         /* hostdev net devices must also exist in the hostdevs array */
         return virDomainHostdevInsert(def, &net->data.hostdev.def);
     }
@@ -7631,7 +7690,8 @@ virDomainNetRemove(virDomainDefPtr def, size_t i)
 {
     virDomainNetDefPtr net = def->nets[i];
 
-    if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+    if ((net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) {
         /* hostdev net devices are normally also be in the hostdevs
          * array, but might have already been removed by the time we
          * get here.
@@ -8995,8 +9055,10 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps,
 
         def->nets[def->nnets++] = net;
 
-        /* <interface type='hostdev'> must also be in the hostdevs array */
-        if (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+        /* <interface type='hostdev' and 'hostdev-hybrid'> must also be in
+           the hostdevs array */
+        if (((net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+             (net->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) &&
             virDomainHostdevInsert(def, &net->data.hostdev.def) < 0) {
             goto no_memory;
         }
@@ -11941,7 +12003,8 @@ virDomainActualNetDefFormat(virBufferPtr buf,
     }
 
     virBufferAsprintf(buf, "<actual type='%s'", type);
-    if (def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+    if ((def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+        def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) &&
         def->data.hostdev.def.managed) {
         virBufferAddLit(buf, " managed='yes'");
     }
@@ -11971,6 +12034,7 @@ virDomainActualNetDefFormat(virBufferPtr buf,
         break;
 
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
                                          flags, true) < 0) {
             return -1;
@@ -12011,7 +12075,8 @@ virDomainNetDefFormat(virBufferPtr buf,
     }
 
     virBufferAsprintf(buf, "    <interface type='%s'", type);
-    if (def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV &&
+    if (((def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)) &&
         def->data.hostdev.def.managed) {
         virBufferAddLit(buf, " managed='yes'");
     }
@@ -12078,6 +12143,7 @@ virDomainNetDefFormat(virBufferPtr buf,
         break;
 
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
                                          flags, true) < 0) {
             return -1;
@@ -14620,10 +14686,12 @@ virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
 virDomainHostdevDefPtr
 virDomainNetGetActualHostdev(virDomainNetDefPtr iface)
 {
-    if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
+    if ((iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) ||
+        (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID))
         return &iface->data.hostdev.def;
     if (iface->type == VIR_DOMAIN_NET_TYPE_NETWORK &&
-        iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+         iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID)){
         return &iface->data.network.actual->data.hostdev.def;
     }
     return NULL;
@@ -14636,6 +14704,7 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
     case VIR_DOMAIN_NET_TYPE_DIRECT:
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         return iface->virtPortProfile;
     case VIR_DOMAIN_NET_TYPE_NETWORK:
         if (!iface->data.network.actual)
@@ -14644,6 +14713,7 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
         case VIR_DOMAIN_NET_TYPE_DIRECT:
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
             return iface->data.network.actual->virtPortProfile;
         default:
             return NULL;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3995c2d..156eb32 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -378,6 +378,7 @@ struct _virDomainHostdevDef {
     virDomainDeviceDef parent; /* higher level Def containing this */
     int mode; /* enum virDomainHostdevMode */
     unsigned int managed : 1;
+    unsigned int ephemeral : 1;
     union {
         virDomainHostdevSubsys subsys;
         struct {
@@ -727,6 +728,7 @@ enum virDomainNetType {
     VIR_DOMAIN_NET_TYPE_INTERNAL,
     VIR_DOMAIN_NET_TYPE_DIRECT,
     VIR_DOMAIN_NET_TYPE_HOSTDEV,
+    VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID,
 
     VIR_DOMAIN_NET_TYPE_LAST,
 };
diff --git a/src/uml/uml_conf.c b/src/uml/uml_conf.c
index 410f3e2..edea034 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -261,6 +261,11 @@ umlBuildCommandLineNet(virConnectPtr conn,
                        _("hostdev networking type not supported"));
         goto error;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("hostdev-hybrid networking type not supported"));
+        goto error;
+
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
     }
diff --git a/src/xenxs/xen_sxpr.c b/src/xenxs/xen_sxpr.c
index 8bb3849..c94b787 100644
--- a/src/xenxs/xen_sxpr.c
+++ b/src/xenxs/xen_sxpr.c
@@ -1987,6 +1987,7 @@ xenFormatSxprNet(virConnectPtr conn,
     case VIR_DOMAIN_NET_TYPE_INTERNAL:
     case VIR_DOMAIN_NET_TYPE_DIRECT:
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
     }
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.args b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.args
new file mode 100644
index 0000000..a4c50d1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.args
@@ -0,0 +1,8 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S \
+-M pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c \
+-hda /dev/HostVG/QEMUGuest1 \
+-device rtl8139,vlan=0,id=net0,mac=00:11:22:33:44:55,bus=pci.0,addr=0x3 \
+-net user,vlan=0,name=hostnet0 -usb \
+-device pci-assign,host=03:07.1,id=hostdev0,bus=pci.0,addr=0x4 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.xml
new file mode 100644
index 0000000..dcf3fd1
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.xml
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <interface type='hostdev-hybrid' managed='yes'>
+      <mac address='00:11:22:33:44:55'/>
+      <source>
+        <address type='pci' domain='0x0002' bus='0x03' slot='0x07' function='0x1'/>
+      </source>
+      <virtualport type='802.1Qbg'>
+        <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
+      </virtualport>
+    </interface>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 47c3f6c..4155352 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -576,6 +576,8 @@ mymain(void)
     DO_TEST("net-mcast", NONE);
     DO_TEST("net-hostdev",
             QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
+    DO_TEST("net-hostdevhybrid",
+            QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_NODEFCONFIG);
 
     DO_TEST("serial-vc", NONE);
     DO_TEST("serial-pty", NONE);
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-hostdevhybrid.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-hostdevhybrid.xml
new file mode 100644
index 0000000..5ab9ed3
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-net-hostdevhybrid.xml
@@ -0,0 +1,40 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory unit='KiB'>219136</memory>
+  <currentMemory unit='KiB'>219136</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <os>
+    <type arch='i686' machine='pc'>hvm</type>
+    <boot dev='hd'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>destroy</on_crash>
+  <devices>
+    <emulator>/usr/bin/qemu</emulator>
+    <disk type='block' device='disk'>
+      <source dev='/dev/HostVG/QEMUGuest1'/>
+      <target dev='hda' bus='ide'/>
+      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
+    </disk>
+    <controller type='usb' index='0'/>
+    <controller type='ide' index='0'/>
+    <interface type='hostdev-hybrid' managed='yes'>
+      <mac address='00:11:22:33:44:55'/>
+      <source>
+        <address type='pci' domain='0x0002' bus='0x03' slot='0x07' function='0x1'/>
+      </source>
+      <virtualport type='802.1Qbg'>
+        <parameters managerid='11' typeid='1193047' typeidversion='2' instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
+      </virtualport>
+    </interface>
+    <hostdev mode='subsystem' type='pci' managed='yes'>
+      <source>
+        <address domain='0x0002' bus='0x03' slot='0x07' function='0x1'/>
+      </source>
+    </hostdev>
+    <memballoon model='virtio'/>
+  </devices>
+</domain>
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 87d9e77..73846e2 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -181,6 +181,7 @@ mymain(void)
     DO_TEST("net-eth-ifname");
     DO_TEST("net-virtio-network-portgroup");
     DO_TEST("net-hostdev");
+    DO_TEST_DIFFERENT("net-hostdevhybrid");
     DO_TEST("net-openvswitch");
     DO_TEST("sound");
     DO_TEST("sound-device");
-- 
1.7.4.4





More information about the libvir-list mailing list