2 * Copyright (c) 2006-2007 The Regents of the University of California.
3 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4 * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
5 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * Copyright (c) 2009 HNR Consulting. All rights reserved.
7 * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
9 * This software is available to you under a choice of one of two
10 * licenses. You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
23 * - Redistributions in binary form must reproduce the above
24 * copyright notice, this list of conditions and the following
25 * disclaimer in the documentation and/or other materials
26 * provided with the distribution.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40 * Define common functions which can be included in the various C based diags.
49 #include <sys/types.h>
58 #include <infiniband/umad.h>
59 #include <infiniband/mad.h>
60 #include <ibdiag_common.h>
61 #include <ibdiag_version.h>
64 enum MAD_DEST ibd_dest_type = IB_DEST_LID;
65 ib_portid_t *ibd_sm_id;
66 static ib_portid_t sm_portid = { 0 };
68 /* general config options */
69 #define IBDIAG_CONFIG_GENERAL IBDIAG_CONFIG_PATH"/ibdiag.conf"
73 uint32_t ibd_ibnetdisc_flags = IBND_CONFIG_MLX_EPI;
75 uint64_t ibd_sakey = 0;
77 char *ibd_nd_format = NULL;
79 static const char *prog_name;
80 static const char *prog_args;
81 static const char **prog_examples;
82 static struct option *long_opts = NULL;
83 static const struct ibdiag_opt *opts_map[256];
85 static const char *get_build_version(void)
87 return "BUILD VERSION: " IBDIAG_VERSION;
90 static void pretty_print(int start, int width, const char *str)
92 int len = width - start;
102 } while (p && p - str < len);
104 fprintf(stderr, "%s", str);
109 fprintf(stderr, "%.*s\n%*s", (int)(e - str), str, start, "");
114 static inline int val_str_true(const char *val_str)
116 return ((strncmp(val_str, "TRUE", strlen("TRUE")) == 0) ||
117 (strncmp(val_str, "true", strlen("true")) == 0));
120 void read_ibdiag_config(const char *file)
123 FILE *config_fd = NULL;
124 char *p_prefix, *p_last;
129 /* silently ignore missing config file */
130 if (stat(file, &statbuf))
133 config_fd = fopen(file, "r");
137 while (fgets(buf, sizeof buf, config_fd) != NULL) {
138 p_prefix = strtok_r(buf, "\n", &p_last);
140 continue; /* ignore blank lines */
142 if (*p_prefix == '#')
143 continue; /* ignore comment lines */
145 name = strtok_r(p_prefix, "=", &p_last);
146 val_str = strtok_r(NULL, "\n", &p_last);
148 if (strncmp(name, "CA", strlen("CA")) == 0) {
150 ibd_ca = strdup(val_str);
151 } else if (strncmp(name, "Port", strlen("Port")) == 0) {
152 ibd_ca_port = strtoul(val_str, NULL, 0);
153 } else if (strncmp(name, "timeout", strlen("timeout")) == 0) {
154 ibd_timeout = strtoul(val_str, NULL, 0);
155 } else if (strncmp(name, "MLX_EPI", strlen("MLX_EPI")) == 0) {
156 if (val_str_true(val_str)) {
157 ibd_ibnetdisc_flags |= IBND_CONFIG_MLX_EPI;
159 ibd_ibnetdisc_flags &= ~IBND_CONFIG_MLX_EPI;
161 } else if (strncmp(name, "m_key", strlen("m_key")) == 0) {
162 ibd_mkey = strtoull(val_str, 0, 0);
163 } else if (strncmp(name, "sa_key",
164 strlen("sa_key")) == 0) {
165 ibd_sakey = strtoull(val_str, 0, 0);
166 } else if (strncmp(name, "nd_format",
167 strlen("nd_format")) == 0) {
168 ibd_nd_format = strdup(val_str);
176 void ibdiag_show_usage()
178 struct option *o = long_opts;
181 fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name,
182 prog_args ? prog_args : "");
184 if (long_opts[0].name)
185 fprintf(stderr, "Options:\n");
186 for (o = long_opts; o->name; o++) {
187 const struct ibdiag_opt *io = opts_map[o->val];
188 n = fprintf(stderr, " --%s", io->name);
189 if (isprint(io->letter))
190 n += fprintf(stderr, ", -%c", io->letter);
192 n += fprintf(stderr, " %s",
193 io->arg_tmpl ? io->arg_tmpl : "<val>");
194 if (io->description && *io->description) {
195 n += fprintf(stderr, "%*s ", 24 - n > 0 ? 24 - n : 0,
197 pretty_print(n, 74, io->description);
199 fprintf(stderr, "\n");
204 fprintf(stderr, "\nExamples:\n");
205 for (p = prog_examples; *p && **p; p++)
206 fprintf(stderr, " %s %s\n", prog_name, *p);
209 fprintf(stderr, "\n");
214 static int process_opt(int ch, char *optarg)
221 read_ibdiag_config(optarg);
227 fprintf(stderr, "%s %s\n", prog_name, get_build_version());
230 madrpc_show_errors(1);
237 madrpc_show_errors(1);
238 umad_debug(ibdebug - 1);
244 ibd_ca_port = strtoul(optarg, 0, 0);
246 IBEXIT("cannot resolve CA port %d", ibd_ca_port);
249 ibd_dest_type = IB_DEST_DRPATH;
252 ibd_dest_type = IB_DEST_LID;
255 ibd_dest_type = IB_DEST_GUID;
259 val = strtol(optarg, &endp, 0);
260 if (errno || (endp && *endp != '\0') || val <= 0 ||
262 IBEXIT("Invalid timeout \"%s\". Timeout requires a "
263 "positive integer value < %d.", optarg, INT_MAX);
265 madrpc_set_timeout((int)val);
266 ibd_timeout = (int)val;
270 /* srcport is not required when resolving via IB_DEST_LID */
271 if (resolve_portid_str(ibd_ca, ibd_ca_port, &sm_portid, optarg,
272 IB_DEST_LID, 0, NULL) < 0)
273 IBEXIT("cannot resolve SM destination port %s",
275 ibd_sm_id = &sm_portid;
282 ibd_mkey = strtoull(optarg, &endp, 0);
283 if (errno || *endp != '\0') {
285 ibd_mkey = strtoull(getpass("M_Key: "), &endp, 0);
286 if (errno || *endp != '\0') {
298 static const struct ibdiag_opt common_opts[] = {
299 {"config", 'z', 1, "<config>", "use config file, default: " IBDIAG_CONFIG_GENERAL},
300 {"Ca", 'C', 1, "<ca>", "Ca name to use"},
301 {"Port", 'P', 1, "<port>", "Ca port number to use"},
302 {"Direct", 'D', 0, NULL, "use Direct address argument"},
303 {"Lid", 'L', 0, NULL, "use LID address argument"},
304 {"Guid", 'G', 0, NULL, "use GUID address argument"},
305 {"timeout", 't', 1, "<ms>", "timeout in ms"},
306 {"sm_port", 's', 1, "<lid>", "SM port lid"},
307 {"show_keys", 'K', 0, NULL, "display security keys in output"},
308 {"m_key", 'y', 1, "<key>", "M_Key to use in request"},
309 {"errors", 'e', 0, NULL, "show send and receive errors"},
310 {"verbose", 'v', 0, NULL, "increase verbosity level"},
311 {"debug", 'd', 0, NULL, "raise debug level"},
312 {"help", 'h', 0, NULL, "help message"},
313 {"version", 'V', 0, NULL, "show version"},
317 static void make_opt(struct option *l, const struct ibdiag_opt *o,
318 const struct ibdiag_opt *map[])
321 l->has_arg = o->has_arg;
328 static struct option *make_long_opts(const char *exclude_str,
329 const struct ibdiag_opt *custom_opts,
330 const struct ibdiag_opt *map[])
332 struct option *long_opts, *l;
333 const struct ibdiag_opt *o;
337 for (o = custom_opts; o->name; o++)
340 long_opts = malloc((sizeof(common_opts) / sizeof(common_opts[0]) + n) *
348 for (o = custom_opts; o->name; o++)
349 make_opt(l++, o, map);
351 for (o = common_opts; o->name; o++) {
352 if (exclude_str && strchr(exclude_str, o->letter))
354 make_opt(l++, o, map);
357 memset(l, 0, sizeof(*l));
362 static void make_str_opts(const struct option *o, char *p, unsigned size)
366 for (n = 0; o->name && n + 2 + o->has_arg < size; o++) {
367 p[n++] = (char)o->val;
368 for (i = 0; i < (unsigned)o->has_arg; i++)
374 int ibdiag_process_opts(int argc, char *const argv[], void *cxt,
375 const char *exclude_common_str,
376 const struct ibdiag_opt custom_opts[],
377 int (*custom_handler) (void *cxt, int val,
379 const char *usage_args, const char *usage_examples[])
382 const struct ibdiag_opt *o;
385 prog_args = usage_args;
386 prog_examples = usage_examples;
391 long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map);
395 read_ibdiag_config(IBDIAG_CONFIG_GENERAL);
397 make_str_opts(long_opts, str_opts, sizeof(str_opts));
400 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
406 if (custom_handler) {
407 if (custom_handler(cxt, ch, optarg) &&
408 process_opt(ch, optarg))
410 } else if (process_opt(ch, optarg))
417 void ibexit(const char *fn, char *msg, ...)
424 n = vsprintf(buf, msg, va);
429 printf("%s: iberror: [pid %d] %s: failed: %s\n",
430 prog_name ? prog_name : "", getpid(), fn, buf);
432 printf("%s: iberror: failed: %s\n",
433 prog_name ? prog_name : "", buf);
439 conv_cnt_human_readable(uint64_t val64, float *val, int data)
441 uint64_t tmp = val64;
452 *val = (float)(val64);
455 if (*val/div > 1024) {
504 int is_port_info_extended_supported(ib_portid_t * dest, int port,
505 struct ibmad_port *srcport)
507 uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
511 if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, port, 0, srcport))
512 IBEXIT("port info query failed");
514 mad_decode_field(data, IB_PORT_CAPMASK_F, &cap_mask);
515 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_CAP_MASK2)) {
516 mad_decode_field(data, IB_PORT_CAPMASK2_F, &cap_mask2);
518 CL_NTOH16(IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED))) {
519 IBWARN("port info capability mask2 = 0x%x doesn't"
520 " indicate PortInfoExtended support", cap_mask2);
524 IBWARN("port info capability mask2 not supported");
531 int is_mlnx_ext_port_info_supported(uint32_t vendorid,
534 if (ibd_ibnetdisc_flags & IBND_CONFIG_MLX_EPI) {
536 if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 ||
537 ((vendorid == 0x119f) &&
539 (devid == 0x1b02 || devid == 0x1b50 ||
540 /* Bull SwitchIB and SwitchIB2 */
542 (devid >= 0x1bd0 && devid <= 0x1bd5))))
544 if ((devid >= 0x1003 && devid <= 0x1017) ||
545 ((vendorid == 0x119f) &&
547 (devid == 0x1b33 || devid == 0x1b73 ||
548 devid == 0x1b40 || devid == 0x1b41 ||
549 devid == 0x1b60 || devid == 0x1b61 ||
552 devid == 0x1b93 || devid == 0x1b94 ||
554 devid == 0x1bb4 || devid == 0x1bb5 ||
562 /** =========================================================================
563 * Resolve the SM portid using the umad layer rather than using
564 * ib_resolve_smlid_via which requires a PortInfo query on the local port.
566 int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id)
574 if ((rc = umad_get_port(ca_name, portnum, &port)) < 0)
577 memset(sm_id, 0, sizeof(*sm_id));
578 sm_id->lid = port.sm_lid;
579 sm_id->sl = port.sm_sl;
581 umad_release_port(&port);
586 /** =========================================================================
587 * Resolve local CA characteristics using the umad layer rather than using
588 * ib_resolve_self_via which requires SMP queries on the local port.
590 int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
591 int *portnum, ibmad_gid_t *gid)
594 uint64_t prefix, guid;
597 if (!(portid || portnum || gid))
600 if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0)
604 memset(portid, 0, sizeof(*portid));
605 portid->lid = port.base_lid;
606 portid->sl = port.sm_sl;
609 *portnum = port.portnum;
611 memset(gid, 0, sizeof(*gid));
612 prefix = cl_ntoh64(port.gid_prefix);
613 guid = cl_ntoh64(port.port_guid);
614 mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix);
615 mad_encode_field(*gid, IB_GID_GUID_F, &guid);
618 umad_release_port(&port);
623 int resolve_gid(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
624 ibmad_gid_t gid, ib_portid_t * sm_id,
625 const struct ibmad_port *srcport)
627 ib_portid_t sm_portid;
628 char buf[IB_SA_DATA_SIZE] = { 0 };
632 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
637 ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0)
643 int resolve_guid(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
644 uint64_t *guid, ib_portid_t *sm_id,
645 const struct ibmad_port *srcport)
647 ib_portid_t sm_portid;
648 uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
654 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
658 if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0)
661 memcpy(&prefix, portid->gid, sizeof(prefix));
663 mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
664 IB_DEFAULT_SUBN_PREFIX);
666 mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);
669 ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0)
672 mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl);
677 * Callers of this function should ensure their ibmad_port has been opened with
678 * IB_SA_CLASS as this function may require the SA to resolve addresses.
680 int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
681 char *addr_str, enum MAD_DEST dest_type,
682 ib_portid_t *sm_id, const struct ibmad_port *srcport)
688 ib_portid_t selfportid = { 0 };
691 memset(portid, 0, sizeof *portid);
695 lid = strtol(addr_str, 0, 0);
696 if (!IB_LID_VALID(lid))
698 return ib_portid_set(portid, lid, 0, 0);
701 if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0)
706 if (!(guid = strtoull(addr_str, 0, 0)))
709 /* keep guid in portid? */
710 return resolve_guid(ca_name, ca_port, portid, &guid, sm_id,
714 lid = strtol(addr_str, &routepath, 0);
716 if (!IB_LID_VALID(lid))
718 ib_portid_set(portid, lid, 0, 0);
720 /* handle DR parsing and set DrSLID to local lid */
721 if (resolve_self(ca_name, ca_port, &selfportid, &selfport,
724 if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) <
730 if (inet_pton(AF_INET6, addr_str, &gid) <= 0)
732 return resolve_gid(ca_name, ca_port, portid, gid, sm_id,
735 IBWARN("bad dest_type %d", dest_type);
741 static unsigned int get_max_width(unsigned int num)
743 unsigned r = 0; /* 1x */
759 static unsigned int get_max(unsigned int num)
761 unsigned r = 0; // r will be lg(num)
763 while (num >>= 1) // unroll for more speed...
769 void get_max_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port)
772 uint32_t max_speed = 0;
773 uint32_t cap_mask, rem_cap_mask, fdr10;
774 uint8_t *info = NULL;
776 uint32_t max_width = get_max_width(mad_get_field(port->info, 0,
777 IB_PORT_LINK_WIDTH_SUPPORTED_F)
778 & mad_get_field(port->remoteport->info, 0,
779 IB_PORT_LINK_WIDTH_SUPPORTED_F));
780 if ((max_width & mad_get_field(port->info, 0,
781 IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0)
782 // we are not at the max supported width
783 // print what we could be at.
784 snprintf(width_msg, msg_size, "Could be %s",
785 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F,
786 buf, 64, &max_width));
788 if (port->node->type == IB_NODE_SWITCH) {
789 if (port->node->ports[0])
790 info = (uint8_t *)&port->node->ports[0]->info;
793 info = (uint8_t *)&port->info;
796 cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
801 if (port->remoteport->node->type == IB_NODE_SWITCH) {
802 if (port->remoteport->node->ports[0])
803 info = (uint8_t *)&port->remoteport->node->ports[0]->info;
805 info = (uint8_t *)&port->remoteport->info;
808 rem_cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
811 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS) &&
812 rem_cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
813 goto check_ext_speed;
815 fdr10 = (mad_get_field(port->ext_info, 0,
816 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10)
817 && (mad_get_field(port->remoteport->ext_info, 0,
818 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10);
820 goto check_fdr10_active;
822 max_speed = get_max(mad_get_field(port->info, 0,
823 IB_PORT_LINK_SPEED_SUPPORTED_F)
824 & mad_get_field(port->remoteport->info, 0,
825 IB_PORT_LINK_SPEED_SUPPORTED_F));
826 if ((max_speed & mad_get_field(port->info, 0,
827 IB_PORT_LINK_SPEED_ACTIVE_F)) == 0)
828 // we are not at the max supported speed
829 // print what we could be at.
830 snprintf(speed_msg, msg_size, "Could be %s",
831 mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F,
832 buf, 64, &max_speed));
836 if (mad_get_field(port->info, 0,
837 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0 ||
838 mad_get_field(port->remoteport->info, 0,
839 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0)
840 goto check_fdr10_supp;
841 max_speed = get_max(mad_get_field(port->info, 0,
842 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F)
843 & mad_get_field(port->remoteport->info, 0,
844 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F));
845 if ((max_speed & mad_get_field(port->info, 0,
846 IB_PORT_LINK_SPEED_EXT_ACTIVE_F)) == 0)
847 // we are not at the max supported extended speed
848 // print what we could be at.
849 snprintf(speed_msg, msg_size, "Could be %s",
850 mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
851 buf, 64, &max_speed));
855 if ((mad_get_field(port->ext_info, 0,
856 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10) == 0) {
857 /* Special case QDR to try to avoid confusion with FDR10 */
858 if (mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F) == 4) /* QDR (10.0 Gbps) */
859 snprintf(speed_msg, msg_size,
860 "Could be FDR10 (Found link at QDR but expected speed is FDR10)");
862 snprintf(speed_msg, msg_size, "Could be FDR10");
866 int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
867 const char *format, va_list va_args)
871 len = strlen(mad_field_name(f));
872 if (len + 2 > n || spacing + 1 > n)
875 strncpy(buf, mad_field_name(f), n);
877 for (i = len+1; i < spacing+1; i++) {
881 ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args);
882 if (ret >= n - spacing)
885 return ret + spacing;
888 int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
889 const char *format, ...)
894 va_start(val, format);
895 ret = vsnprint_field(buf, n, f, spacing, format, val);
901 void dump_portinfo(void *pi, int tabs)
907 for (field = IB_PORT_FIRST_F; field < IB_PORT_LAST_F; field++) {
910 if (field == IB_PORT_MKEY_F && show_keys == 0) {
911 snprint_field(buf, 1024, field, 32, NOT_DISPLAYED_STR);
913 mad_decode_field(pi, field, val);
914 if (!mad_dump_field(field, buf, 1024, val))
920 for (field = IB_PORT_CAPMASK2_F;
921 field < IB_PORT_LINK_SPEED_EXT_LAST_F; field++) {
924 mad_decode_field(pi, field, val);
925 if (!mad_dump_field(field, buf, 1024, val))
931 op_fn_t *match_op(const match_rec_t match_tbl[], char *name)
933 const match_rec_t *r;
934 for (r = match_tbl; r->name; r++)
935 if (!strcasecmp(r->name, name) ||
936 (r->alias && !strcasecmp(r->alias, name)))