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

[libvirt] [PATCH 07/15] RNG updates, new xml parser/formatter code to support interface type=hostdev-hybrid



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.
---
 docs/formatdomain.html.in                          |   29 ++++++
 docs/schemas/domaincommon.rng                      |   50 ++++++++++
 src/conf/domain_conf.c                             |   97 ++++++++++++++++++--
 src/conf/domain_conf.h                             |    1 +
 src/uml/uml_conf.c                                 |    5 +
 src/xenxs/xen_sxpr.c                               |    1 +
 .../qemuxml2argv-net-hostdevhybrid.args            |    6 +
 .../qemuxml2argv-net-hostdevhybrid.xml             |   35 +++++++
 tests/qemuxml2xmltest.c                            |    1 +
 9 files changed, 215 insertions(+), 10 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index f97c630..045e655 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -2504,6 +2504,20 @@
       guest instead of <interface type='hostdev'/>.
     </p>
 
+    <p>
+      Libvirt later than 0.9.13 also supports "intelligent passthrough"
+      of VF in the hybrid mode. This is done by using the &lt;interface 
+      type='hostdev-hybrid'/&gt; functionality. Similar to &lt;interface 
+      type='hostdev'/&gt; the device's MAC address is first optionally
+      configured and the device is associated with an 802.1Qbh capable 
+      switch using an optionally specified &lt;virtualport&gt; 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>
   ...
   &lt;devices&gt;
@@ -2519,6 +2533,21 @@
   &lt;/devices&gt;
   ...</pre>
 
+<pre>
+  ...
+  &lt;devices&gt;
+    &lt;interface type='hostdev-hybrid'&gt;
+      &lt;source&gt;
+        &lt;address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/&gt;
+      &lt;/source&gt;
+      &lt;mac address='52:54:00:6d:90:02'&gt;
+      &lt;virtualport type='802.1Qbh'&gt;
+        &lt;parameters profileid='finance'/&gt;
+      &lt;/virtualport&gt;
+    &lt;/interface&gt;
+  &lt;/devices&gt;
+  ...</pre>
+
 
     <h5><a name="elementsNICSMulticast">Multicast tunnel</a></h5>
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index c85d763..2f95e91 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -1597,6 +1597,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 ecad6cc..39b5cdb 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -289,7 +289,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",
@@ -1023,6 +1024,10 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
         virDomainHostdevDefClear(&def->data.hostdev.def);
         VIR_FREE(def->data.hostdev.virtPortProfile);
         break;
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        virDomainHostdevDefClear(&def->data.hostdev.def);
+        VIR_FREE(def->data.hostdev.virtPortProfile);
+        break;
     default:
         break;
     }
@@ -1078,6 +1083,11 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
         VIR_FREE(def->data.hostdev.virtPortProfile);
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
+        virDomainHostdevDefClear(&def->data.hostdev.def);
+        VIR_FREE(def->data.hostdev.virtPortProfile);
+        break;
+
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
@@ -4312,6 +4322,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"),
@@ -4375,6 +4386,37 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
                virNetDevVPortProfileParse(virtPortNode)))) {
             goto error;
         }
+    } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) {
+        xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
+        virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
+
+        hostdev->parent.type = VIR_DOMAIN_DEVICE_NONE;
+        
+        if (VIR_ALLOC(hostdev->info) < 0) {
+            virReportOOMError();
+            goto error;
+        }
+        /* 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;
+        }
+        
+        if (virtPortNode &&
+            (!(actual->data.hostdev.virtPortProfile =
+               virNetDevVPortProfileParse(virtPortNode)))) {
+            goto error;
+        }
     }
 
     bandwidth_node = virXPathNode("./bandwidth", ctxt);
@@ -4485,7 +4527,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
                        (def->type == VIR_DOMAIN_NET_TYPE_DIRECT ||
                         def->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
                         def->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
-                        def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+                        def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV ||
+                        def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID) &&
                        xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
                 if (!(virtPort = virNetDevVPortProfileParse(cur)))
                     goto error;
@@ -4733,6 +4776,28 @@ virDomainNetDefParseXML(virCapsPtr caps,
         def->data.hostdev.virtPortProfile = virtPort;
         virtPort = NULL;
         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;
+        }
+        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;
+        }
+        def->data.hostdev.virtPortProfile = virtPort;
+        virtPort = NULL;
+        break;
 
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
@@ -7352,7 +7417,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);
     }
@@ -7374,7 +7440,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.
@@ -8675,8 +8742,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;
         }
@@ -11486,7 +11555,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'");
     }
@@ -11525,6 +11595,7 @@ virDomainActualNetDefFormat(virBufferPtr buf,
         break;
 
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         virBufferAdjustIndent(buf, 8);
         if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
                                          flags, true) < 0) {
@@ -11571,7 +11642,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'");
     }
@@ -11649,6 +11721,7 @@ virDomainNetDefFormat(virBufferPtr buf,
         break;
 
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         virBufferAdjustIndent(buf, 6);
         if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
                                          flags, true) < 0) {
@@ -14982,10 +15055,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;
@@ -15000,6 +15075,7 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
         return iface->data.bridge.virtPortProfile;
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
         return iface->data.hostdev.virtPortProfile;
     case VIR_DOMAIN_NET_TYPE_NETWORK:
         if (!iface->data.network.actual)
@@ -15010,6 +15086,7 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
             return iface->data.network.actual->data.bridge.virtPortProfile;
         case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        case VIR_DOMAIN_NET_TYPE_HOSTDEV_HYBRID:
             return iface->data.network.actual->data.hostdev.virtPortProfile;
         default:
             return NULL;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a2e4816..7bcaee4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -710,6 +710,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 4c299d8..63fc27c 100644
--- a/src/uml/uml_conf.c
+++ b/src/uml/uml_conf.c
@@ -260,6 +260,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..398a0cd
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdevhybrid.args
@@ -0,0 +1,6 @@
+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 -usb \
+-device pci-assign,host=03:07.1,id=hostdev0,bus=pci.0,addr=0x3 \
+-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
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/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index dcdba4f..46ad421 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -178,6 +178,7 @@ mymain(void)
     DO_TEST("net-eth-ifname");
     DO_TEST("net-virtio-network-portgroup");
     DO_TEST("net-hostdev");
+    DO_TEST("net-hostdevhybrid");
     DO_TEST("sound");
     DO_TEST("sound-device");
     DO_TEST("net-bandwidth");
-- 
1.7.4.4



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