[Libvir] Proposal for dealing with host devices

Daniel P. Berrange berrange at redhat.com
Wed Apr 2 01:05:58 UTC 2008

The following document illustrates an API for host device enumeration,
creation and deletion. This has a number of use cases:

 - PCI passthrough. Need to enumerate PCI devices, get their domain,
   bus, slot, function IDs to be able to pass-though to a guest.
   Need to disable the host kernel driver. Need to get metadata about
   the device to present to the user, eg model / vendor.

 - USB passthrough. Need to enumerate USB devices, get their bus, device
   IDs to be able to pass-though to a guest. Need to disable the host
   kernel driver. Need to get metadata about the device to present to
   the user, eg model / vendor.

 - Fibre Channel. Need to enumerate SCSI HBAs with FC capability and
   get their WWNN and WWPN (World Wide Node/Port Name) to enable the
   administrator to associate with the SAN.
   This relates to the SCSI storage pool impl I posted last week

 - NPIV. Need to create/delete NPIV virtual Fibre Channel adapters.
   This relates to the SCSI storage pool impl I posted last week

 - Networking. Need to enumerate NICs, bridges, VLANs, bonding.

This all sounds like alot of data / stuff to manage, but the good news
is that there is already an application which does most of this for
us. ie HAL.  So at the basic level all we need to do is map the HAL
properties into a libvirt XML format for describing devices.

I have chosen to define a very direct mapping.

 - At the top level, "<device>" element

 - A short 'name' and longer 'key' both unique to host
   The key is the HAL 'udi' value

 - A 'parent' key to show nesting of devices.

 - Optional 'bus' information inside a <bus> element
   Bus names will map straight into HAL bus names.
   The content is bus specific

 - Optional 'capability' information inside one or more
   <capability> elements. NB a single device can provide
   several capabilites. Capability names will map straight
   onto HAL capability names. The content is capability

 - Capabilities can be nested for specialization. eg a
   'net' capability can have a '80211' sub-capability
   if it is a wifi device.

Now some example XML descriptions....

An arbitrary PCI device


    <bus type="pci">
      <vendor id="32902">Intel Corporation</vendor>
      <product id="10202">82801G (ICH7 Family) SMBus Controller</product>

      <address domain="0000" bus="00" slot="1f" function="3"/>

An arbitrary USB device


    <bus type="usb">
      <vendor id="1155">SGS Thomson Microelectronics</vendor>
      <product id="8214">Fingerprint Reader</product>

      <address bus="003" dev="005"/>



    <capability type="scsihost">
      <capability type="fc">
        <address wwnn="023432532532632" wwpn="32453253252352"/>

        <vports max="4"/>

As an example, consider a wireless NIC


    <capability type="net">

       <capability type="80211"/>

Notice how the specific functional devices like NICs, HBAs, are
children of the physical USB or PCI device. This is where the
hierarchy comes in.

There are a few other types of devices we want explicit representations
for, block devices, sound devices, storage devices, input devices. I
want describe them here, but they follow same pattern of mapping the
XML onto the HAL properties in their <capability> tags.

There are some devices HAL does not represent so we'll have to augment
the HAL information. Specifically devices which don't correspond to
a physical device, eg

  - Bonding NICs
  - Bridges
  - VLANs

There are also cases where HAL does not have enough properties so we
again need to augment the data

 - Fibre Channel / NPIV:  Add WWPN, WWNN

The API to deal with this is really very simple. APIs to query all
devices, or query devices based on a capability, or bus type:

  virNodeNumOfDevices(virConnectPtr conn)

  virNodeListDevices(virConnectPtr conn,
                     char **const names,
                     int maxnames)
  virNodeNumOfDevicesByCap(virConnectPtr conn,
			   const char *cap)

  virNodeListDevicesByCap(virConnectPtr conn,
			  const char *cap,
			  char **const names,
			  int maxnames)
  virNodeNumOfDevicesByBus(virConnectPtr conn,
			   const char *bus)
  virNodeListDevicesByBus(virConnectPtr conn,
			  const char *bus,
			  char **const names,
			  int maxnames)

Then APIs to obtain a virNodeDevicePtr object corresponding to a
device name / key :

  virNodeDeviceLookupByName(virConnectPtr conn, const char *name)

  virNodeDeviceLookupByName(virConnectPtr conn, const char *key)

  virNodeDeviceFree(virNodeDevicePtr dev)

An API to get the XML description:

  char *
  virNodeDeviceDumpXML(virConnectPtr conn,
                       unsigned int flags)

Finally an API to create / delete devices - this is only for devices
with certain capabilities

  virNodeDeviceCreate(virConnectPtr conn,
                      const char *xml)

  virNodeDeviceDestroy(virNodeDevicePtr dev)

BTW if you want to see all the HAL metadata on your machine run


I don't propose to expose all the data - only specific properties we have
immediate need for. The HAL spec describes the meaning of various props


|: Red Hat, Engineering, Boston   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|

More information about the libvir-list mailing list