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

Laine Stump laine at laine.org
Thu Sep 13 15:51:59 UTC 2012


(a couple of things I noticed in passing, which are useful general info
whether or not we take these patches in their current form)


On 09/07/2012 12:14 PM, Shradha Shah wrote:
> 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>

I noticed that the <group> for hostdev-hybrid is exactly the same as for
hostdev. In this case, you can just change this line in the hostdev group:


     <value>hostdev></value>

into the following 4 lines:

     <choice>
       <value>hostdev</value>
       <value>hostdev-hybrid</value>
     </choice>

and avoid adding the new <group> altogether.


> +          </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;

might as well combine the above two cases.

>      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;
> +

Same here I think (can't see all of the context)

>      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;
> +        }

I've got a feeling a lot of this is common code with hostdev. Maybe you
could refactor it to avoid duplicated code.


>      }
>  
>      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;

I'm not sure why managed was defined as a bitfield, but these days we're
more inclined to use bool

>      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");




More information about the libvir-list mailing list