Message ID | 1453192795-15693-6-git-send-email-cyliu@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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.
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
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 >
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.
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. >
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.
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
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.
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 > >
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.
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.
>>> 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 >
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
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
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
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 --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);