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 <[email protected]>
> ---
>  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
[email protected]
Computer Scientist
High Performance Systems Division
Lawrence Livermore National Laboratory

_______________________________________________
general mailing list
[email protected]
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to