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

[Xen-devel] [PATCH v2 1/2] libxl: Introduce functions to add and remove host USB devices to an HVM guest



This uses the qmp functionality, and is thus only available for qemu-xen,
not qemu-traditional.

Devices must be removed by "id", an identifying string, which must be
specified when the device is created.  The caller can either pass one
in to request; if none is passed in, then libxl will choose one and
pass it back to the caller.  In the second case, it will return a
string containing the id used in the "id" field of the device struct.

Devices can either be removed by passing in the id returned when the
device was added, or by passing a device struct with exactly the same
parameters as when it was added (which will allow libxl to re-generate
the id for device removal).

v2:
 - Make interface async-ready
 - usb_del takes libxl_device_host_usb struct
 - usb_del will re-construct original id given device info if no id is given

Signed-off-by: George Dunlap <george.dunlap@xxxxxxxxxxxxx>
---
 tools/libxl/libxl.c          |   96 ++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/libxl.h          |   43 +++++++++++++++++++
 tools/libxl/libxl_internal.h |    4 ++
 tools/libxl/libxl_qmp.c      |   54 ++++++++++++++++++++++++
 tools/libxl/libxl_types.idl  |    8 ++++
 5 files changed, 205 insertions(+)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 572c2c6..fbe6fff 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2498,6 +2498,102 @@ out:
     return AO_INPROGRESS;
 }
 
+int libxl_hvm_host_usb_add(libxl_ctx *ctx, uint32_t domid,
+                           libxl_device_host_usb *dev,
+                           const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc = ERROR_FAIL, dm_ver;
+
+    libxl_domain_type type = libxl__domain_type(gc, domid);
+    if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+        goto out;
+    }
+    if (type != LIBXL_DOMAIN_TYPE_HVM) {
+        LOG(ERROR, "hvm-host-usb-add requires an HVM domain");
+        goto out;
+    }
+
+    if (libxl_get_stubdom_id(ctx, domid) != 0) {
+        LOG(ERROR, "hvm-host-usb-add doesn't work for stub domains");
+        goto out;
+    }
+
+    dm_ver = libxl__device_model_version_running(gc, domid);
+    if (dm_ver == -1) {
+        LOG(ERROR, "cannot determine device model version");
+        goto out;
+    }
+
+    if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+        rc = libxl__qmp_host_usb_add(gc, domid, dev);
+    } else {
+        LOG(ERROR, "hvm-host-usb-add not yet implemented for 
qemu-traditional");
+    }
+
+    /* success, no actual async */
+    libxl__ao_complete(egc, ao, 0);
+
+    rc = 0;
+out:
+    if (rc) return AO_ABORT(rc);
+    return AO_INPROGRESS;
+}
+
+int libxl_hvm_host_usb_del(libxl_ctx *ctx, uint32_t domid,
+                           libxl_device_host_usb *dev,
+                           const libxl_asyncop_how *ao_how)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc = ERROR_FAIL, dm_ver;
+    libxl_domain_type type;
+
+    if (dev->id
+        && (dev->hostbus != LIBXL_DEVICE_HOST_USB_ANY
+            || dev->hostaddr != LIBXL_DEVICE_HOST_USB_ANY
+            || dev->vendorid != LIBXL_DEVICE_HOST_USB_ANY
+            || dev->productid != LIBXL_DEVICE_HOST_USB_ANY) ) {
+        LOG(ERROR, "hvm-host-usb-del cannot accept both id and device 
specifier!");
+        rc = ERROR_INVAL;
+        goto out;
+    }
+
+    type = libxl__domain_type(gc, domid);
+    if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+        goto out;
+    }
+    if (type != LIBXL_DOMAIN_TYPE_HVM) {
+        LOG(ERROR, "hvm-host-usb-del requires an HVM domain");
+        goto out;
+    }
+
+    if (libxl_get_stubdom_id(ctx, domid) != 0) {
+        LOG(ERROR, "hvm-host-usb-del doesn't work for stub domains");
+        goto out;
+    }
+
+    dm_ver = libxl__device_model_version_running(gc, domid);
+    if (dm_ver == -1) {
+        LOG(ERROR, "cannot determine device model version");
+        goto out;
+    }
+
+    if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+        rc = libxl__qmp_host_usb_del(gc, domid, dev);
+    } else {
+        LOG(ERROR, "hvm-host-usb-del not yet implemented for 
qemu-traditional");
+    }
+
+    /* success, no actual async */
+    libxl__ao_complete(egc, ao, 0);
+
+    rc = 0;
+out:
+    if (rc) return AO_ABORT(rc);
+    return AO_INPROGRESS;
+}
+
+
 /* libxl__alloc_vdev only works on the local domain, that is the domain
  * where the toolstack is running */
 static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user,
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 030aa86..aac6f3f 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -75,6 +75,15 @@
 #define LIBXL_HAVE_FIRMWARE_PASSTHROUGH 1
 
 /*
+ * LIBXL_HAVE_HVM_HOST_USB indicates that the structure libxl_device_host_usb
+ * exists, as well as the following two functions, relating to passing through
+ * host USB devices to HVM guests:
+ * - libxl_hvm_host_usb_add
+ * - libxl_hvm_host_usb_del.
+ */
+#define LIBXL_HAVE_HVM_HOST_USB 1
+
+/*
  * libxl ABI compatibility
  *
  * The only guarantee which libxl makes regarding ABI compatibility
@@ -719,6 +728,40 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, 
libxl_device_disk *disk,
                        const libxl_asyncop_how *ao_how)
                        LIBXL_EXTERNAL_CALLERS_ONLY;
 
+/*
+ * HVM Host USB
+ * 
+ * Add and remove specified host USB device to an HVM guest.
+ *
+ * libxl_device_host_usb contains four potential specifiers which are
+ * initialized to LIBXL_DEVICE_HOST_USB_ANY.  According to the qemu
+ * documentation, any parameter that is left empty will match
+ * anything.  It is recommended to at least specify hostbus.hostid, or
+ * vendorid:productid.
+ *
+ * The caller can specify the 'id' field of libxl_device_host_usb.  If
+ * this is left NULL, then libxl will choose one and return the value
+ * in the id field.  Id's must be unique to the device within a VM;
+ * attempting to assign a device with an existing id will return an
+ * error.
+ *
+ * When calling libxl_hvm_host_usb_del, devices can be removed either
+ * by passing the id string with which the device was created, or by
+ * passing the exact same values as when the device was created.  If
+ * "id" is passed, then all other parameters must be set to
+ * LIBXL_DEVICE_HOST_USB_ANY (the default setting).  If the 'id' was
+ * specified on device creation, then 'id' must be used to remove the
+ * device; passing the parameters will fail.
+ */
+#define LIBXL_DEVICE_HOST_USB_ANY (-1)
+int libxl_hvm_host_usb_add(libxl_ctx *ctx, uint32_t domid,
+                           libxl_device_host_usb *dev,
+                           const libxl_asyncop_how *ao_how)
+                           LIBXL_EXTERNAL_CALLERS_ONLY;
+int libxl_hvm_host_usb_del(libxl_ctx *ctx, uint32_t domid, 
+                           libxl_device_host_usb *dev,
+                           const libxl_asyncop_how *ao_how)
+                           LIBXL_EXTERNAL_CALLERS_ONLY;
 /* Network Interfaces */
 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
                          const libxl_asyncop_how *ao_how)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8be086d..f8dd886 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1411,6 +1411,10 @@ _hidden int libxl__qmp_save(libxl__gc *gc, int domid, 
const char *filename);
 /* Set dirty bitmap logging status */
 _hidden int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, bool 
enable);
 _hidden int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid, const 
libxl_device_disk *disk);
+_hidden int libxl__qmp_host_usb_add(libxl__gc *gc, int domid, 
+                                    libxl_device_host_usb *dev);
+_hidden int libxl__qmp_host_usb_del(libxl__gc *gc, int domid, 
+                                    libxl_device_host_usb *dev);
 /* close and free the QMP handler */
 _hidden void libxl__qmp_close(libxl__qmp_handler *qmp);
 /* remove the socket file, if the file has already been removed,
diff --git a/tools/libxl/libxl_qmp.c b/tools/libxl/libxl_qmp.c
index 644d2c0..49b9e48 100644
--- a/tools/libxl/libxl_qmp.c
+++ b/tools/libxl/libxl_qmp.c
@@ -42,6 +42,7 @@
 
 #define QMP_RECEIVE_BUFFER_SIZE 4096
 #define PCI_PT_QDEV_ID "pci-pt-%02x_%02x.%01x"
+#define HOST_USB_QDEV_ID "host-usb-%04x.%04x-%04x.%04x"
 
 typedef int (*qmp_callback_t)(libxl__qmp_handler *qmp,
                               const libxl__json_object *tree,
@@ -929,6 +930,59 @@ int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid,
     }
 }
 
+int libxl__qmp_host_usb_add(libxl__gc *gc, int domid,
+                            libxl_device_host_usb *dev)
+{
+    libxl__json_object *args = NULL;
+
+    if (dev->id == NULL )
+    {
+        dev->id = libxl__sprintf(NOGC, HOST_USB_QDEV_ID,
+                                 (uint16_t) dev->hostbus,
+                                 (uint16_t) dev->hostaddr,
+                                 (uint16_t) dev->vendorid,
+                                 (uint16_t) dev->productid);
+    }
+
+    qmp_parameters_add_string(gc, &args, "driver", "usb-host");
+    if(dev->hostbus != LIBXL_DEVICE_HOST_USB_ANY) {
+        QMP_PARAMETERS_SPRINTF(&args, "hostbus", "0x%x", dev->hostbus);
+    }
+    if(dev->hostaddr != LIBXL_DEVICE_HOST_USB_ANY) {
+        QMP_PARAMETERS_SPRINTF(&args, "hostaddr", "0x%x", dev->hostaddr);
+    }
+    if(dev->vendorid != LIBXL_DEVICE_HOST_USB_ANY) {
+        QMP_PARAMETERS_SPRINTF(&args, "vendorid", "0x%x", dev->vendorid);
+    }
+    if(dev->productid != LIBXL_DEVICE_HOST_USB_ANY) {
+        QMP_PARAMETERS_SPRINTF(&args, "productid", "0x%x", dev->productid);
+    }
+
+    qmp_parameters_add_string(gc, &args, "id", dev->id);
+
+    return qmp_run_command(gc, domid, "device_add", args, NULL, NULL);
+}
+
+int libxl__qmp_host_usb_del(libxl__gc *gc, int domid, 
+                            libxl_device_host_usb *dev)
+{
+    libxl__json_object *args = NULL;
+
+    if (dev->id == NULL )
+    {
+        dev->id = libxl__sprintf(NOGC, HOST_USB_QDEV_ID,
+                                 (uint16_t) dev->hostbus,
+                                 (uint16_t) dev->hostaddr,
+                                 (uint16_t) dev->vendorid,
+                                 (uint16_t) dev->productid);
+    }
+
+    qmp_parameters_add_string(gc, &args, "id", dev->id);
+
+    return qmp_run_command(gc, domid, "device_del", args, NULL, NULL);
+}
+
+
 int libxl__qmp_initializations(libxl__gc *gc, uint32_t domid,
                                const libxl_domain_config *guest_config)
 {
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index f3c212b..45ee531 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -406,6 +406,14 @@ libxl_device_vtpm = Struct("device_vtpm", [
     ("uuid",             libxl_uuid),
 ])
 
+libxl_device_host_usb = Struct("device_host_usb", [
+    ("hostbus",   integer, {'init_val': 'LIBXL_DEVICE_HOST_USB_ANY'}),
+    ("hostaddr",  integer, {'init_val': 'LIBXL_DEVICE_HOST_USB_ANY'}),
+    ("vendorid",  integer, {'init_val': 'LIBXL_DEVICE_HOST_USB_ANY'}),
+    ("productid", integer, {'init_val': 'LIBXL_DEVICE_HOST_USB_ANY'}),
+    ("id",         string),
+    ])
+
 libxl_domain_config = Struct("domain_config", [
     ("c_info", libxl_domain_create_info),
     ("b_info", libxl_domain_build_info),
-- 
1.7.9.5


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.