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