[libvirt] PATCH: 8/12:Interal driver API for node devices

Mark McLoughlin markmc at redhat.com
Fri Nov 14 13:20:22 UTC 2008


On Thu, 2008-11-13 at 17:31 +0000, Daniel P. Berrange wrote:
> This is the basic internal driver support code for the node device APIs.
> The actual registration of the drivers was pushed to a later patch to
> allow this to compile on its own & thus be fully bisectable.
> 
> Daniel
> 
> diff -r 6812c3044043 src/Makefile.am
> --- a/src/Makefile.am	Wed Nov 12 21:11:46 2008 +0000
> +++ b/src/Makefile.am	Wed Nov 12 21:11:51 2008 +0000
> @@ -132,6 +132,10 @@
>  		storage_driver.h storage_driver.c		\
>  		storage_backend.h storage_backend.c
>  
> +# Network driver generic impl APIs

Typo

> +NODE_DEVICE_CONF_SOURCES =					\
> +		node_device_conf.c node_device_conf.h
> +
...
> diff -r 6812c3044043 src/node_device_conf.c
> --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
> +++ b/src/node_device_conf.c	Wed Nov 12 21:11:51 2008 +0000
...
> +char *virNodeDeviceDefFormat(virConnectPtr conn,
> +                             const virNodeDeviceDefPtr def)
> +{
> +    virBuffer buf = VIR_BUFFER_INITIALIZER;
> +    virNodeDevCapsDefPtr caps = def->caps;
> +    char *tmp;
> +
> +    virBufferAddLit(&buf, "<device>\n");
> +    virBufferEscapeString(&buf, "  <name>%s</name>\n", def->name);
> +
> +    if (def->parent)
> +        virBufferEscapeString(&buf, "  <parent>%s</parent>\n", def->parent);
> +
> +    for (caps = def->caps; caps; caps = caps->next) {
> +        char uuidstr[VIR_UUID_STRING_BUFLEN];
> +        union _virNodeDevCapData *data = &caps->data;
> +
> +        virBufferVSprintf(&buf, "  <capability type='%s'>\n",
> +                          virNodeDevCapTypeToString(caps->type));
> +        switch (caps->type) {
...
> +        case VIR_NODE_DEV_CAP_NET:
> +            virBufferVSprintf(&buf, "    <interface>%s</interface>\n",
> +                              data->net.interface);
> +            if (data->net.address)
> +                virBufferVSprintf(&buf, "    <address>%s</address>\n",
> +                                  data->net.address);
> +            if (data->net.subtype != VIR_NODE_DEV_CAP_NET_LAST) {
> +                const char *subtyp =
> +                    virNodeDevNetCapTypeToString(data->net.subtype);
> +                virBufferVSprintf(&buf, "    <capability type='%s'>\n", subtyp);
> +                switch (data->net.subtype) {
> +                case VIR_NODE_DEV_CAP_NET_80203:
> +                    virBufferVSprintf(&buf,
> +                                      "      <mac_address>%012llx</address>\n",
> +                                      data->net.data.ieee80203.mac_address);
> +                    break;
> +                case VIR_NODE_DEV_CAP_NET_80211:
> +                    virBufferVSprintf(&buf,
> +                                      "      <mac_address>%012llx</address>\n",
> +                                      data->net.data.ieee80211.mac_address);
> +                    break;
> +                case VIR_NODE_DEV_CAP_NET_LAST:
> +                    /* Keep dumb compiler happy */
> +                    break;
> +                }
> +                virBufferAddLit(&buf, "    </capability>\n");

This all seems a bit odd.

We've listed the mac address once already, so why do it again in a hex format?

And I wouldn't think of "802.3 vs 802.11" as a network device capability, but more like it's "type" - they're mutually exclusive, right?

Also, we have:

  <device>
    ...
    <capability type='net'>
      ...
      <capability type='80203'>
        <mac_address>001320f74a06</address>
      </capability>
    </capability>
  </device>

i.e. two different capability semantics?

> +            }
> +            break;
> +        case VIR_NODE_DEV_CAP_BLOCK:
> +            virBufferVSprintf(&buf, "    <device>%s</device>\n",
> +                              data->block.device);

Two nested <device> nodes:

<device>
  ...
  <capability type='block'>
    <device>/dev/sda1</device>
  </capability>
</device>

How about <path> or <device_path> ?

> +            break;
> +        case VIR_NODE_DEV_CAP_SCSI_HOST:
> +            virBufferVSprintf(&buf, "    <host>%d</host>\n",
> +                              data->scsi_host.host);
> +            break;
> +        case VIR_NODE_DEV_CAP_SCSI:
> +            virBufferVSprintf(&buf, "    <host>%d</host>\n", data->scsi.host);
> +            virBufferVSprintf(&buf, "    <bus>%d</bus>\n", data->scsi.bus);
> +            virBufferVSprintf(&buf, "    <target>%d</target>\n",
> +                              data->scsi.target);
> +            virBufferVSprintf(&buf, "    <lun>%d</lun>\n", data->scsi.lun);
> +            if (data->scsi.type)
> +                virBufferVSprintf(&buf, "    <type>%s</type>\n",
> +                                  data->scsi.type);
> +            break;
> +        case VIR_NODE_DEV_CAP_STORAGE:
> +            if (data->storage.bus)
> +                virBufferVSprintf(&buf, "    <bus>%s</bus>\n",
> +                                  data->storage.bus);
> +            if (data->storage.drive_type)
> +                virBufferVSprintf(&buf, "    <drive_type>%s</drive_type>\n",
> +                                  data->storage.drive_type);
> +            if (data->storage.originating_device)
> +                virBufferVSprintf(&buf,
> +                                  "    <originating_device>%s"
> +                                  "</originating_device>\n",
> +                                  data->storage.originating_device);

This originating_device thing sounds strange, and I don't think we
implement it yet. Leave it out for now?

> +            if (data->storage.model)
> +                virBufferVSprintf(&buf, "    <model>%s</model>\n",
> +                                  data->storage.model);
> +            if (data->storage.vendor)
> +                virBufferVSprintf(&buf, "    <vendor>%s</vendor>\n",
> +                                  data->storage.vendor);
> +            if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_REMOVABLE) {
> +                int avl = data->storage.flags &
> +                    VIR_NODE_DEV_CAP_STORAGE_REMOVABLE_MEDIA_AVAILABLE;
> +                virBufferAddLit(&buf, "    <capability type='removable'>\n");
> +                virBufferVSprintf(&buf,
> +                                  "      <media_available>%d"
> +                                  "</media_available>\n", avl ? 1 : 0);
> +                virBufferVSprintf(&buf, "      <media_size>%llu</media_size>\n",
> +                                  data->storage.removable_media_size);
> +                virBufferAddLit(&buf, "    </capability>\n");
> +            } else {
> +                virBufferVSprintf(&buf, "    <size>%llu</size>\n",
> +                                  data->storage.size);
> +            }
> +            if (data->storage.flags & VIR_NODE_DEV_CAP_STORAGE_HOTPLUGGABLE)
> +                virBufferAddLit(&buf,
> +                                "    <capability type='hotpluggable' />\n");

Again, the nested capabilities doesn't seem right.

How about just:

  <removable media_available="1"/>
  <hotpluggable/>

> +            break;
> +        case VIR_NODE_DEV_CAP_LAST:
> +            /* ignore special LAST value */
> +            break;
> +        }
> +
> +        virBufferAddLit(&buf, "  </capability>\n");
> +    }
> +
> +    virBufferAddLit(&buf, "</device>\n");
> +
> +    if (virBufferError(&buf))
> +        goto no_memory;
> +
> +    return virBufferContentAndReset(&buf);
> +
> + no_memory:
> +    virNodeDeviceReportError(conn, VIR_ERR_NO_MEMORY, NULL);
> +    tmp = virBufferContentAndReset(&buf);
> +    VIR_FREE(tmp);
> +    return NULL;
> +}
> +
> +void virNodeDevCapsDefFree(virNodeDevCapsDefPtr caps)
> +{
> +    union _virNodeDevCapData *data = &caps->data;
> +
> +    switch (caps->type) {
> +    case VIR_NODE_DEV_CAP_SYSTEM:
> +        VIR_FREE(data->system.product_name);
> +        VIR_FREE(data->system.hardware.vendor_name);
> +        VIR_FREE(data->system.hardware.version);
> +        VIR_FREE(data->system.hardware.serial);
> +        VIR_FREE(data->system.firmware.vendor_name);
> +        VIR_FREE(data->system.firmware.version);
> +        VIR_FREE(data->system.firmware.release_date);
> +        break;
> +    case VIR_NODE_DEV_CAP_PCI_DEV:
> +        VIR_FREE(data->pci_dev.product_name);
> +        VIR_FREE(data->pci_dev.vendor_name);
> +        break;
> +    case VIR_NODE_DEV_CAP_USB_DEV:
> +        VIR_FREE(data->usb_dev.product_name);
> +        VIR_FREE(data->usb_dev.vendor_name);
> +        break;
> +    case VIR_NODE_DEV_CAP_USB_INTERFACE:
> +        VIR_FREE(data->usb_if.description);
> +        break;
> +    case VIR_NODE_DEV_CAP_NET:
> +        VIR_FREE(data->net.interface);
> +        VIR_FREE(data->net.address);
> +        break;
> +    case VIR_NODE_DEV_CAP_BLOCK:
> +        VIR_FREE(data->block.device);
> +        break;
> +    case VIR_NODE_DEV_CAP_SCSI_HOST:
> +        break;
> +    case VIR_NODE_DEV_CAP_SCSI:
> +        VIR_FREE(data->scsi.type);
> +        break;
> +    case VIR_NODE_DEV_CAP_STORAGE:
> +        VIR_FREE(data->storage.bus);
> +        VIR_FREE(data->storage.drive_type);
> +        VIR_FREE(data->storage.model);
> +        VIR_FREE(data->storage.vendor);

originating_device not freed.

> +        break;
> +    case VIR_NODE_DEV_CAP_LAST:
> +        /* This case is here to shutup the compiler */
> +        break;
> +    }
> +
> +    VIR_FREE(caps);
> +}
> +
> diff -r 6812c3044043 src/node_device_conf.h
> --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
> +++ b/src/node_device_conf.h	Wed Nov 12 21:11:51 2008 +0000
...
> +char *virNodeDeviceDefFormat(virConnectPtr conn,
> +                             const virNodeDeviceDefPtr def);
> +
> +// TODO: virNodeDeviceDefParseString/File/Node for virNodeDeviceCreate

Kinda superflous comment - if we implement DeviceCreate(), the need for
those functions will be obvious.

Cheers,
Mark.




More information about the libvir-list mailing list