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
