[ofa-general] Re: [PATCH] infiniband-diags: command line option processing framework
Al Chu
chu11 at llnl.gov
Mon Jan 26 09:22:09 PST 2009
Hey Sasha,
Just wondering, what tools are you targeting for these unified command
line options? Since (doing a quick glance) it will break some options
for some tools.
for ibstat
/usr/sbin/ibstat -l # list all IB devices
I don't think there will be a lot of issues. Any changes will just have
to be announced/documented in the release notes so people can update
scripts.
Al
On Sun, 2009-01-25 at 13:51 +0200, Sasha Khapyorsky wrote:
> The main motivation of this is to unify infiniband-diags command line
> options and tools usage. Also it simplifies programming and can remove
> a lot of duplications. The usage message is also unified over all tools
> and looks like:
>
> Usage: ibaddr [options] [<lid|dr_path|guid>]
>
> Options:
> --gid_show, -g show gid address only
> --lid_show, -l show lid range only
> --Lid_show, -L show lid range (in decimal) only
> --Ca, -C <ca> Ca name to use
> --Port, -P <port> Ca port number to use
> --Direct, -D use Direct address argument
> --Guid, -G use GUID address argument
> --timeout, -t <ms> timeout in ms
> --sm_port, -s <lid> SM port lid
> --errors, -e show send and receive errors
> --verbose, -v increase verbosity level
> --debug, -d raise debug level
> --usage, -u usage message
> --help, -h help message
> --version, -V show version
>
> Examples:
> ibaddr # local port's address
> ibaddr 32 # show lid range and gid of lid 32
> ibaddr -G 0x8f1040023 # same but using guid address
> ibaddr -l 32 # show lid range only
> ibaddr -L 32 # show decimal lid range only
> ibaddr -g 32 # show gid address only
>
> Custom (per tool) option processing is also supported.
>
> Signed-off-by: Sasha Khapyorsky <sashak at voltaire.com>
> ---
> infiniband-diags/include/ibdiag_common.h | 28 +++-
> infiniband-diags/src/ibdiag_common.c | 248 ++++++++++++++++++++++++++++++
> 2 files changed, 274 insertions(+), 2 deletions(-)
>
> diff --git a/infiniband-diags/include/ibdiag_common.h b/infiniband-diags/include/ibdiag_common.h
> index 0518579..4304826 100644
> --- a/infiniband-diags/include/ibdiag_common.h
> +++ b/infiniband-diags/include/ibdiag_common.h
> @@ -35,18 +35,42 @@
> #ifndef _IBDIAG_COMMON_H_
> #define _IBDIAG_COMMON_H_
>
> +#include <infiniband/mad.h>
> +
> extern int ibdebug;
> +extern int ibverbose;
> +extern char *ibd_ca;
> +extern int ibd_ca_port;
> +extern int ibd_dest_type;
> +extern ib_portid_t *ibd_sm_id;
> +extern int ibd_timeout;
>
> /*========================================================*/
> /* External interface */
> /*========================================================*/
>
> #undef DEBUG
> -#define DEBUG if (ibdebug || verbose) IBWARN
> -#define VERBOSE if (ibdebug || verbose > 1) IBWARN
> +#define DEBUG if (ibdebug || ibverbose) IBWARN
> +#define VERBOSE if (ibdebug || ibverbose > 1) IBWARN
> #define IBERROR(fmt, args...) iberror(__FUNCTION__, fmt, ## args)
>
> extern void iberror(const char *fn, char *msg, ...);
> extern const char *get_build_version(void);
>
> +struct ibdiag_opt {
> + const char *name;
> + char letter;
> + unsigned has_arg;
> + const char *arg_tmpl;
> + const char *description;
> +};
> +
> +extern int ibdiag_process_opts(int argc, char * const argv[], void *context,
> + const char *exclude_common_str,
> + const struct ibdiag_opt custom_opts[],
> + int (*custom_handler)(void *cxt, int val, char *optarg),
> + const char *usage_args,
> + const char *usage_examples[]);
> +extern void ibdiag_show_usage();
> +
> #endif /* _IBDIAG_COMMON_H_ */
> diff --git a/infiniband-diags/src/ibdiag_common.c b/infiniband-diags/src/ibdiag_common.c
> index 3a9d5c2..8dcec5e 100644
> --- a/infiniband-diags/src/ibdiag_common.c
> +++ b/infiniband-diags/src/ibdiag_common.c
> @@ -46,11 +46,259 @@
> #include <unistd.h>
> #include <ctype.h>
> #include <config.h>
> +#include <getopt.h>
>
> +#include <infiniband/umad.h>
> +#include <infiniband/mad.h>
> #include <ibdiag_common.h>
> #include <ibdiag_version.h>
>
> int ibdebug;
> +int ibverbose;
> +char *ibd_ca;
> +int ibd_ca_port;
> +int ibd_dest_type = IB_DEST_LID;
> +ib_portid_t *ibd_sm_id;
> +int ibd_timeout;
> +
> +static ib_portid_t sm_portid = {0};
> +
> +static const char *prog_name;
> +static const char *prog_args;
> +static const char **prog_examples;
> +static struct option *long_opts;
> +static const struct ibdiag_opt *opts_map[256];
> +
> +static void pretty_print(int start, int width, const char *str)
> +{
> + int len = width - start;
> + const char *p, *e;
> +
> + while (1) {
> + while(isspace(*str))
> + str++;
> + p = str;
> + do {
> + e = p + 1;
> + p = strchr(e, ' ');
> + } while (p && p - str < len);
> + if (!p) {
> + fprintf(stderr, "%s", str);
> + break;
> + }
> + if (e - str == 1)
> + e = p;
> + fprintf(stderr, "%.*s\n%*s", e - str, str, start, "");
> + str = e;
> + }
> +}
> +
> +void ibdiag_show_usage()
> +{
> + struct option *o = long_opts;
> + int n;
> +
> + fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name,
> + prog_args ? prog_args : "");
> +
> + if (long_opts[0].name)
> + fprintf(stderr, "Options:\n");
> + for (o = long_opts; o->name; o++) {
> + const struct ibdiag_opt *io = opts_map[o->val];
> + n = fprintf(stderr, " --%s", io->name);
> + if (isprint(io->letter))
> + n += fprintf(stderr, ", -%c", io->letter);
> + if (io->has_arg)
> + n += fprintf(stderr, " %s",
> + io->arg_tmpl ? io->arg_tmpl : "<val>");
> + if (io->description && *io->description) {
> + n += fprintf(stderr, "%*s ", 24 - n > 0 ? 24 - n : 0, "");
> + pretty_print(n, 74, io->description);
> + }
> + fprintf(stderr, "\n");
> + }
> +
> + if (prog_examples) {
> + const char **p;
> + fprintf(stderr, "\nExamples:\n");
> + for (p = prog_examples; *p && **p; p++)
> + fprintf(stderr, " %s %s\n", prog_name, *p);
> + }
> +
> + fprintf(stderr, "\n");
> +
> + exit(2);
> +}
> +
> +static int process_opt(int ch, char *optarg)
> +{
> + int val;
> +
> + switch (ch) {
> + case 'h':
> + case 'u':
> + ibdiag_show_usage();
> + break;
> + case 'V':
> + fprintf(stderr, "%s %s\n", prog_name, get_build_version());
> + exit(2);
> + case 'e':
> + madrpc_show_errors(1);
> + break;
> + case 'v':
> + ibverbose++;
> + break;
> + case 'd':
> + ibdebug++;
> + madrpc_show_errors(1);
> + umad_debug(ibdebug - 1);
> + break;
> + case 'C':
> + ibd_ca = optarg;
> + break;
> + case 'P':
> + ibd_ca_port = strtoul(optarg, 0, 0);
> + break;
> + case 'D':
> + ibd_dest_type = IB_DEST_DRPATH;
> + break;
> + case 'L':
> + ibd_dest_type = IB_DEST_LID;
> + break;
> + case 'G':
> + ibd_dest_type = IB_DEST_GUID;
> + break;
> + case 't':
> + val = strtoul(optarg, 0, 0);
> + madrpc_set_timeout(val);
> + ibd_timeout = val;
> + break;
> + case 's':
> + if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
> + IBERROR("cannot resolve SM destination port %s", optarg);
> + ibd_sm_id = &sm_portid;
> + break;
> + default:
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static const struct ibdiag_opt common_opts[] = {
> + { "Ca", 'C', 1, "<ca>", "Ca name to use"},
> + { "Port", 'P', 1, "<port>", "Ca port number to use"},
> + { "Direct", 'D', 0, NULL, "use Direct address argument"},
> + { "Lid", 'L', 0, NULL, "use LID address argument"},
> + { "Guid", 'G', 0, NULL, "use GUID address argument"},
> + { "timeout", 't', 1, "<ms>", "timeout in ms"},
> + { "sm_port", 's', 1, "<lid>", "SM port lid" },
> + { "errors", 'e', 0, NULL, "show send and receive errors" },
> + { "verbose", 'v', 0, NULL, "increase verbosity level" },
> + { "debug", 'd', 0, NULL, "raise debug level" },
> + { "usage", 'u', 0, NULL, "usage message" },
> + { "help", 'h', 0, NULL, "help message" },
> + { "version", 'V', 0, NULL, "show version" },
> + {}
> +};
> +
> +static void make_opt(struct option *l, const struct ibdiag_opt *o,
> + const struct ibdiag_opt *map[])
> +{
> + l->name = o->name;
> + l->has_arg = o->has_arg;
> + l->flag = NULL;
> + l->val = o->letter;
> + if (!map[l->val])
> + map[l->val] = o;
> +}
> +
> +static struct option *make_long_opts(const char *exclude_str,
> + const struct ibdiag_opt *custom_opts,
> + const struct ibdiag_opt *map[])
> +{
> + struct option *long_opts, *l;
> + const struct ibdiag_opt *o;
> + unsigned n = 0;
> +
> + if (custom_opts)
> + for (o = custom_opts; o->name; o++)
> + n++;
> +
> + long_opts = malloc((sizeof(common_opts)/sizeof(common_opts[0]) + n) *
> + sizeof(*long_opts));
> + if (!long_opts)
> + return NULL;
> +
> + l = long_opts;
> +
> + if (custom_opts)
> + for (o = custom_opts; o->name; o++)
> + make_opt(l++, o, map);
> +
> + for (o = common_opts; o->name; o++) {
> + if (exclude_str && strchr(exclude_str, o->letter))
> + continue;
> + make_opt(l++, o, map);
> + }
> +
> + memset(l, 0, sizeof(*l));
> +
> + return long_opts;
> +}
> +
> +static void make_str_opts(const struct option *o, char *p, unsigned size)
> +{
> + int i, n = 0;
> +
> + for (n = 0; o->name && n + 2 + o->has_arg < size; o++) {
> + p[n++] = o->val;
> + for (i = 0; i < o->has_arg; i++)
> + p[n++] = ':';
> + }
> + p[n] = '\0';
> +}
> +
> +int ibdiag_process_opts(int argc, char * const argv[], void *cxt,
> + const char *exclude_common_str,
> + const struct ibdiag_opt custom_opts[],
> + int (*custom_handler)(void *cxt, int val, char *optarg),
> + const char *usage_args, const char *usage_examples[])
> +{
> + char str_opts[1024];
> + const struct ibdiag_opt *o;
> +
> + memset(opts_map, 0, sizeof(opts_map));
> +
> + prog_name = argv[0];
> + prog_args = usage_args;
> + prog_examples = usage_examples;
> +
> + long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map);
> + if (!long_opts)
> + return -1;
> +
> + make_str_opts(long_opts, str_opts, sizeof(str_opts));
> +
> + while (1) {
> + int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
> + if ( ch == -1 )
> + break;
> + o = opts_map[ch];
> + if (!o)
> + ibdiag_show_usage();
> + if (custom_handler) {
> + if (custom_handler(cxt, ch, optarg) &&
> + process_opt(ch, optarg))
> + ibdiag_show_usage();
> + } else if (process_opt(ch, optarg))
> + ibdiag_show_usage();
> + }
> +
> + free(long_opts);
> +
> + return 0;
> +}
>
> extern char *argv0;
>
--
Albert Chu
chu11 at llnl.gov
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory
More information about the general
mailing list