1 /* 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. 8 * 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: 14 * 15 * Redistribution and use in source and binary forms, with or 16 * without modification, are permitted provided that the following 17 * conditions are met: 18 * 19 * - Redistributions of source code must retain the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer. 22 * 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. 27 * 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 35 * SOFTWARE. 36 * 37 */ 38 39 /** 40 * Define common functions which can be included in the various C based diags. 41 */ 42 43 #define _GNU_SOURCE 44 #include <stdio.h> 45 #include <errno.h> 46 #include <string.h> 47 #include <stdlib.h> 48 #include <stdarg.h> 49 #include <sys/types.h> 50 #include <unistd.h> 51 #include <ctype.h> 52 #include <config.h> 53 #include <getopt.h> 54 #include <limits.h> 55 #include <sys/stat.h> 56 #include <stdarg.h> 57 58 #include <infiniband/umad.h> 59 #include <infiniband/mad.h> 60 #include <ibdiag_common.h> 61 #include <ibdiag_version.h> 62 63 int ibverbose; 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 }; 67 68 /* general config options */ 69 #define IBDIAG_CONFIG_GENERAL IBDIAG_CONFIG_PATH"/ibdiag.conf" 70 char *ibd_ca = NULL; 71 int ibd_ca_port = 0; 72 int ibd_timeout = 0; 73 uint32_t ibd_ibnetdisc_flags = IBND_CONFIG_MLX_EPI; 74 uint64_t ibd_mkey; 75 uint64_t ibd_sakey = 0; 76 int show_keys = 0; 77 char *ibd_nd_format = NULL; 78 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]; 84 85 static const char *get_build_version(void) 86 { 87 return "BUILD VERSION: " IBDIAG_VERSION " Build date: " __DATE__ " " 88 __TIME__; 89 } 90 91 static void pretty_print(int start, int width, const char *str) 92 { 93 int len = width - start; 94 const char *p, *e; 95 96 while (1) { 97 while (isspace(*str)) 98 str++; 99 p = str; 100 do { 101 e = p + 1; 102 p = strchr(e, ' '); 103 } while (p && p - str < len); 104 if (!p) { 105 fprintf(stderr, "%s", str); 106 break; 107 } 108 if (e - str == 1) 109 e = p; 110 fprintf(stderr, "%.*s\n%*s", (int)(e - str), str, start, ""); 111 str = e; 112 } 113 } 114 115 static inline int val_str_true(const char *val_str) 116 { 117 return ((strncmp(val_str, "TRUE", strlen("TRUE")) == 0) || 118 (strncmp(val_str, "true", strlen("true")) == 0)); 119 } 120 121 void read_ibdiag_config(const char *file) 122 { 123 char buf[1024]; 124 FILE *config_fd = NULL; 125 char *p_prefix, *p_last; 126 char *name; 127 char *val_str; 128 struct stat statbuf; 129 130 /* silently ignore missing config file */ 131 if (stat(file, &statbuf)) 132 return; 133 134 config_fd = fopen(file, "r"); 135 if (!config_fd) 136 return; 137 138 while (fgets(buf, sizeof buf, config_fd) != NULL) { 139 p_prefix = strtok_r(buf, "\n", &p_last); 140 if (!p_prefix) 141 continue; /* ignore blank lines */ 142 143 if (*p_prefix == '#') 144 continue; /* ignore comment lines */ 145 146 name = strtok_r(p_prefix, "=", &p_last); 147 val_str = strtok_r(NULL, "\n", &p_last); 148 149 if (strncmp(name, "CA", strlen("CA")) == 0) { 150 free(ibd_ca); 151 ibd_ca = strdup(val_str); 152 } else if (strncmp(name, "Port", strlen("Port")) == 0) { 153 ibd_ca_port = strtoul(val_str, NULL, 0); 154 } else if (strncmp(name, "timeout", strlen("timeout")) == 0) { 155 ibd_timeout = strtoul(val_str, NULL, 0); 156 } else if (strncmp(name, "MLX_EPI", strlen("MLX_EPI")) == 0) { 157 if (val_str_true(val_str)) { 158 ibd_ibnetdisc_flags |= IBND_CONFIG_MLX_EPI; 159 } else { 160 ibd_ibnetdisc_flags &= ~IBND_CONFIG_MLX_EPI; 161 } 162 } else if (strncmp(name, "m_key", strlen("m_key")) == 0) { 163 ibd_mkey = strtoull(val_str, 0, 0); 164 } else if (strncmp(name, "sa_key", 165 strlen("sa_key")) == 0) { 166 ibd_sakey = strtoull(val_str, 0, 0); 167 } else if (strncmp(name, "nd_format", 168 strlen("nd_format")) == 0) { 169 ibd_nd_format = strdup(val_str); 170 } 171 } 172 173 fclose(config_fd); 174 } 175 176 177 void ibdiag_show_usage() 178 { 179 struct option *o = long_opts; 180 int n; 181 182 fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name, 183 prog_args ? prog_args : ""); 184 185 if (long_opts[0].name) 186 fprintf(stderr, "Options:\n"); 187 for (o = long_opts; o->name; o++) { 188 const struct ibdiag_opt *io = opts_map[o->val]; 189 n = fprintf(stderr, " --%s", io->name); 190 if (isprint(io->letter)) 191 n += fprintf(stderr, ", -%c", io->letter); 192 if (io->has_arg) 193 n += fprintf(stderr, " %s", 194 io->arg_tmpl ? io->arg_tmpl : "<val>"); 195 if (io->description && *io->description) { 196 n += fprintf(stderr, "%*s ", 24 - n > 0 ? 24 - n : 0, 197 ""); 198 pretty_print(n, 74, io->description); 199 } 200 fprintf(stderr, "\n"); 201 } 202 203 if (prog_examples) { 204 const char **p; 205 fprintf(stderr, "\nExamples:\n"); 206 for (p = prog_examples; *p && **p; p++) 207 fprintf(stderr, " %s %s\n", prog_name, *p); 208 } 209 210 fprintf(stderr, "\n"); 211 212 exit(2); 213 } 214 215 static int process_opt(int ch, char *optarg) 216 { 217 char *endp; 218 long val; 219 220 switch (ch) { 221 case 'z': 222 read_ibdiag_config(optarg); 223 break; 224 case 'h': 225 ibdiag_show_usage(); 226 break; 227 case 'V': 228 fprintf(stderr, "%s %s\n", prog_name, get_build_version()); 229 exit(0); 230 case 'e': 231 madrpc_show_errors(1); 232 break; 233 case 'v': 234 ibverbose++; 235 break; 236 case 'd': 237 ibdebug++; 238 madrpc_show_errors(1); 239 umad_debug(ibdebug - 1); 240 break; 241 case 'C': 242 ibd_ca = optarg; 243 break; 244 case 'P': 245 ibd_ca_port = strtoul(optarg, 0, 0); 246 if (ibd_ca_port < 0) 247 IBEXIT("cannot resolve CA port %d", ibd_ca_port); 248 break; 249 case 'D': 250 ibd_dest_type = IB_DEST_DRPATH; 251 break; 252 case 'L': 253 ibd_dest_type = IB_DEST_LID; 254 break; 255 case 'G': 256 ibd_dest_type = IB_DEST_GUID; 257 break; 258 case 't': 259 errno = 0; 260 val = strtol(optarg, &endp, 0); 261 if (errno || (endp && *endp != '\0') || val <= 0 || 262 val > INT_MAX) 263 IBEXIT("Invalid timeout \"%s\". Timeout requires a " 264 "positive integer value < %d.", optarg, INT_MAX); 265 else { 266 madrpc_set_timeout((int)val); 267 ibd_timeout = (int)val; 268 } 269 break; 270 case 's': 271 /* srcport is not required when resolving via IB_DEST_LID */ 272 if (resolve_portid_str(ibd_ca, ibd_ca_port, &sm_portid, optarg, 273 IB_DEST_LID, 0, NULL) < 0) 274 IBEXIT("cannot resolve SM destination port %s", 275 optarg); 276 ibd_sm_id = &sm_portid; 277 break; 278 case 'K': 279 show_keys = 1; 280 break; 281 case 'y': 282 errno = 0; 283 ibd_mkey = strtoull(optarg, &endp, 0); 284 if (errno || *endp != '\0') { 285 errno = 0; 286 ibd_mkey = strtoull(getpass("M_Key: "), &endp, 0); 287 if (errno || *endp != '\0') { 288 IBEXIT("Bad M_Key"); 289 } 290 } 291 break; 292 default: 293 return -1; 294 } 295 296 return 0; 297 } 298 299 static const struct ibdiag_opt common_opts[] = { 300 {"config", 'z', 1, "<config>", "use config file, default: " IBDIAG_CONFIG_GENERAL}, 301 {"Ca", 'C', 1, "<ca>", "Ca name to use"}, 302 {"Port", 'P', 1, "<port>", "Ca port number to use"}, 303 {"Direct", 'D', 0, NULL, "use Direct address argument"}, 304 {"Lid", 'L', 0, NULL, "use LID address argument"}, 305 {"Guid", 'G', 0, NULL, "use GUID address argument"}, 306 {"timeout", 't', 1, "<ms>", "timeout in ms"}, 307 {"sm_port", 's', 1, "<lid>", "SM port lid"}, 308 {"show_keys", 'K', 0, NULL, "display security keys in output"}, 309 {"m_key", 'y', 1, "<key>", "M_Key to use in request"}, 310 {"errors", 'e', 0, NULL, "show send and receive errors"}, 311 {"verbose", 'v', 0, NULL, "increase verbosity level"}, 312 {"debug", 'd', 0, NULL, "raise debug level"}, 313 {"help", 'h', 0, NULL, "help message"}, 314 {"version", 'V', 0, NULL, "show version"}, 315 {0} 316 }; 317 318 static void make_opt(struct option *l, const struct ibdiag_opt *o, 319 const struct ibdiag_opt *map[]) 320 { 321 l->name = o->name; 322 l->has_arg = o->has_arg; 323 l->flag = NULL; 324 l->val = o->letter; 325 if (!map[l->val]) 326 map[l->val] = o; 327 } 328 329 static struct option *make_long_opts(const char *exclude_str, 330 const struct ibdiag_opt *custom_opts, 331 const struct ibdiag_opt *map[]) 332 { 333 struct option *long_opts, *l; 334 const struct ibdiag_opt *o; 335 unsigned n = 0; 336 337 if (custom_opts) 338 for (o = custom_opts; o->name; o++) 339 n++; 340 341 long_opts = malloc((sizeof(common_opts) / sizeof(common_opts[0]) + n) * 342 sizeof(*long_opts)); 343 if (!long_opts) 344 return NULL; 345 346 l = long_opts; 347 348 if (custom_opts) 349 for (o = custom_opts; o->name; o++) 350 make_opt(l++, o, map); 351 352 for (o = common_opts; o->name; o++) { 353 if (exclude_str && strchr(exclude_str, o->letter)) 354 continue; 355 make_opt(l++, o, map); 356 } 357 358 memset(l, 0, sizeof(*l)); 359 360 return long_opts; 361 } 362 363 static void make_str_opts(const struct option *o, char *p, unsigned size) 364 { 365 unsigned i, n = 0; 366 367 for (n = 0; o->name && n + 2 + o->has_arg < size; o++) { 368 p[n++] = (char)o->val; 369 for (i = 0; i < (unsigned)o->has_arg; i++) 370 p[n++] = ':'; 371 } 372 p[n] = '\0'; 373 } 374 375 int ibdiag_process_opts(int argc, char *const argv[], void *cxt, 376 const char *exclude_common_str, 377 const struct ibdiag_opt custom_opts[], 378 int (*custom_handler) (void *cxt, int val, 379 char *optarg), 380 const char *usage_args, const char *usage_examples[]) 381 { 382 char str_opts[1024]; 383 const struct ibdiag_opt *o; 384 385 prog_name = argv[0]; 386 prog_args = usage_args; 387 prog_examples = usage_examples; 388 389 if (long_opts) 390 free(long_opts); 391 392 long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map); 393 if (!long_opts) 394 return -1; 395 396 read_ibdiag_config(IBDIAG_CONFIG_GENERAL); 397 398 make_str_opts(long_opts, str_opts, sizeof(str_opts)); 399 400 while (1) { 401 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 402 if (ch == -1) 403 break; 404 o = opts_map[ch]; 405 if (!o) 406 ibdiag_show_usage(); 407 if (custom_handler) { 408 if (custom_handler(cxt, ch, optarg) && 409 process_opt(ch, optarg)) 410 ibdiag_show_usage(); 411 } else if (process_opt(ch, optarg)) 412 ibdiag_show_usage(); 413 } 414 415 return 0; 416 } 417 418 void ibexit(const char *fn, char *msg, ...) 419 { 420 char buf[512]; 421 va_list va; 422 int n; 423 424 va_start(va, msg); 425 n = vsprintf(buf, msg, va); 426 va_end(va); 427 buf[n] = 0; 428 429 if (ibdebug) 430 printf("%s: iberror: [pid %d] %s: failed: %s\n", 431 prog_name ? prog_name : "", getpid(), fn, buf); 432 else 433 printf("%s: iberror: failed: %s\n", 434 prog_name ? prog_name : "", buf); 435 436 exit(-1); 437 } 438 439 char * 440 conv_cnt_human_readable(uint64_t val64, float *val, int data) 441 { 442 uint64_t tmp = val64; 443 int ui = 0; 444 int div = 1; 445 446 tmp /= 1024; 447 while (tmp) { 448 ui++; 449 tmp /= 1024; 450 div *= 1024; 451 } 452 453 *val = (float)(val64); 454 if (data) { 455 *val *= 4; 456 if (*val/div > 1024) { 457 ui++; 458 div *= 1024; 459 } 460 } 461 *val /= div; 462 463 if (data) { 464 switch (ui) { 465 case 0: 466 return ("B"); 467 case 1: 468 return ("KB"); 469 case 2: 470 return ("MB"); 471 case 3: 472 return ("GB"); 473 case 4: 474 return ("TB"); 475 case 5: 476 return ("PB"); 477 case 6: 478 return ("EB"); 479 default: 480 return (""); 481 } 482 } else { 483 switch (ui) { 484 case 0: 485 return (""); 486 case 1: 487 return ("K"); 488 case 2: 489 return ("M"); 490 case 3: 491 return ("G"); 492 case 4: 493 return ("T"); 494 case 5: 495 return ("P"); 496 case 6: 497 return ("E"); 498 default: 499 return (""); 500 } 501 } 502 return (""); 503 } 504 505 int is_port_info_extended_supported(ib_portid_t * dest, int port, 506 struct ibmad_port *srcport) 507 { 508 uint8_t data[IB_SMP_DATA_SIZE] = { 0 }; 509 uint32_t cap_mask; 510 uint16_t cap_mask2; 511 512 if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, port, 0, srcport)) 513 IBEXIT("port info query failed"); 514 515 mad_decode_field(data, IB_PORT_CAPMASK_F, &cap_mask); 516 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_CAP_MASK2)) { 517 mad_decode_field(data, IB_PORT_CAPMASK2_F, &cap_mask2); 518 if (!(cap_mask2 & 519 CL_NTOH16(IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED))) { 520 IBWARN("port info capability mask2 = 0x%x doesn't" 521 " indicate PortInfoExtended support", cap_mask2); 522 return 0; 523 } 524 } else { 525 IBWARN("port info capability mask2 not supported"); 526 return 0; 527 } 528 529 return 1; 530 } 531 532 int is_mlnx_ext_port_info_supported(uint32_t vendorid, 533 uint16_t devid) 534 { 535 if (ibd_ibnetdisc_flags & IBND_CONFIG_MLX_EPI) { 536 537 if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 || 538 ((vendorid == 0x119f) && 539 /* Bull SwitchX */ 540 (devid == 0x1b02 || devid == 0x1b50 || 541 /* Bull SwitchIB and SwitchIB2 */ 542 devid == 0x1ba0 || 543 (devid >= 0x1bd0 && devid <= 0x1bd5)))) 544 return 1; 545 if ((devid >= 0x1003 && devid <= 0x1017) || 546 ((vendorid == 0x119f) && 547 /* Bull ConnectX3 */ 548 (devid == 0x1b33 || devid == 0x1b73 || 549 devid == 0x1b40 || devid == 0x1b41 || 550 devid == 0x1b60 || devid == 0x1b61 || 551 /* Bull ConnectIB */ 552 devid == 0x1b83 || 553 devid == 0x1b93 || devid == 0x1b94 || 554 /* Bull ConnectX4 */ 555 devid == 0x1bb4 || devid == 0x1bb5 || 556 devid == 0x1bc4))) 557 return 1; 558 } 559 560 return 0; 561 } 562 563 /** ========================================================================= 564 * Resolve the SM portid using the umad layer rather than using 565 * ib_resolve_smlid_via which requires a PortInfo query on the local port. 566 */ 567 int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id) 568 { 569 umad_port_t port; 570 int rc; 571 572 if (!sm_id) 573 return (-1); 574 575 if ((rc = umad_get_port(ca_name, portnum, &port)) < 0) 576 return rc; 577 578 memset(sm_id, 0, sizeof(*sm_id)); 579 sm_id->lid = port.sm_lid; 580 sm_id->sl = port.sm_sl; 581 582 umad_release_port(&port); 583 584 return 0; 585 } 586 587 /** ========================================================================= 588 * Resolve local CA characteristics using the umad layer rather than using 589 * ib_resolve_self_via which requires SMP queries on the local port. 590 */ 591 int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid, 592 int *portnum, ibmad_gid_t *gid) 593 { 594 umad_port_t port; 595 uint64_t prefix, guid; 596 int rc; 597 598 if (!(portid || portnum || gid)) 599 return (-1); 600 601 if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0) 602 return rc; 603 604 if (portid) { 605 memset(portid, 0, sizeof(*portid)); 606 portid->lid = port.base_lid; 607 portid->sl = port.sm_sl; 608 } 609 if (portnum) 610 *portnum = port.portnum; 611 if (gid) { 612 memset(gid, 0, sizeof(*gid)); 613 prefix = cl_ntoh64(port.gid_prefix); 614 guid = cl_ntoh64(port.port_guid); 615 mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix); 616 mad_encode_field(*gid, IB_GID_GUID_F, &guid); 617 } 618 619 umad_release_port(&port); 620 621 return 0; 622 } 623 624 int resolve_gid(char *ca_name, uint8_t ca_port, ib_portid_t * portid, 625 ibmad_gid_t gid, ib_portid_t * sm_id, 626 const struct ibmad_port *srcport) 627 { 628 ib_portid_t sm_portid; 629 char buf[IB_SA_DATA_SIZE] = { 0 }; 630 631 if (!sm_id) { 632 sm_id = &sm_portid; 633 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0) 634 return -1; 635 } 636 637 if ((portid->lid = 638 ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0) 639 return -1; 640 641 return 0; 642 } 643 644 int resolve_guid(char *ca_name, uint8_t ca_port, ib_portid_t *portid, 645 uint64_t *guid, ib_portid_t *sm_id, 646 const struct ibmad_port *srcport) 647 { 648 ib_portid_t sm_portid; 649 uint8_t buf[IB_SA_DATA_SIZE] = { 0 }; 650 uint64_t prefix; 651 ibmad_gid_t selfgid; 652 653 if (!sm_id) { 654 sm_id = &sm_portid; 655 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0) 656 return -1; 657 } 658 659 if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0) 660 return -1; 661 662 memcpy(&prefix, portid->gid, sizeof(prefix)); 663 if (!prefix) 664 mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F, 665 IB_DEFAULT_SUBN_PREFIX); 666 if (guid) 667 mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid); 668 669 if ((portid->lid = 670 ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0) 671 return -1; 672 673 mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl); 674 return 0; 675 } 676 677 /* 678 * Callers of this function should ensure their ibmad_port has been opened with 679 * IB_SA_CLASS as this function may require the SA to resolve addresses. 680 */ 681 int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid, 682 char *addr_str, enum MAD_DEST dest_type, 683 ib_portid_t *sm_id, const struct ibmad_port *srcport) 684 { 685 ibmad_gid_t gid; 686 uint64_t guid; 687 int lid; 688 char *routepath; 689 ib_portid_t selfportid = { 0 }; 690 int selfport = 0; 691 692 memset(portid, 0, sizeof *portid); 693 694 switch (dest_type) { 695 case IB_DEST_LID: 696 lid = strtol(addr_str, 0, 0); 697 if (!IB_LID_VALID(lid)) 698 return -1; 699 return ib_portid_set(portid, lid, 0, 0); 700 701 case IB_DEST_DRPATH: 702 if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0) 703 return -1; 704 return 0; 705 706 case IB_DEST_GUID: 707 if (!(guid = strtoull(addr_str, 0, 0))) 708 return -1; 709 710 /* keep guid in portid? */ 711 return resolve_guid(ca_name, ca_port, portid, &guid, sm_id, 712 srcport); 713 714 case IB_DEST_DRSLID: 715 lid = strtol(addr_str, &routepath, 0); 716 routepath++; 717 if (!IB_LID_VALID(lid)) 718 return -1; 719 ib_portid_set(portid, lid, 0, 0); 720 721 /* handle DR parsing and set DrSLID to local lid */ 722 if (resolve_self(ca_name, ca_port, &selfportid, &selfport, 723 NULL) < 0) 724 return -1; 725 if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) < 726 0) 727 return -1; 728 return 0; 729 730 case IB_DEST_GID: 731 if (inet_pton(AF_INET6, addr_str, &gid) <= 0) 732 return -1; 733 return resolve_gid(ca_name, ca_port, portid, gid, sm_id, 734 srcport); 735 default: 736 IBWARN("bad dest_type %d", dest_type); 737 } 738 739 return -1; 740 } 741 742 static unsigned int get_max_width(unsigned int num) 743 { 744 unsigned r = 0; /* 1x */ 745 746 if (num & 8) 747 r = 3; /* 12x */ 748 else { 749 if (num & 4) 750 r = 2; /* 8x */ 751 else if (num & 2) 752 r = 1; /* 4x */ 753 else if (num & 0x10) 754 r = 4; /* 2x */ 755 } 756 757 return (1 << r); 758 } 759 760 static unsigned int get_max(unsigned int num) 761 { 762 unsigned r = 0; // r will be lg(num) 763 764 while (num >>= 1) // unroll for more speed... 765 r++; 766 767 return (1 << r); 768 } 769 770 void get_max_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port) 771 { 772 char buf[64]; 773 uint32_t max_speed = 0; 774 uint32_t cap_mask, rem_cap_mask, fdr10; 775 uint8_t *info = NULL; 776 777 uint32_t max_width = get_max_width(mad_get_field(port->info, 0, 778 IB_PORT_LINK_WIDTH_SUPPORTED_F) 779 & mad_get_field(port->remoteport->info, 0, 780 IB_PORT_LINK_WIDTH_SUPPORTED_F)); 781 if ((max_width & mad_get_field(port->info, 0, 782 IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0) 783 // we are not at the max supported width 784 // print what we could be at. 785 snprintf(width_msg, msg_size, "Could be %s", 786 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, 787 buf, 64, &max_width)); 788 789 if (port->node->type == IB_NODE_SWITCH) { 790 if (port->node->ports[0]) 791 info = (uint8_t *)&port->node->ports[0]->info; 792 } 793 else 794 info = (uint8_t *)&port->info; 795 796 if (info) 797 cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F); 798 else 799 cap_mask = 0; 800 801 info = NULL; 802 if (port->remoteport->node->type == IB_NODE_SWITCH) { 803 if (port->remoteport->node->ports[0]) 804 info = (uint8_t *)&port->remoteport->node->ports[0]->info; 805 } else 806 info = (uint8_t *)&port->remoteport->info; 807 808 if (info) 809 rem_cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F); 810 else 811 rem_cap_mask = 0; 812 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS) && 813 rem_cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS)) 814 goto check_ext_speed; 815 check_fdr10_supp: 816 fdr10 = (mad_get_field(port->ext_info, 0, 817 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10) 818 && (mad_get_field(port->remoteport->ext_info, 0, 819 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10); 820 if (fdr10) 821 goto check_fdr10_active; 822 823 max_speed = get_max(mad_get_field(port->info, 0, 824 IB_PORT_LINK_SPEED_SUPPORTED_F) 825 & mad_get_field(port->remoteport->info, 0, 826 IB_PORT_LINK_SPEED_SUPPORTED_F)); 827 if ((max_speed & mad_get_field(port->info, 0, 828 IB_PORT_LINK_SPEED_ACTIVE_F)) == 0) 829 // we are not at the max supported speed 830 // print what we could be at. 831 snprintf(speed_msg, msg_size, "Could be %s", 832 mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, 833 buf, 64, &max_speed)); 834 return; 835 836 check_ext_speed: 837 if (mad_get_field(port->info, 0, 838 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0 || 839 mad_get_field(port->remoteport->info, 0, 840 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0) 841 goto check_fdr10_supp; 842 max_speed = get_max(mad_get_field(port->info, 0, 843 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) 844 & mad_get_field(port->remoteport->info, 0, 845 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F)); 846 if ((max_speed & mad_get_field(port->info, 0, 847 IB_PORT_LINK_SPEED_EXT_ACTIVE_F)) == 0) 848 // we are not at the max supported extended speed 849 // print what we could be at. 850 snprintf(speed_msg, msg_size, "Could be %s", 851 mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, 852 buf, 64, &max_speed)); 853 return; 854 855 check_fdr10_active: 856 if ((mad_get_field(port->ext_info, 0, 857 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10) == 0) { 858 /* Special case QDR to try to avoid confusion with FDR10 */ 859 if (mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F) == 4) /* QDR (10.0 Gbps) */ 860 snprintf(speed_msg, msg_size, 861 "Could be FDR10 (Found link at QDR but expected speed is FDR10)"); 862 else 863 snprintf(speed_msg, msg_size, "Could be FDR10"); 864 } 865 } 866 867 int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing, 868 const char *format, va_list va_args) 869 { 870 int len, i, ret; 871 872 len = strlen(mad_field_name(f)); 873 if (len + 2 > n || spacing + 1 > n) 874 return 0; 875 876 strncpy(buf, mad_field_name(f), n); 877 buf[len] = ':'; 878 for (i = len+1; i < spacing+1; i++) { 879 buf[i] = '.'; 880 } 881 882 ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args); 883 if (ret >= n - spacing) 884 buf[n] = '\0'; 885 886 return ret + spacing; 887 } 888 889 int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing, 890 const char *format, ...) 891 { 892 va_list val; 893 int ret; 894 895 va_start(val, format); 896 ret = vsnprint_field(buf, n, f, spacing, format, val); 897 va_end(val); 898 899 return ret; 900 } 901 902 void dump_portinfo(void *pi, int tabs) 903 { 904 int field, i; 905 char val[64]; 906 char buf[1024]; 907 908 for (field = IB_PORT_FIRST_F; field < IB_PORT_LAST_F; field++) { 909 for (i=0;i<tabs;i++) 910 printf("\t"); 911 if (field == IB_PORT_MKEY_F && show_keys == 0) { 912 snprint_field(buf, 1024, field, 32, NOT_DISPLAYED_STR); 913 } else { 914 mad_decode_field(pi, field, val); 915 if (!mad_dump_field(field, buf, 1024, val)) 916 return; 917 } 918 printf("%s\n", buf); 919 } 920 921 for (field = IB_PORT_CAPMASK2_F; 922 field < IB_PORT_LINK_SPEED_EXT_LAST_F; field++) { 923 for (i=0;i<tabs;i++) 924 printf("\t"); 925 mad_decode_field(pi, field, val); 926 if (!mad_dump_field(field, buf, 1024, val)) 927 return; 928 printf("%s\n", buf); 929 } 930 } 931 932 op_fn_t *match_op(const match_rec_t match_tbl[], char *name) 933 { 934 const match_rec_t *r; 935 for (r = match_tbl; r->name; r++) 936 if (!strcasecmp(r->name, name) || 937 (r->alias && !strcasecmp(r->alias, name))) 938 return r->fn; 939 return NULL; 940 } 941