diff mbox

[V13,5/5] xl: add pvusb commands

Message ID 1453192795-15693-6-git-send-email-cyliu@suse.com
State New, archived
Headers show

Commit Message

Chunyan Liu Jan. 19, 2016, 8:39 a.m. UTC
Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
usbdev-attach and usbdev-detach.

To attach a usb device to guest through pvusb, one could follow
following example:

 #xl usbctrl-attach test_vm version=1 ports=8

 #xl usb-list test_vm
 will show the usb controllers and port usage under the domain.

 #xl usbdev-attach test_vm hostbus=1 hostaddr=2
 will find the first usable controller:port, and attach usb
 device whose busnum is 1 and devnum is 6.
 One could also specify which <controller> and which <port>.

 #xl usbdev-detach test_vm 0 1
 will detach USB device under controller 0 port 1.

 #xl usbctrl-detach test_vm dev_id
 will destroy the controller with specified dev_id. Dev_id
 can be traced in usb-list info.

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Simon Cao <caobosimon@gmail.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
---
changes:
* update docs to reuse documentation in xl.cfg
* remove backend patch information from usb-list

 docs/man/xl.pod.1         |  35 +++++++++
 tools/libxl/xl.h          |   5 ++
 tools/libxl/xl_cmdimpl.c  | 190 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |  25 ++++++
 4 files changed, 255 insertions(+)

Comments

Ian Jackson Jan. 19, 2016, 6:11 p.m. UTC | #1
Chunyan Liu writes ("[PATCH V13 5/5] xl: add pvusb commands"):
> Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
> usbdev-attach and usbdev-detach.

Thanks for swapping this with the other patch.  It is better now.

> +=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>

However, I think you need to explictly state that the user may (and
indeed, must) pass multiple settings as separate arguments.  AFAICT
the parser here doesn't do the ,-splitting.

> +I<usbctrl-device> describes the device to attach, using the same format
> +as the B<usbctrl> string in the domain config file. See L<xl.cfg> for
> +more information.

And this, therefore, is not quite true.

To be clear, I think that you should fix the documentation to match
the code.

Thanks,
Ian.
Jim Fehlig Jan. 20, 2016, 3:10 a.m. UTC | #2
On 01/19/2016 11:11 AM, Ian Jackson wrote:
> Chunyan Liu writes ("[PATCH V13 5/5] xl: add pvusb commands"):
>> Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
>> usbdev-attach and usbdev-detach.
> Thanks for swapping this with the other patch.  It is better now.
>
>> +=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>
> However, I think you need to explictly state that the user may (and
> indeed, must) pass multiple settings as separate arguments.  AFAICT
> the parser here doesn't do the ,-splitting.

I just noticed this is the case with network devices as well. E.g.

#xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb: script: Could
not find bridge device xenbr0

main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on the ',', so
everything after mac=00:16:3e:xx:yy:zz is ignored. I'd need advice on how to fix
this though. Based on xl-network-configuration doc and Xen tool's long history
of network-attach supporting that syntax, I'd say main_networkattach() should be
changed to split on ','. I could also change the docs. Do tools maintainers have
a preference, or alternative option?

Regards,
Jim
Wei Liu Jan. 21, 2016, 12:12 p.m. UTC | #3
On Tue, Jan 19, 2016 at 08:10:07PM -0700, Jim Fehlig wrote:
> On 01/19/2016 11:11 AM, Ian Jackson wrote:
> > Chunyan Liu writes ("[PATCH V13 5/5] xl: add pvusb commands"):
> >> Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
> >> usbdev-attach and usbdev-detach.
> > Thanks for swapping this with the other patch.  It is better now.
> >
> >> +=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>
> > However, I think you need to explictly state that the user may (and
> > indeed, must) pass multiple settings as separate arguments.  AFAICT
> > the parser here doesn't do the ,-splitting.
> 
> I just noticed this is the case with network devices as well. E.g.
> 
> #xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
> libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb: script: Could
> not find bridge device xenbr0
> 
> main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on the ',', so
> everything after mac=00:16:3e:xx:yy:zz is ignored. I'd need advice on how to fix
> this though. Based on xl-network-configuration doc and Xen tool's long history
> of network-attach supporting that syntax, I'd say main_networkattach() should be
> changed to split on ','. I could also change the docs. Do tools maintainers have
> a preference, or alternative option?
> 

It is splitting on " " at the moment which is not very desirable.

I think this is a bug. I've added it to my list and will look into
fixing it.

Wei.

> Regards,
> Jim
>
Ian Campbell Jan. 21, 2016, 12:21 p.m. UTC | #4
On Thu, 2016-01-21 at 12:12 +0000, Wei Liu wrote:
> On Tue, Jan 19, 2016 at 08:10:07PM -0700, Jim Fehlig wrote:
> > On 01/19/2016 11:11 AM, Ian Jackson wrote:
> > > Chunyan Liu writes ("[PATCH V13 5/5] xl: add pvusb commands"):
> > > > Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
> > > > usbdev-attach and usbdev-detach.
> > > Thanks for swapping this with the other patch.  It is better now.
> > > 
> > > > +=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>
> > > However, I think you need to explictly state that the user may (and
> > > indeed, must) pass multiple settings as separate arguments.  AFAICT
> > > the parser here doesn't do the ,-splitting.
> > 
> > I just noticed this is the case with network devices as well. E.g.
> > 
> > #xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
> > libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb:
> > script: Could
> > not find bridge device xenbr0
> > 
> > main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on the
> > ',', so
> > everything after mac=00:16:3e:xx:yy:zz is ignored. I'd need advice on
> > how to fix
> > this though. Based on xl-network-configuration doc and Xen tool's long
> > history
> > of network-attach supporting that syntax, I'd say main_networkattach()
> > should be
> > changed to split on ','. I could also change the docs. Do tools
> > maintainers have
> > a preference, or alternative option?
> > 
> 
> It is splitting on " " at the moment which is not very desirable.
> 
> I think this is a bug. I've added it to my list and will look into
> fixing it.

If you are feeling particularly highly motivated then xl_cmdimpl.c contains
quite a lot of adhoc parsing of various comma a space separated lists
(often dupped for a given instance into cmdline vs cfg file, which leads to
unintentional behavioural differences like above) which could usefully be
consolidated into a series of helpers.

Ian.
Wei Liu Jan. 21, 2016, 12:29 p.m. UTC | #5
On Thu, Jan 21, 2016 at 12:21:11PM +0000, Ian Campbell wrote:
> On Thu, 2016-01-21 at 12:12 +0000, Wei Liu wrote:
> > On Tue, Jan 19, 2016 at 08:10:07PM -0700, Jim Fehlig wrote:
> > > On 01/19/2016 11:11 AM, Ian Jackson wrote:
> > > > Chunyan Liu writes ("[PATCH V13 5/5] xl: add pvusb commands"):
> > > > > Add pvusb commands: usbctrl-attach, usbctrl-detach, usb-list,
> > > > > usbdev-attach and usbdev-detach.
> > > > Thanks for swapping this with the other patch.  It is better now.
> > > > 
> > > > > +=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>
> > > > However, I think you need to explictly state that the user may (and
> > > > indeed, must) pass multiple settings as separate arguments.  AFAICT
> > > > the parser here doesn't do the ,-splitting.
> > > 
> > > I just noticed this is the case with network devices as well. E.g.
> > > 
> > > #xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
> > > libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb:
> > > script: Could
> > > not find bridge device xenbr0
> > > 
> > > main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on the
> > > ',', so
> > > everything after mac=00:16:3e:xx:yy:zz is ignored. I'd need advice on
> > > how to fix
> > > this though. Based on xl-network-configuration doc and Xen tool's long
> > > history
> > > of network-attach supporting that syntax, I'd say main_networkattach()
> > > should be
> > > changed to split on ','. I could also change the docs. Do tools
> > > maintainers have
> > > a preference, or alternative option?
> > > 
> > 
> > It is splitting on " " at the moment which is not very desirable.
> > 
> > I think this is a bug. I've added it to my list and will look into
> > fixing it.
> 
> If you are feeling particularly highly motivated then xl_cmdimpl.c contains
> quite a lot of adhoc parsing of various comma a space separated lists
> (often dupped for a given instance into cmdline vs cfg file, which leads to
> unintentional behavioural differences like above) which could usefully be
> consolidated into a series of helpers.
> 

Or rewrite every adhoc parser with bison/flex or Ocaml / Haskell parsec.

Jokes aside. I will see what I can do. Consolidating them into helper
functions is a good start.

Wei.

> Ian.
>
Ian Jackson Jan. 21, 2016, 5:37 p.m. UTC | #6
Wei Liu writes ("Re: [Xen-devel] [PATCH V13 5/5] xl: add pvusb commands"):
> Or rewrite every adhoc parser with bison/flex or Ocaml / Haskell parsec.

I endorse this product and/or service.

> Jokes aside. I will see what I can do. Consolidating them into helper
> functions is a good start.

Yes :-).

Ian.
Olaf Hering Feb. 16, 2016, 4:56 p.m. UTC | #7
On Tue, Jan 19, Chunyan Liu wrote:

>  #xl usbctrl-attach test_vm version=1 ports=8

>  #xl usbdev-attach test_vm hostbus=1 hostaddr=2

I think this does not handle the -N knob of xl. Other commands check the
global dryrun_only variable.

Olaf
Ian Jackson Feb. 16, 2016, 5:53 p.m. UTC | #8
Jim Fehlig writes ("Re: [Xen-devel] [PATCH V13 5/5] xl: add pvusb commands"):
> I just noticed this is the case with network devices as well. E.g.
> 
> #xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
> libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb: script: Could
> not find bridge device xenbr0

This is clearly a bug.

> main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on
> the ',', so everything after mac=00:16:3e:xx:yy:zz is ignored.

That's quite silly, isn't it.  Looking at the code it would also accept
  mac=00:16:3e:aa:bb:cc:THIS:SHOULD:NOT:BE:HERE

The bug seems to be that the ad-hoc strtoul-based mac address parser
in xl_cmdimpl.c:parse_nic_config doesn't notice garbage after its
option.

> I'd need advice on how to fix this though. Based on
> xl-network-configuration doc and Xen tool's long history of
> network-attach supporting that syntax, I'd say main_networkattach()
> should be changed to split on ','. I could also change the docs. Do
> tools maintainers have a preference, or alternative option?

I don't have a strong opinion, but I would lean towards insisting that
on command lines each setting should be in its own argument.

Ian.
Chunyan Liu Feb. 17, 2016, 6:14 a.m. UTC | #9
n

>>> On 2/17/2016 at 12:56 AM, in message <20160216165608.GA21669@gmail.com>, Olaf
Hering <olaf@aepfle.de> wrote: 
> On Tue, Jan 19, Chunyan Liu wrote: 
>  
> >  #xl usbctrl-attach test_vm version=1 ports=8 
>  
> >  #xl usbdev-attach test_vm hostbus=1 hostaddr=2 
>  
> I think this does not handle the -N knob of xl. Other commands check the 
> global dryrun_only variable. 

Thanks. I'll add.

>  
> Olaf 
>  
> _______________________________________________ 
> Xen-devel mailing list 
> Xen-devel@lists.xen.org 
> http://lists.xen.org/xen-devel 
>  
>
Wei Liu Feb. 17, 2016, 11:43 a.m. UTC | #10
On Tue, Feb 16, 2016 at 05:53:18PM +0000, Ian Jackson wrote:
> Jim Fehlig writes ("Re: [Xen-devel] [PATCH V13 5/5] xl: add pvusb commands"):
> > I just noticed this is the case with network devices as well. E.g.
> > 
> > #xl network-attach hvm-domU mac=00:16:3e:xx:yy:zz,bridge=br0
> > libxl: error: libxl_device.c:1095:device_hotplug_child_death_cb: script: Could
> > not find bridge device xenbr0
> 
> This is clearly a bug.
> 
> > main_networkattach() in tools/libxl/xl_cmdimpl.c doesn't split on
> > the ',', so everything after mac=00:16:3e:xx:yy:zz is ignored.
> 
> That's quite silly, isn't it.  Looking at the code it would also accept
>   mac=00:16:3e:aa:bb:cc:THIS:SHOULD:NOT:BE:HERE
> 
> The bug seems to be that the ad-hoc strtoul-based mac address parser
> in xl_cmdimpl.c:parse_nic_config doesn't notice garbage after its
> option.
> 
> > I'd need advice on how to fix this though. Based on
> > xl-network-configuration doc and Xen tool's long history of
> > network-attach supporting that syntax, I'd say main_networkattach()
> > should be changed to split on ','. I could also change the docs. Do
> > tools maintainers have a preference, or alternative option?
> 
> I don't have a strong opinion, but I would lean towards insisting that
> on command lines each setting should be in its own argument.
> 

We should support both IMHO. Libxlu's disk spec parser is able to do
that with parse_disk_config_multistring.

Wei.

> Ian.
Ian Jackson Feb. 17, 2016, 12:17 p.m. UTC | #11
Wei Liu writes ("Re: [Xen-devel] [PATCH V13 5/5] xl: add pvusb commands"):
> On Tue, Feb 16, 2016 at 05:53:18PM +0000, Ian Jackson wrote:
> > I don't have a strong opinion, but I would lean towards insisting that
> > on command lines each setting should be in its own argument.
> 
> We should support both IMHO. Libxlu's disk spec parser is able to do
> that with parse_disk_config_multistring.

Fine by me.  As I say I don't have a strong opinion, so we should do
what Wei wants as he does :-).

Ian.
Chunyan Liu Feb. 19, 2016, 10:43 a.m. UTC | #12
>>> On 2/17/2016 at 12:56 AM, in message <20160216165608.GA21669@gmail.com>, Olaf
Hering <olaf@aepfle.de> wrote: 
> On Tue, Jan 19, Chunyan Liu wrote: 
>  
> >  #xl usbctrl-attach test_vm version=1 ports=8 
>  
> >  #xl usbdev-attach test_vm hostbus=1 hostaddr=2 
>  
> I think this does not handle the -N knob of xl. Other commands check the 
> global dryrun_only variable. 

Just sent V14. I tried to add dryrun_only codes but finally gave up. For usbdev-attach,
since it will automatically and dynamically create usb controller in some cases, it's hard
to print dryrun-only information.

Chunyan
>  
> Olaf 
>
Olaf Hering Feb. 19, 2016, 10:52 a.m. UTC | #13
On Fri, Feb 19, Chun Yan Liu wrote:

> 
> 
> >>> On 2/17/2016 at 12:56 AM, in message <20160216165608.GA21669@gmail.com>, Olaf
> Hering <olaf@aepfle.de> wrote: 
> > On Tue, Jan 19, Chunyan Liu wrote: 
> >  
> > >  #xl usbctrl-attach test_vm version=1 ports=8 
> >  
> > >  #xl usbdev-attach test_vm hostbus=1 hostaddr=2 
> >  
> > I think this does not handle the -N knob of xl. Other commands check the 
> > global dryrun_only variable. 
> 
> Just sent V14. I tried to add dryrun_only codes but finally gave up. For usbdev-attach,
> since it will automatically and dynamically create usb controller in some cases, it's hard
> to print dryrun-only information.

Not sure how to handle it, perhaps exit when xl -N is called?

Olaf
Olaf Hering Feb. 19, 2016, 12:07 p.m. UTC | #14
On Fri, Feb 19, Olaf Hering wrote:

> Not sure how to handle it, perhaps exit when xl -N is called?

Also the interface is 'xl -N' is not clearly defined. What is it
supposed to do with the newly introduced ctrl types? Should it display
the json just for the dev, just for the ctrl+dev or the entire ctrl with
all existing devs + the new dev?
Who is the consumer of the json output?
xl(1) says just "-N  Dry run: do not actually execute the command."

I'm asking this mainly in the context of main_vscsiattach, which right
now dumps the enitre ctrl with all existing devs + the new dev.

Olaf
Wei Liu Feb. 24, 2016, 12:03 p.m. UTC | #15
On Fri, Feb 19, 2016 at 01:07:08PM +0100, Olaf Hering wrote:
> On Fri, Feb 19, Olaf Hering wrote:
> 
> > Not sure how to handle it, perhaps exit when xl -N is called?
> 
> Also the interface is 'xl -N' is not clearly defined. What is it
> supposed to do with the newly introduced ctrl types? Should it display
> the json just for the dev, just for the ctrl+dev or the entire ctrl with
> all existing devs + the new dev?
> Who is the consumer of the json output?
> xl(1) says just "-N  Dry run: do not actually execute the command."
> 
> I'm asking this mainly in the context of main_vscsiattach, which right
> now dumps the enitre ctrl with all existing devs + the new dev.
> 

I just turn everything into JSON and print it out?

Say, if you only add a controller, you just print the ctrl JSON. If you
add a controller and a bunch of devices, you print all of them. Does
this sound plausible?

I tend to think dryrun output is only used by administrator to eye-ball
the resulting structure. I'm not sure if it is meant to be stable at
all.

Maybe Ian has a second opinion on this.

Wei.

> Olaf
Olaf Hering Feb. 24, 2016, 12:52 p.m. UTC | #16
On Wed, Feb 24, Wei Liu wrote:

> Say, if you only add a controller, you just print the ctrl JSON. If you
> add a controller and a bunch of devices, you print all of them. Does
> this sound plausible?

Yes.

Olaf
diff mbox

Patch

diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index 4279c7c..7e0a380 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -1345,6 +1345,41 @@  List pass-through pci devices for a domain.
 
 =back
 
+=head1 USB PASS-THROUGH
+
+=over 4
+
+=item B<usbctrl-attach> I<domain-id> I<usbctrl-device>
+
+Create a new USB controller in the domain specified by I<domain-id>,
+I<usbctrl-device> describes the device to attach, using the same format
+as the B<usbctrl> string in the domain config file. See L<xl.cfg> for
+more information.
+
+=item B<usbctrl-detach> I<domain-id> I<devid>
+
+Destroy a USB controller from the specified domain.
+B<devid> is devid of the USB controller.
+
+=item B<usbdev-attach> I<domain-id> I<usbdev-device>
+
+Hot-plug a new pass-through USB device to the domain specified by
+I<domain-id>, I<usbdev-device> describes the device to attach, using
+the same format as the B<usbdev> string in the domain config file.
+See L<xl.cfg> for more information.
+
+=item B<usbdev-detach> I<domain-id> I<controller=devid> I<port=number>
+
+Hot-unplug a previously assigned USB device from a domain.
+B<controller=devid> and B<port=number> is USB controller:port in guest
+where the USB device is attached to.
+
+=item B<usb-list> I<domain-id>
+
+List pass-through usb devices for a domain.
+
+=back
+
 =head1 TMEM
 
 =over 4
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index bdab125..309627a 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -92,6 +92,11 @@  int main_blockdetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
+int main_usbctrl_attach(int argc, char **argv);
+int main_usbctrl_detach(int argc, char **argv);
+int main_usbdev_attach(int argc, char **argv);
+int main_usbdev_detach(int argc, char **argv);
+int main_usblist(int argc, char **argv);
 int main_uptime(int argc, char **argv);
 int main_claims(int argc, char **argv);
 int main_tmem_list(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index d0715e6..a968e46 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3507,6 +3507,196 @@  int main_cd_insert(int argc, char **argv)
     return 0;
 }
 
+int main_usbctrl_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 0;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-attach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbctrl_config(&usbctrl, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+}
+
+int main_usbctrl_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, devid, rc;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbctrl-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
+        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+
+}
+
+int main_usbdev_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-attach", 2) {
+        /* No options */
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+
+    domid = find_domain(argv[optind++]);
+
+    for (argv += optind, argc -= optind; argc > 0; ++argv, --argc) {
+        if (parse_usbdev_config(&usbdev, *argv))
+            return 1;
+    }
+
+    rc = libxl_device_usbdev_add(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_add failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usbdev_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int ctrl, port;
+    int opt, rc = 1;
+    libxl_device_usbdev usbdev;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usbdev-detach", 3) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    ctrl = atoi(argv[optind+1]);
+    port = atoi(argv[optind+2]);
+
+    if (argc - optind > 3) {
+        fprintf(stderr, "Invalid arguments.\n");
+        return 1;
+    }
+
+    libxl_device_usbdev_init(&usbdev);
+    if (libxl_ctrlport_to_device_usbdev(ctx, domid, ctrl, port, &usbdev)) {
+        fprintf(stderr, "Unknown device at controller %d port %d.\n",
+                ctrl, port);
+        return 1;
+    }
+
+    rc = libxl_device_usbdev_remove(ctx, domid, &usbdev, 0);
+    if (rc) {
+        fprintf(stderr, "libxl_device_usbdev_remove failed.\n");
+        rc = 1;
+    }
+
+    libxl_device_usbdev_dispose(&usbdev);
+    return rc;
+}
+
+int main_usblist(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_device_usbctrl *usbctrls;
+    libxl_usbctrlinfo usbctrlinfo;
+    int numctrl, i, j, opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    if (argc > optind) {
+        fprintf(stderr, "Invalid arguments.\n");
+        exit(-1);
+    }
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!usbctrls) {
+        return 0;
+    }
+
+    for (i = 0; i < numctrl; ++i) {
+        printf("%-6s %-6s %-3s %-5s %-7s %-5s\n",
+                "Devid", "Type", "BE", "state", "usb-ver", "ports");
+
+        libxl_usbctrlinfo_init(&usbctrlinfo);
+
+        if (!libxl_device_usbctrl_getinfo(ctx, domid,
+                                &usbctrls[i], &usbctrlinfo)) {
+            printf("%-6d %-6s %-3d %-5d %-7d %-5d\n",
+                    usbctrlinfo.devid,
+                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
+                    usbctrlinfo.backend_id, usbctrlinfo.state,
+                    usbctrlinfo.version, usbctrlinfo.ports);
+
+            for (j = 1; j <= usbctrlinfo.ports; j++) {
+                libxl_device_usbdev usbdev;
+
+                libxl_device_usbdev_init(&usbdev);
+
+                printf("  Port %d:", j);
+
+                if (!libxl_ctrlport_to_device_usbdev(ctx, domid,
+                                                     usbctrlinfo.devid,
+                                                     j, &usbdev)) {
+                    printf(" Bus %03x Device %03x\n",
+                           usbdev.u.hostdev.hostbus,
+                           usbdev.u.hostdev.hostaddr);
+                } else {
+                    printf("\n");
+                }
+
+                libxl_device_usbdev_dispose(&usbdev);
+            }
+        }
+
+        libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    }
+
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return 0;
+}
+
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index fdc1ac6..b14b881 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -553,6 +553,31 @@  struct cmd_spec cmd_table[] = {
     },
 
 #endif
+    { "usbctrl-attach",
+      &main_usbctrl_attach, 0, 1,
+      "Create a virtual USB controller for a domain",
+      "<Domain> [type=pv] [version=<version>] [ports=<number>]",
+    },
+    { "usbctrl-detach",
+      &main_usbctrl_detach, 0, 1,
+      "Remove the virtual USB controller specified by <DevId> for a domain",
+      "<Domain> <DevId>",
+    },
+    { "usbdev-attach",
+      &main_usbdev_attach, 0, 1,
+      "Attach a USB device to a domain",
+      "<Domain> hostbus=<busnum> hostaddr=<devnum> [controller=<DevId> [port=<port>]]",
+    },
+    { "usbdev-detach",
+      &main_usbdev_detach, 0, 1,
+      "Detach a USB device from a domain",
+      "<Domain> <controller> <port>",
+    },
+    { "usb-list",
+      &main_usblist, 0, 0,
+      "List information about all USB controllers and devices for a domain",
+      "<Domain>",
+    },
 };
 
 int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);