]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: parse/format type='hostdev' network interfaces
authorLaine Stump <laine@laine.org>
Wed, 15 Feb 2012 17:37:15 +0000 (12:37 -0500)
committerLaine Stump <laine@laine.org>
Tue, 6 Mar 2012 04:24:28 +0000 (23:24 -0500)
This is the new interface type that sets up an SR-IOV PCI network
device to be assigned to the guest with PCI passthrough after
initializing some network device-specific things from the config
(e.g. MAC address, virtualport profile parameters). Here is an example
of the syntax:

  <interface type='hostdev' managed='yes'>
    <source>
      <address type='pci' domain='0' bus='0' slot='4' function='3'/>
    </source>
    <mac address='00:11:22:33:44:55'/>
    <address type='pci' domain='0' bus='0' slot='7' function='0'/>
  </interface>

This would assign the PCI card from bus 0 slot 4 function 3 on the
host, to bus 0 slot 7 function 0 on the guest, but would first set the
MAC address of the card to 00:11:22:33:44:55.

NB: The parser and formatter don't care if the PCI card being
specified is a standard single function network adapter, or a virtual
function (VF) of an SR-IOV capable network adapter, but the upcoming
code that implements the back end of this config will work *only* with
SR-IOV VFs. This is because modifying the mac address of a standard
network adapter prior to assigning it to a guest is pointless - part
of the device reset that occurs during that process will reset the MAC
address to the value programmed into the card's firmware.

Although it's not supported by any of libvirt's hypervisor drivers,
usb network hostdevs are also supported in the parser and formatter
for completeness and consistency. <source> syntax is identical to that
for plain <hostdev> devices, except that the <address> element should
have "type='usb'" added if bus/device are specified:

  <interface type='hostdev'>
    <source>
      <address type='usb' bus='0' device='4'/>
    </source>
    <mac address='00:11:22:33:44:55'/>
  </interface>

If the vendor/product form of usb specification is used, type='usb'
is implied:

  <interface type='hostdev'>
    <source>
      <vendor id='0x0012'/>
      <product id='0x24dd'/>
    </source>
    <mac address='00:11:22:33:44:55'/>
  </interface>

Again, the upcoming patch to fill in the backend of this functionality
will log an error and fail with "Unsupported Config" if you actually
try to assign a USB network adapter to a guest using <interface
type='hostdev'> - just use a standard <hostdev> entry in that case
(and also for single-port PCI adapters).

docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_command.c
src/uml/uml_conf.c
src/xenxs/xen_sxpr.c
tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml [new file with mode: 0644]
tests/qemuxml2xmltest.c

index a61895f9f93342e775a9696e216cb6f1b4f41583..6434ae5bc707278344a967f77135b2e6dfeef548 100644 (file)
   ...
   </pre>
 
+
+    <h5><a name="elementsNICSHostdev">PCI Passthrough</a></h5>
+
+    <p>
+      A PCI network device (specified by the &lt;source&gt; element)
+      is directly assigned to the guest using generic device
+      passthrough, after first optionally setting the device's MAC
+      address to the configured value, and associating the device with
+      an 802.1Qgh capable switch using an optionally specified
+      %lt;virtualport%gt; element (see the examples of virtualport
+      given above for type='direct' network devices). Note that - due
+      to limitations in standard single-port PCI ethernet card driver
+      design - only SR-IOV (Single Root I/O Virtualization) virtual
+      function (VF) devices can be assigned in this manner; to assign
+      a standard single-port PCI or PCIe ethernet card to a guest, use
+      the traditional &lt;hostdev&gt; device definition and
+      <span class="since">Since 0.9.11</span>
+    </p>
+
+    <p>
+      Note that this "intelligent passthrough" of network devices is
+      very similar to the functionality of a standard &lt;hostdev&gt;
+      device, the difference being that this method allows specifying
+      a MAC address and &lt;virtualport&gt; for the passed-through
+      device. If these capabilities are not required, if you have a
+      standard single-port PCI, PCIe, or USB network card that doesn't
+      support SR-IOV (and hence would anyway lose the configured MAC
+      address during reset after being assigned to the guest domain),
+      or if you are using a version of libvirt older than 0.9.11, you
+      should use standard &lt;hostdev&gt; to assign the device to the
+      guest instead of &lt;interface type='hostdev'/&gt;.
+    </p>
+
+<pre>
+  ...
+  &lt;devices&gt;
+    &lt;interface type='hostdev'&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>
 
     <p>
index 3908733283840ed80757f0d3b4174c0745c35cda..a905457a767bf1c0f525ac35642e23e83882f17e 100644 (file)
             </optional>
           </interleave>
         </group>
+        <group>
+          <attribute name="type">
+            <value>hostdev</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>
index 94ee634ca3fa47670fcb61ec4037eb4614b27b9c..70e92242f72a18d75d5fe439181222e64093b70d 100644 (file)
@@ -286,7 +286,8 @@ VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
               "network",
               "bridge",
               "internal",
-              "direct")
+              "direct",
+              "hostdev")
 
 VIR_ENUM_IMPL(virDomainNetBackend, VIR_DOMAIN_NET_BACKEND_TYPE_LAST,
               "default",
@@ -971,6 +972,10 @@ virDomainActualNetDefFree(virDomainActualNetDefPtr def)
         VIR_FREE(def->data.direct.linkdev);
         VIR_FREE(def->data.direct.virtPortProfile);
         break;
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        virDomainHostdevDefClear(&def->data.hostdev.def);
+        VIR_FREE(def->data.hostdev.virtPortProfile);
+        break;
     default:
         break;
     }
@@ -1021,6 +1026,11 @@ void virDomainNetDefFree(virDomainNetDefPtr def)
         VIR_FREE(def->data.direct.virtPortProfile);
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        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;
@@ -4115,7 +4125,9 @@ cleanup:
 static int
 virDomainActualNetDefParseXML(xmlNodePtr node,
                               xmlXPathContextPtr ctxt,
-                              virDomainActualNetDefPtr *def)
+                              virDomainNetDefPtr parent,
+                              virDomainActualNetDefPtr *def,
+                              unsigned int flags)
 {
     virDomainActualNetDefPtr actual = NULL;
     int ret = -1;
@@ -4123,6 +4135,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
     xmlNodePtr bandwidth_node = NULL;
     char *type = NULL;
     char *mode = NULL;
+    char *addrtype = NULL;
 
     if (VIR_ALLOC(actual) < 0) {
         virReportOOMError();
@@ -4144,6 +4157,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_NETWORK) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                              _("unsupported type '%s' in interface's <actual> element"),
@@ -4179,6 +4193,34 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
             (!(actual->data.direct.virtPortProfile =
                virNetDevVPortProfileParse(virtPortNode))))
             goto error;
+    } else if (actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+        xmlNodePtr virtPortNode = virXPathNode("./virtualport", ctxt);
+        virDomainHostdevDefPtr hostdev = &actual->data.hostdev.def;
+
+        hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->parent.data.net = parent;
+        hostdev->info = &parent->info;
+        /* 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);
@@ -4192,6 +4234,7 @@ virDomainActualNetDefParseXML(xmlNodePtr node,
 error:
     VIR_FREE(type);
     VIR_FREE(mode);
+    VIR_FREE(addrtype);
     virDomainActualNetDefFree(actual);
 
     ctxt->node = save_ctxt;
@@ -4213,6 +4256,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
                         unsigned int flags)
 {
     virDomainNetDefPtr def;
+    virDomainHostdevDefPtr hostdev;
     xmlNodePtr cur;
     char *macaddr = NULL;
     char *type = NULL;
@@ -4234,6 +4278,7 @@ virDomainNetDefParseXML(virCapsPtr caps,
     char *devaddr = NULL;
     char *mode = NULL;
     char *linkstate = NULL;
+    char *addrtype = NULL;
     virNWFilterHashTablePtr filterparams = NULL;
     virNetDevVPortProfilePtr virtPort = NULL;
     virDomainActualNetDefPtr actual = NULL;
@@ -4286,7 +4331,8 @@ virDomainNetDefParseXML(virCapsPtr caps,
             } else if ((virtPort == NULL) &&
                        ((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_BRIDGE) ||
+                        (def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) &&
                        xmlStrEqual(cur->name, BAD_CAST "virtualport")) {
                 if (!(virtPort = virNetDevVPortProfileParse(cur)))
                     goto error;
@@ -4338,8 +4384,10 @@ virDomainNetDefParseXML(virCapsPtr caps,
                        (flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) &&
                        (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
                        xmlStrEqual(cur->name, BAD_CAST "actual")) {
-                if (virDomainActualNetDefParseXML(cur, ctxt, &actual) < 0)
+                if (virDomainActualNetDefParseXML(cur, ctxt, def,
+                                                  &actual, flags) < 0) {
                     goto error;
+                }
             } else if (xmlStrEqual(cur->name, BAD_CAST "bandwidth")) {
                 if (!(def->bandwidth = virNetDevBandwidthParse(cur)))
                     goto error;
@@ -4494,6 +4542,30 @@ virDomainNetDefParseXML(virCapsPtr caps,
 
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        hostdev = &def->data.hostdev.def;
+        hostdev->parent.type = VIR_DOMAIN_DEVICE_NET;
+        hostdev->parent.data.net = def;
+        hostdev->info = &def->info;
+        /* 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;
+        }
+        def->data.hostdev.virtPortProfile = virtPort;
+        virtPort = NULL;
+        break;
+
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
@@ -4629,6 +4701,7 @@ cleanup:
     VIR_FREE(devaddr);
     VIR_FREE(mode);
     VIR_FREE(linkstate);
+    VIR_FREE(addrtype);
     virNWFilterHashTableFree(filterparams);
 
     return def;
@@ -10725,7 +10798,8 @@ virDomainHostdevSourceFormat(virBufferPtr buf,
 
 static int
 virDomainActualNetDefFormat(virBufferPtr buf,
-                            virDomainActualNetDefPtr def)
+                            virDomainActualNetDefPtr def,
+                            unsigned int flags)
 {
     int ret = -1;
     const char *type;
@@ -10741,14 +10815,12 @@ virDomainActualNetDefFormat(virBufferPtr buf,
         return ret;
     }
 
-    if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
-        def->type != VIR_DOMAIN_NET_TYPE_DIRECT &&
-        def->type != VIR_DOMAIN_NET_TYPE_NETWORK) {
-        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
-                             _("unexpected net type %s"), type);
-        goto error;
+    virBufferAsprintf(buf, "      <actual type='%s'", type);
+    if ((def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+        def->data.hostdev.def.managed) {
+        virBufferAddLit(buf, " managed='yes'");
     }
-    virBufferAsprintf(buf, "      <actual type='%s'>\n", type);
+    virBufferAddLit(buf, ">\n");
 
     switch (def->type) {
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
@@ -10781,8 +10853,26 @@ virDomainActualNetDefFormat(virBufferPtr buf,
             goto error;
         virBufferAdjustIndent(buf, -8);
         break;
-    default:
+
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        virBufferAdjustIndent(buf, 8);
+        if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
+                                         flags, true) < 0) {
+            return -1;
+        }
+        if (virNetDevVPortProfileFormat(def->data.hostdev.virtPortProfile,
+                                        buf) < 0) {
+            return -1;
+        }
+        virBufferAdjustIndent(buf, -8);
         break;
+
+    case VIR_DOMAIN_NET_TYPE_NETWORK:
+        break;
+    default:
+        virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                             _("unexpected net type %s"), type);
+        goto error;
     }
 
     virBufferAdjustIndent(buf, 8);
@@ -10810,7 +10900,12 @@ virDomainNetDefFormat(virBufferPtr buf,
         return -1;
     }
 
-    virBufferAsprintf(buf, "    <interface type='%s'>\n", type);
+    virBufferAsprintf(buf, "    <interface type='%s'", type);
+    if ((def->type == VIR_DOMAIN_NET_TYPE_HOSTDEV) &&
+        def->data.hostdev.def.managed) {
+        virBufferAddLit(buf, " managed='yes'");
+    }
+    virBufferAddLit(buf, ">\n");
 
     virBufferAsprintf(buf,
                       "      <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
@@ -10829,7 +10924,7 @@ virDomainNetDefFormat(virBufferPtr buf,
             return -1;
         virBufferAdjustIndent(buf, -6);
         if ((flags & VIR_DOMAIN_XML_INTERNAL_ACTUAL_NET) &&
-            (virDomainActualNetDefFormat(buf, def->data.network.actual) < 0))
+            (virDomainActualNetDefFormat(buf, def->data.network.actual, flags) < 0))
             return -1;
         break;
 
@@ -10883,6 +10978,19 @@ virDomainNetDefFormat(virBufferPtr buf,
         virBufferAdjustIndent(buf, -6);
         break;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        virBufferAdjustIndent(buf, 6);
+        if (virDomainHostdevSourceFormat(buf, &def->data.hostdev.def,
+                                         flags, true) < 0) {
+            return -1;
+        }
+        if (virNetDevVPortProfileFormat(def->data.hostdev.virtPortProfile,
+                                        buf) < 0) {
+            return -1;
+        }
+        virBufferAdjustIndent(buf, -6);
+        break;
+
     case VIR_DOMAIN_NET_TYPE_USER:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
@@ -14136,6 +14244,18 @@ virDomainNetGetActualDirectMode(virDomainNetDefPtr iface)
     return iface->data.network.actual->data.direct.mode;
 }
 
+virDomainHostdevDefPtr
+virDomainNetGetActualHostdev(virDomainNetDefPtr iface)
+{
+    if (iface->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
+        return &iface->data.hostdev.def;
+    if ((iface->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
+        (iface->data.network.actual->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)) {
+        return &iface->data.network.actual->data.hostdev.def;
+    }
+    return NULL;
+}
+
 virNetDevVPortProfilePtr
 virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
 {
@@ -14144,6 +14264,8 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
         return iface->data.direct.virtPortProfile;
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
         return iface->data.bridge.virtPortProfile;
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        return iface->data.hostdev.virtPortProfile;
     case VIR_DOMAIN_NET_TYPE_NETWORK:
         if (!iface->data.network.actual)
             return NULL;
@@ -14152,6 +14274,8 @@ virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface)
             return iface->data.network.actual->data.direct.virtPortProfile;
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
             return iface->data.network.actual->data.bridge.virtPortProfile;
+        case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+            return iface->data.network.actual->data.hostdev.virtPortProfile;
         default:
             return NULL;
         }
index 14581e4b516cac0224840e8e862b7800427a1566..c3f12ad227e89e3db3fd474768073cbe91547468 100644 (file)
@@ -694,6 +694,7 @@ enum virDomainNetType {
     VIR_DOMAIN_NET_TYPE_BRIDGE,
     VIR_DOMAIN_NET_TYPE_INTERNAL,
     VIR_DOMAIN_NET_TYPE_DIRECT,
+    VIR_DOMAIN_NET_TYPE_HOSTDEV,
 
     VIR_DOMAIN_NET_TYPE_LAST,
 };
@@ -744,6 +745,10 @@ struct _virDomainActualNetDef {
             int mode; /* enum virMacvtapMode from util/macvtap.h */
             virNetDevVPortProfilePtr virtPortProfile;
         } direct;
+        struct {
+            virDomainHostdevDef def;
+            virNetDevVPortProfilePtr virtPortProfile;
+        } hostdev;
     } data;
     virNetDevBandwidthPtr bandwidth;
 };
@@ -797,6 +802,10 @@ struct _virDomainNetDef {
             int mode; /* enum virMacvtapMode from util/macvtap.h */
             virNetDevVPortProfilePtr virtPortProfile;
         } direct;
+        struct {
+            virDomainHostdevDef def;
+            virNetDevVPortProfilePtr virtPortProfile;
+        } hostdev;
     } data;
     struct {
         bool sndbuf_specified;
@@ -1922,6 +1931,7 @@ int virDomainNetGetActualType(virDomainNetDefPtr iface);
 const char *virDomainNetGetActualBridgeName(virDomainNetDefPtr iface);
 const char *virDomainNetGetActualDirectDev(virDomainNetDefPtr iface);
 int virDomainNetGetActualDirectMode(virDomainNetDefPtr iface);
+virDomainHostdevDefPtr virDomainNetGetActualHostdev(virDomainNetDefPtr iface);
 virNetDevVPortProfilePtr
 virDomainNetGetActualVirtPortProfile(virDomainNetDefPtr iface);
 virNetDevBandwidthPtr
index 751d6d5df0ccce94259a77215805e3b451f1eda8..a6d741a6b13448aa30877c6df2892eee1126897b 100644 (file)
@@ -384,6 +384,7 @@ virDomainNetGetActualBandwidth;
 virDomainNetGetActualBridgeName;
 virDomainNetGetActualDirectDev;
 virDomainNetGetActualDirectMode;
+virDomainNetGetActualHostdev;
 virDomainNetGetActualType;
 virDomainNetGetActualVirtPortProfile;
 virDomainNetIndexByMac;
index e0e2945ce73d0f563daec4a187f9eea8a80eff6f..c628aed9270fbe5885ad06cd6c721238e74d48e5 100644 (file)
@@ -2720,6 +2720,7 @@ qemuBuildHostNetStr(virDomainNetDefPtr net,
         case VIR_DOMAIN_NET_TYPE_BRIDGE:
         case VIR_DOMAIN_NET_TYPE_INTERNAL:
         case VIR_DOMAIN_NET_TYPE_DIRECT:
+        case VIR_DOMAIN_NET_TYPE_HOSTDEV:
         case VIR_DOMAIN_NET_TYPE_LAST:
             break;
         }
index 89fdd9fb4cfe6325d66c8cbb3c0751feae103013..397d33224a14a9c80934859d803224d162f0f6d9 100644 (file)
@@ -254,6 +254,11 @@ umlBuildCommandLineNet(virConnectPtr conn,
                        _("direct networking type not supported"));
         goto error;
 
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+        umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("hostdev networking type not supported"));
+        goto error;
+
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
     }
index 8994cbc5da1d7f67426172d1946af4600fe5d6ab..e5df953fb357196db3468c2e9e847e35b6ccbaef 100644 (file)
@@ -1956,6 +1956,7 @@ xenFormatSxprNet(virConnectPtr conn,
     case VIR_DOMAIN_NET_TYPE_MCAST:
     case VIR_DOMAIN_NET_TYPE_INTERNAL:
     case VIR_DOMAIN_NET_TYPE_DIRECT:
+    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
     case VIR_DOMAIN_NET_TYPE_LAST:
         break;
     }
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml b/tests/qemuxml2argvdata/qemuxml2argv-net-hostdev.xml
new file mode 100644 (file)
index 0000000..65cd55d
--- /dev/null
@@ -0,0 +1,35 @@
+<domain type='qemu'>
+  <name>QEMUGuest1</name>
+  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+  <memory>219136</memory>
+  <currentMemory>219136</currentMemory>
+  <vcpu>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' 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>
index 4a2e016eca9d7f0edaa7a71827fbf39cde7938b4..03c75f81d10eec2aec257a62913a1f0c6d070fe1 100644 (file)
@@ -171,6 +171,7 @@ mymain(void)
     DO_TEST("net-eth");
     DO_TEST("net-eth-ifname");
     DO_TEST("net-virtio-network-portgroup");
+    DO_TEST("net-hostdev");
     DO_TEST("sound");
     DO_TEST("net-bandwidth");