/* * Copyright (c) 2013-2020 Intel Corporation. All rights reserved. * Copyright (c) 2016 Cisco Systems, Inc. All rights reserved. * * This software is available to you under the BSD license below: * * Redistribution and use in source and binary forms, with or * without modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "config.h" #include #include #include #include #include #include #include #include static struct fi_info *hints; static char *node, *port; static int ver = 0; static int list_providers = 0; static int verbose = 0, env = 0; static char *envstr; /* options and matching help strings need to be kept in sync */ static const struct option longopts[] = { {"help", no_argument, NULL, 'h'}, {"src_addr", required_argument, NULL, 's'}, {"node", required_argument, NULL, 'n'}, {"port", required_argument, NULL, 'P'}, {"caps", required_argument, NULL, 'c'}, {"mode", required_argument, NULL, 'm'}, {"ep_type", required_argument, NULL, 't'}, {"domain", required_argument, NULL, 'd'}, {"fabric", required_argument, NULL, 'f'}, {"addr_format", required_argument, NULL, 'a'}, {"provider", required_argument, NULL, 'p'}, {"env", no_argument, NULL, 'e'}, {"getenv", required_argument, NULL, 'g'}, {"info", required_argument, NULL, 'i'}, {"list", no_argument, NULL, 'l'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, &ver, 1}, {0,0,0,0} }; static const char *help_strings[][2] = { {"", "\t\tdisplay this help and exit"}, {"ADDR", "\t\tsource name or address"}, {"NAME", "\t\tdest node name or address"}, {"PNUM", "\t\tport number"}, {"CAP1|CAP2..", "\tone or more capabilities: FI_MSG|FI_RMA..."}, {"MOD1|MOD2..", "\tone or more modes, default all modes"}, {"EPTYPE", "\t\tspecify single endpoint type: FI_EP_MSG, FI_EP_DGRAM..."}, {"DOMAIN", "\t\tspecify the domain name"}, {"FABRIC", "\t\tspecify the fabric name"}, {"FMT", "\t\tspecify accepted address format: FI_FORMAT_UNSPEC, FI_SOCKADDR..."}, {"PROV", "\t\tspecify provider explicitly"}, {"", "\t\tprint libfabric environment variables"}, {"SUBSTR", "\t\tprint libfabric environment variables with substr"}, {"", "\t\tprint fi_info structures containing substr"}, {"", "\t\tlist available libfabric providers"}, {"", "\t\tverbose output"}, {"", "\t\tprint version info and exit"}, {"", ""} }; static void usage(void) { int i = 0; const struct option *ptr = longopts; for (; ptr->name != NULL; ++i, ptr = &longopts[i]) if (ptr->has_arg == required_argument) printf(" -%c, --%s=%s%s\n", ptr->val, ptr->name, help_strings[i][0], help_strings[i][1]); else if (ptr->flag != NULL) printf(" --%s\t%s\n", ptr->name, help_strings[i][1]); else printf(" -%c, --%s\t%s\n", ptr->val, ptr->name, help_strings[i][1]); } #define ORCASE(SYM) \ do { \ if (strcasecmp(#SYM, inputstr) == 0) { \ *value = SYM; \ return 0; \ } \ } while (0) static int str2cap(char *inputstr, uint64_t *value) { ORCASE(FI_MSG); ORCASE(FI_RMA); ORCASE(FI_TAGGED); ORCASE(FI_ATOMIC); ORCASE(FI_MULTICAST); ORCASE(FI_COLLECTIVE); ORCASE(FI_READ); ORCASE(FI_WRITE); ORCASE(FI_RECV); ORCASE(FI_SEND); ORCASE(FI_REMOTE_READ); ORCASE(FI_REMOTE_WRITE); ORCASE(FI_MULTI_RECV); ORCASE(FI_REMOTE_CQ_DATA); ORCASE(FI_MORE); ORCASE(FI_PEEK); ORCASE(FI_TRIGGER); ORCASE(FI_FENCE); ORCASE(FI_SOURCE_ERR); ORCASE(FI_LOCAL_COMM); ORCASE(FI_REMOTE_COMM); ORCASE(FI_SHARED_AV); ORCASE(FI_RMA_EVENT); ORCASE(FI_SOURCE); ORCASE(FI_NAMED_RX_CTX); ORCASE(FI_DIRECTED_RECV); ORCASE(FI_HMEM); fprintf(stderr, "error: Unrecognized capability: %s\n", inputstr); return -EINVAL; } static int str2mode(char *inputstr, uint64_t *value) { ORCASE(FI_CONTEXT); ORCASE(FI_MSG_PREFIX); ORCASE(FI_ASYNC_IOV); ORCASE(FI_RX_CQ_DATA); ORCASE(FI_LOCAL_MR); ORCASE(FI_CONTEXT2); fprintf(stderr, "error: Unrecognized mode: %s\n", inputstr); return -EINVAL; } static int str2ep_type(char *inputstr, enum fi_ep_type *value) { ORCASE(FI_EP_UNSPEC); ORCASE(FI_EP_MSG); ORCASE(FI_EP_DGRAM); ORCASE(FI_EP_RDM); fprintf(stderr, "error: Unrecognized endpoint type: %s\n", inputstr); return -EINVAL; } static int str2addr_format(char *inputstr, uint32_t *value) { ORCASE(FI_FORMAT_UNSPEC); ORCASE(FI_SOCKADDR); ORCASE(FI_SOCKADDR_IN); ORCASE(FI_SOCKADDR_IN6); ORCASE(FI_SOCKADDR_IB); ORCASE(FI_ADDR_MLX); ORCASE(FI_ADDR_STR); ORCASE(FI_ADDR_PSMX2); ORCASE(FI_ADDR_EFA); fprintf(stderr, "error: Unrecognized address format: %s\n", inputstr); return -EINVAL; } static int tokparse(char *caps, int (*str2flag)(char *, uint64_t *), uint64_t *flags) { uint64_t value; char *tok; int ret; for (tok = strtok(caps, "|"); tok != NULL; tok = strtok(NULL, "|")) { ret = str2flag(tok, &value); if (ret) return ret; *flags |= value; } return 0; } static const char *param_type(enum fi_param_type type) { switch (type) { case FI_PARAM_STRING: return "String"; case FI_PARAM_INT: return "Integer"; case FI_PARAM_SIZE_T: return "size_t"; case FI_PARAM_BOOL: return "Boolean (0/1, on/off, true/false, yes/no)"; default: return "Unknown"; } } static int print_vars(void) { int ret, count, i; struct fi_param *params; char delim; ret = fi_getparams(¶ms, &count); if (ret) return ret; for (i = 0; i < count; ++i) { if (envstr && !strcasestr(params[i].name, envstr)) continue; printf("# %s: %s\n", params[i].name, param_type(params[i].type)); printf("# %s\n", params[i].help_string); if (params[i].value) { delim = strchr(params[i].value, ' ') ? '"' : '\0'; printf("%s=%c%s%c\n", params[i].name, delim, params[i].value, delim); } printf("\n"); } fi_freeparams(params); return ret; } static int print_providers(struct fi_info *info) { struct fi_info *cur; for (cur = info; cur; cur = cur->next) { printf("%s:\n", cur->fabric_attr->prov_name); printf(" version: %d.%d\n", FI_MAJOR(cur->fabric_attr->prov_version), FI_MINOR(cur->fabric_attr->prov_version)); } return EXIT_SUCCESS; } static int print_short_info(struct fi_info *info) { struct fi_info *cur; for (cur = info; cur; cur = cur->next) { printf("provider: %s\n", cur->fabric_attr->prov_name); printf(" fabric: %s\n", cur->fabric_attr->name), printf(" domain: %s\n", cur->domain_attr->name), printf(" version: %d.%d\n", FI_MAJOR(cur->fabric_attr->prov_version), FI_MINOR(cur->fabric_attr->prov_version)); if (!list_providers) { printf(" type: %s\n", fi_tostr(&cur->ep_attr->type, FI_TYPE_EP_TYPE)); printf(" protocol: %s\n", fi_tostr(&cur->ep_attr->protocol, FI_TYPE_PROTOCOL)); } } return EXIT_SUCCESS; } static int print_long_info(struct fi_info *info) { char buf[8192]; struct fi_info *cur; for (cur = info; cur; cur = cur->next) { fi_tostr_r(buf, sizeof(buf), cur, FI_TYPE_INFO); if (!envstr || strcasestr(buf, envstr)) { printf("---\n"); printf("%s", buf); } } return EXIT_SUCCESS; } static int run(struct fi_info *hints, char *node, char *port, uint64_t flags) { struct fi_info *info; int ret; ret = fi_getinfo(FI_VERSION(FI_MAJOR_VERSION, FI_MINOR_VERSION), node, port, flags, hints, &info); if (ret) { fprintf(stderr, "fi_getinfo: %d (%s)\n", ret, fi_strerror(-ret)); return ret; } if (env) ret = print_vars(); else if (verbose) ret = print_long_info(info); else if (list_providers) ret = print_providers(info); else ret = print_short_info(info); fi_freeinfo(info); return ret; } int main(int argc, char **argv) { uint64_t flags = 0; int op, ret, option_index; int use_hints = 0; hints = fi_allocinfo(); if (!hints) return EXIT_FAILURE; hints->mode = ~0; hints->domain_attr->mode = ~0; hints->domain_attr->mr_mode = ~(FI_MR_BASIC | FI_MR_SCALABLE); while ((op = getopt_long(argc, argv, "s:n:P:c:m:t:a:p:d:f:eg:i:lhv", longopts, &option_index)) != -1) { switch (op) { case 0: /* there is no short variant only for --version */ if (ver) { printf("%s: %s\n", argv[0], PACKAGE_VERSION); printf("libfabric: %s\n", fi_tostr("1", FI_TYPE_VERSION)); printf("libfabric api: %d.%d\n", FI_MAJOR_VERSION, FI_MINOR_VERSION); return EXIT_SUCCESS; } goto print_help; case 's': node = optarg; flags |= FI_SOURCE; break; case 'n': node = optarg; break; case 'P': port = optarg; break; case 'c': ret = tokparse(optarg, str2cap, &hints->caps); if (ret) goto out; use_hints = 1; break; case 'm': hints->mode = 0; ret = tokparse(optarg, str2mode, &hints->mode); if (ret) goto out; use_hints = 1; break; case 't': ret = str2ep_type(optarg, &hints->ep_attr->type); if (ret) goto out; use_hints = 1; break; case 'a': ret = str2addr_format(optarg, &hints->addr_format); if (ret) goto out; use_hints = 1; break; case 'p': free(hints->fabric_attr->prov_name); hints->fabric_attr->prov_name = strdup(optarg); use_hints = 1; break; case 'd': hints->domain_attr->name = strdup(optarg); use_hints = 1; break; case 'f': hints->fabric_attr->name = strdup(optarg); use_hints = 1; break; case 'g': envstr = optarg; /* fall through */ case 'e': env = 1; break; case 'l': list_providers = 1; flags |= FI_PROV_ATTR_ONLY; break; case 'i': envstr = optarg; /* fall through */ case 'v': verbose = 1; break; case 'h': default: print_help: printf("Usage: %s\n", argv[0]); usage(); return EXIT_FAILURE; } } ret = run(use_hints ? hints : NULL, node, port, flags); out: fi_freeinfo(hints); return -ret; }