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 FILE *config_fd = NULL; 124 char *p_prefix, *p_last; 125 char *name; 126 char *val_str; 127 struct stat statbuf; 128 129 /* silently ignore missing config file */ 130 if (stat(file, &statbuf)) 131 return; 132 133 config_fd = fopen(file, "r"); 134 if (!config_fd) 135 return; 136 137 while (fgets(buf, sizeof buf, config_fd) != NULL) { 138 p_prefix = strtok_r(buf, "\n", &p_last); 139 if (!p_prefix) 140 continue; /* ignore blank lines */ 141 142 if (*p_prefix == '#') 143 continue; /* ignore comment lines */ 144 145 name = strtok_r(p_prefix, "=", &p_last); 146 val_str = strtok_r(NULL, "\n", &p_last); 147 148 if (strncmp(name, "CA", strlen("CA")) == 0) { 149 free(ibd_ca); 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; 158 } else { 159 ibd_ibnetdisc_flags &= ~IBND_CONFIG_MLX_EPI; 160 } 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); 169 } 170 } 171 172 fclose(config_fd); 173 } 174 175 176 void ibdiag_show_usage() 177 { 178 struct option *o = long_opts; 179 int n; 180 181 fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name, 182 prog_args ? prog_args : ""); 183 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); 191 if (io->has_arg) 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, 196 ""); 197 pretty_print(n, 74, io->description); 198 } 199 fprintf(stderr, "\n"); 200 } 201 202 if (prog_examples) { 203 const char **p; 204 fprintf(stderr, "\nExamples:\n"); 205 for (p = prog_examples; *p && **p; p++) 206 fprintf(stderr, " %s %s\n", prog_name, *p); 207 } 208 209 fprintf(stderr, "\n"); 210 211 exit(2); 212 } 213 214 static int process_opt(int ch, char *optarg) 215 { 216 char *endp; 217 long val; 218 219 switch (ch) { 220 case 'z': 221 read_ibdiag_config(optarg); 222 break; 223 case 'h': 224 ibdiag_show_usage(); 225 break; 226 case 'V': 227 fprintf(stderr, "%s %s\n", prog_name, get_build_version()); 228 exit(0); 229 case 'e': 230 madrpc_show_errors(1); 231 break; 232 case 'v': 233 ibverbose++; 234 break; 235 case 'd': 236 ibdebug++; 237 madrpc_show_errors(1); 238 umad_debug(ibdebug - 1); 239 break; 240 case 'C': 241 ibd_ca = optarg; 242 break; 243 case 'P': 244 ibd_ca_port = strtoul(optarg, 0, 0); 245 if (ibd_ca_port < 0) 246 IBEXIT("cannot resolve CA port %d", ibd_ca_port); 247 break; 248 case 'D': 249 ibd_dest_type = IB_DEST_DRPATH; 250 break; 251 case 'L': 252 ibd_dest_type = IB_DEST_LID; 253 break; 254 case 'G': 255 ibd_dest_type = IB_DEST_GUID; 256 break; 257 case 't': 258 errno = 0; 259 val = strtol(optarg, &endp, 0); 260 if (errno || (endp && *endp != '\0') || val <= 0 || 261 val > INT_MAX) 262 IBEXIT("Invalid timeout \"%s\". Timeout requires a " 263 "positive integer value < %d.", optarg, INT_MAX); 264 else { 265 madrpc_set_timeout((int)val); 266 ibd_timeout = (int)val; 267 } 268 break; 269 case 's': 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", 274 optarg); 275 ibd_sm_id = &sm_portid; 276 break; 277 case 'K': 278 show_keys = 1; 279 break; 280 case 'y': 281 errno = 0; 282 ibd_mkey = strtoull(optarg, &endp, 0); 283 if (errno || *endp != '\0') { 284 errno = 0; 285 ibd_mkey = strtoull(getpass("M_Key: "), &endp, 0); 286 if (errno || *endp != '\0') { 287 IBEXIT("Bad M_Key"); 288 } 289 } 290 break; 291 default: 292 return -1; 293 } 294 295 return 0; 296 } 297 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"}, 314 {0} 315 }; 316 317 static void make_opt(struct option *l, const struct ibdiag_opt *o, 318 const struct ibdiag_opt *map[]) 319 { 320 l->name = o->name; 321 l->has_arg = o->has_arg; 322 l->flag = NULL; 323 l->val = o->letter; 324 if (!map[l->val]) 325 map[l->val] = o; 326 } 327 328 static struct option *make_long_opts(const char *exclude_str, 329 const struct ibdiag_opt *custom_opts, 330 const struct ibdiag_opt *map[]) 331 { 332 struct option *long_opts, *l; 333 const struct ibdiag_opt *o; 334 unsigned n = 0; 335 336 if (custom_opts) 337 for (o = custom_opts; o->name; o++) 338 n++; 339 340 long_opts = malloc((sizeof(common_opts) / sizeof(common_opts[0]) + n) * 341 sizeof(*long_opts)); 342 if (!long_opts) 343 return NULL; 344 345 l = long_opts; 346 347 if (custom_opts) 348 for (o = custom_opts; o->name; o++) 349 make_opt(l++, o, map); 350 351 for (o = common_opts; o->name; o++) { 352 if (exclude_str && strchr(exclude_str, o->letter)) 353 continue; 354 make_opt(l++, o, map); 355 } 356 357 memset(l, 0, sizeof(*l)); 358 359 return long_opts; 360 } 361 362 static void make_str_opts(const struct option *o, char *p, unsigned size) 363 { 364 unsigned i, n = 0; 365 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++) 369 p[n++] = ':'; 370 } 371 p[n] = '\0'; 372 } 373 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, 378 char *optarg), 379 const char *usage_args, const char *usage_examples[]) 380 { 381 char str_opts[1024]; 382 const struct ibdiag_opt *o; 383 384 prog_name = argv[0]; 385 prog_args = usage_args; 386 prog_examples = usage_examples; 387 388 if (long_opts) 389 free(long_opts); 390 391 long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map); 392 if (!long_opts) 393 return -1; 394 395 read_ibdiag_config(IBDIAG_CONFIG_GENERAL); 396 397 make_str_opts(long_opts, str_opts, sizeof(str_opts)); 398 399 while (1) { 400 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 401 if (ch == -1) 402 break; 403 o = opts_map[ch]; 404 if (!o) 405 ibdiag_show_usage(); 406 if (custom_handler) { 407 if (custom_handler(cxt, ch, optarg) && 408 process_opt(ch, optarg)) 409 ibdiag_show_usage(); 410 } else if (process_opt(ch, optarg)) 411 ibdiag_show_usage(); 412 } 413 414 return 0; 415 } 416 417 void ibexit(const char *fn, char *msg, ...) 418 { 419 char buf[512]; 420 va_list va; 421 int n; 422 423 va_start(va, msg); 424 n = vsprintf(buf, msg, va); 425 va_end(va); 426 buf[n] = 0; 427 428 if (ibdebug) 429 printf("%s: iberror: [pid %d] %s: failed: %s\n", 430 prog_name ? prog_name : "", getpid(), fn, buf); 431 else 432 printf("%s: iberror: failed: %s\n", 433 prog_name ? prog_name : "", buf); 434 435 exit(-1); 436 } 437 438 char * 439 conv_cnt_human_readable(uint64_t val64, float *val, int data) 440 { 441 uint64_t tmp = val64; 442 int ui = 0; 443 int div = 1; 444 445 tmp /= 1024; 446 while (tmp) { 447 ui++; 448 tmp /= 1024; 449 div *= 1024; 450 } 451 452 *val = (float)(val64); 453 if (data) { 454 *val *= 4; 455 if (*val/div > 1024) { 456 ui++; 457 div *= 1024; 458 } 459 } 460 *val /= div; 461 462 if (data) { 463 switch (ui) { 464 case 0: 465 return ("B"); 466 case 1: 467 return ("KB"); 468 case 2: 469 return ("MB"); 470 case 3: 471 return ("GB"); 472 case 4: 473 return ("TB"); 474 case 5: 475 return ("PB"); 476 case 6: 477 return ("EB"); 478 default: 479 return (""); 480 } 481 } else { 482 switch (ui) { 483 case 0: 484 return (""); 485 case 1: 486 return ("K"); 487 case 2: 488 return ("M"); 489 case 3: 490 return ("G"); 491 case 4: 492 return ("T"); 493 case 5: 494 return ("P"); 495 case 6: 496 return ("E"); 497 default: 498 return (""); 499 } 500 } 501 return (""); 502 } 503 504 int is_port_info_extended_supported(ib_portid_t * dest, int port, 505 struct ibmad_port *srcport) 506 { 507 uint8_t data[IB_SMP_DATA_SIZE] = { 0 }; 508 uint32_t cap_mask; 509 uint16_t cap_mask2; 510 511 if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, port, 0, srcport)) 512 IBEXIT("port info query failed"); 513 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); 517 if (!(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); 521 return 0; 522 } 523 } else { 524 IBWARN("port info capability mask2 not supported"); 525 return 0; 526 } 527 528 return 1; 529 } 530 531 int is_mlnx_ext_port_info_supported(uint32_t vendorid, 532 uint16_t devid) 533 { 534 if (ibd_ibnetdisc_flags & IBND_CONFIG_MLX_EPI) { 535 536 if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 || 537 ((vendorid == 0x119f) && 538 /* Bull SwitchX */ 539 (devid == 0x1b02 || devid == 0x1b50 || 540 /* Bull SwitchIB and SwitchIB2 */ 541 devid == 0x1ba0 || 542 (devid >= 0x1bd0 && devid <= 0x1bd5)))) 543 return 1; 544 if ((devid >= 0x1003 && devid <= 0x1017) || 545 ((vendorid == 0x119f) && 546 /* Bull ConnectX3 */ 547 (devid == 0x1b33 || devid == 0x1b73 || 548 devid == 0x1b40 || devid == 0x1b41 || 549 devid == 0x1b60 || devid == 0x1b61 || 550 /* Bull ConnectIB */ 551 devid == 0x1b83 || 552 devid == 0x1b93 || devid == 0x1b94 || 553 /* Bull ConnectX4 */ 554 devid == 0x1bb4 || devid == 0x1bb5 || 555 devid == 0x1bc4))) 556 return 1; 557 } 558 559 return 0; 560 } 561 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. 565 */ 566 int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id) 567 { 568 umad_port_t port; 569 int rc; 570 571 if (!sm_id) 572 return (-1); 573 574 if ((rc = umad_get_port(ca_name, portnum, &port)) < 0) 575 return rc; 576 577 memset(sm_id, 0, sizeof(*sm_id)); 578 sm_id->lid = port.sm_lid; 579 sm_id->sl = port.sm_sl; 580 581 umad_release_port(&port); 582 583 return 0; 584 } 585 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. 589 */ 590 int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid, 591 int *portnum, ibmad_gid_t *gid) 592 { 593 umad_port_t port; 594 uint64_t prefix, guid; 595 int rc; 596 597 if (!(portid || portnum || gid)) 598 return (-1); 599 600 if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0) 601 return rc; 602 603 if (portid) { 604 memset(portid, 0, sizeof(*portid)); 605 portid->lid = port.base_lid; 606 portid->sl = port.sm_sl; 607 } 608 if (portnum) 609 *portnum = port.portnum; 610 if (gid) { 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); 616 } 617 618 umad_release_port(&port); 619 620 return 0; 621 } 622 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) 626 { 627 ib_portid_t sm_portid; 628 char buf[IB_SA_DATA_SIZE] = { 0 }; 629 630 if (!sm_id) { 631 sm_id = &sm_portid; 632 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0) 633 return -1; 634 } 635 636 if ((portid->lid = 637 ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0) 638 return -1; 639 640 return 0; 641 } 642 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) 646 { 647 ib_portid_t sm_portid; 648 uint8_t buf[IB_SA_DATA_SIZE] = { 0 }; 649 uint64_t prefix; 650 ibmad_gid_t selfgid; 651 652 if (!sm_id) { 653 sm_id = &sm_portid; 654 if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0) 655 return -1; 656 } 657 658 if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0) 659 return -1; 660 661 memcpy(&prefix, portid->gid, sizeof(prefix)); 662 if (!prefix) 663 mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F, 664 IB_DEFAULT_SUBN_PREFIX); 665 if (guid) 666 mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid); 667 668 if ((portid->lid = 669 ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0) 670 return -1; 671 672 mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl); 673 return 0; 674 } 675 676 /* 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. 679 */ 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) 683 { 684 ibmad_gid_t gid; 685 uint64_t guid; 686 int lid; 687 char *routepath; 688 ib_portid_t selfportid = { 0 }; 689 int selfport = 0; 690 691 memset(portid, 0, sizeof *portid); 692 693 switch (dest_type) { 694 case IB_DEST_LID: 695 lid = strtol(addr_str, 0, 0); 696 if (!IB_LID_VALID(lid)) 697 return -1; 698 return ib_portid_set(portid, lid, 0, 0); 699 700 case IB_DEST_DRPATH: 701 if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0) 702 return -1; 703 return 0; 704 705 case IB_DEST_GUID: 706 if (!(guid = strtoull(addr_str, 0, 0))) 707 return -1; 708 709 /* keep guid in portid? */ 710 return resolve_guid(ca_name, ca_port, portid, &guid, sm_id, 711 srcport); 712 713 case IB_DEST_DRSLID: 714 lid = strtol(addr_str, &routepath, 0); 715 routepath++; 716 if (!IB_LID_VALID(lid)) 717 return -1; 718 ib_portid_set(portid, lid, 0, 0); 719 720 /* handle DR parsing and set DrSLID to local lid */ 721 if (resolve_self(ca_name, ca_port, &selfportid, &selfport, 722 NULL) < 0) 723 return -1; 724 if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) < 725 0) 726 return -1; 727 return 0; 728 729 case IB_DEST_GID: 730 if (inet_pton(AF_INET6, addr_str, &gid) <= 0) 731 return -1; 732 return resolve_gid(ca_name, ca_port, portid, gid, sm_id, 733 srcport); 734 default: 735 IBWARN("bad dest_type %d", dest_type); 736 } 737 738 return -1; 739 } 740 741 static unsigned int get_max_width(unsigned int num) 742 { 743 unsigned r = 0; /* 1x */ 744 745 if (num & 8) 746 r = 3; /* 12x */ 747 else { 748 if (num & 4) 749 r = 2; /* 8x */ 750 else if (num & 2) 751 r = 1; /* 4x */ 752 else if (num & 0x10) 753 r = 4; /* 2x */ 754 } 755 756 return (1 << r); 757 } 758 759 static unsigned int get_max(unsigned int num) 760 { 761 unsigned r = 0; // r will be lg(num) 762 763 while (num >>= 1) // unroll for more speed... 764 r++; 765 766 return (1 << r); 767 } 768 769 void get_max_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port) 770 { 771 char buf[64]; 772 uint32_t max_speed = 0; 773 uint32_t cap_mask, rem_cap_mask, fdr10; 774 uint8_t *info = NULL; 775 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)); 787 788 if (port->node->type == IB_NODE_SWITCH) { 789 if (port->node->ports[0]) 790 info = (uint8_t *)&port->node->ports[0]->info; 791 } 792 else 793 info = (uint8_t *)&port->info; 794 795 if (info) 796 cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F); 797 else 798 cap_mask = 0; 799 800 info = NULL; 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; 804 } else 805 info = (uint8_t *)&port->remoteport->info; 806 807 if (info) 808 rem_cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F); 809 else 810 rem_cap_mask = 0; 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; 814 check_fdr10_supp: 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); 819 if (fdr10) 820 goto check_fdr10_active; 821 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)); 833 return; 834 835 check_ext_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)); 852 return; 853 854 check_fdr10_active: 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)"); 861 else 862 snprintf(speed_msg, msg_size, "Could be FDR10"); 863 } 864 } 865 866 int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing, 867 const char *format, va_list va_args) 868 { 869 int len, i, ret; 870 871 len = strlen(mad_field_name(f)); 872 if (len + 2 > n || spacing + 1 > n) 873 return 0; 874 875 strncpy(buf, mad_field_name(f), n); 876 buf[len] = ':'; 877 for (i = len+1; i < spacing+1; i++) { 878 buf[i] = '.'; 879 } 880 881 ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args); 882 if (ret >= n - spacing) 883 buf[n] = '\0'; 884 885 return ret + spacing; 886 } 887 888 int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing, 889 const char *format, ...) 890 { 891 va_list val; 892 int ret; 893 894 va_start(val, format); 895 ret = vsnprint_field(buf, n, f, spacing, format, val); 896 va_end(val); 897 898 return ret; 899 } 900 901 void dump_portinfo(void *pi, int tabs) 902 { 903 int field, i; 904 char val[64]; 905 char buf[1024]; 906 907 for (field = IB_PORT_FIRST_F; field < IB_PORT_LAST_F; field++) { 908 for (i=0;i<tabs;i++) 909 printf("\t"); 910 if (field == IB_PORT_MKEY_F && show_keys == 0) { 911 snprint_field(buf, 1024, field, 32, NOT_DISPLAYED_STR); 912 } else { 913 mad_decode_field(pi, field, val); 914 if (!mad_dump_field(field, buf, 1024, val)) 915 return; 916 } 917 printf("%s\n", buf); 918 } 919 920 for (field = IB_PORT_CAPMASK2_F; 921 field < IB_PORT_LINK_SPEED_EXT_LAST_F; field++) { 922 for (i=0;i<tabs;i++) 923 printf("\t"); 924 mad_decode_field(pi, field, val); 925 if (!mad_dump_field(field, buf, 1024, val)) 926 return; 927 printf("%s\n", buf); 928 } 929 } 930 931 op_fn_t *match_op(const match_rec_t match_tbl[], char *name) 932 { 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))) 937 return r->fn; 938 return NULL; 939 } 940