1 /* 2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved. 4 * Copyright (c) 2008 Lawrence Livermore National Lab. All rights reserved. 5 * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved. 6 * 7 * This software is available to you under a choice of one of two 8 * licenses. You may choose to be licensed under the terms of the GNU 9 * General Public License (GPL) Version 2, available from the file 10 * COPYING in the main directory of this source tree, or the 11 * OpenIB.org BSD license below: 12 * 13 * Redistribution and use in source and binary forms, with or 14 * without modification, are permitted provided that the following 15 * conditions are met: 16 * 17 * - Redistributions of source code must retain the above 18 * copyright notice, this list of conditions and the following 19 * disclaimer. 20 * 21 * - Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimer in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33 * SOFTWARE. 34 * 35 */ 36 37 #if HAVE_CONFIG_H 38 # include <config.h> 39 #endif /* HAVE_CONFIG_H */ 40 41 #define _GNU_SOURCE 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 #include <stdarg.h> 46 #include <time.h> 47 #include <string.h> 48 #include <getopt.h> 49 #include <errno.h> 50 #include <inttypes.h> 51 52 #include <complib/cl_nodenamemap.h> 53 #include <infiniband/ibnetdisc.h> 54 55 #include "ibdiag_common.h" 56 57 #define DIFF_FLAG_PORT_CONNECTION 0x01 58 #define DIFF_FLAG_PORT_STATE 0x02 59 #define DIFF_FLAG_LID 0x04 60 #define DIFF_FLAG_NODE_DESCRIPTION 0x08 61 62 #define DIFF_FLAG_DEFAULT (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE) 63 64 static char *node_name_map_file = NULL; 65 static nn_map_t *node_name_map = NULL; 66 static char *load_cache_file = NULL; 67 static char *diff_cache_file = NULL; 68 static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT; 69 static char *filterdownports_cache_file = NULL; 70 static ibnd_fabric_t *filterdownports_fabric = NULL; 71 72 static uint64_t guid = 0; 73 static char *guid_str = NULL; 74 static char *dr_path = NULL; 75 static int all = 0; 76 77 static int down_links_only = 0; 78 static int line_mode = 0; 79 static int add_sw_settings = 0; 80 static int only_flag = 0; 81 static int only_type = 0; 82 83 int filterdownport_check(ibnd_node_t * node, ibnd_port_t * port) 84 { 85 ibnd_node_t *fsw; 86 ibnd_port_t *fport; 87 int fistate; 88 89 fsw = ibnd_find_node_guid(filterdownports_fabric, node->guid); 90 91 if (!fsw) 92 return 0; 93 94 if (port->portnum > fsw->numports) 95 return 0; 96 97 fport = fsw->ports[port->portnum]; 98 99 if (!fport) 100 return 0; 101 102 fistate = mad_get_field(fport->info, 0, IB_PORT_STATE_F); 103 104 return (fistate == IB_LINK_DOWN) ? 1 : 0; 105 } 106 107 void print_port(ibnd_node_t * node, ibnd_port_t * port, char *out_prefix) 108 { 109 char width[64], speed[64], state[64], physstate[64]; 110 char remote_guid_str[256]; 111 char remote_str[256]; 112 char link_str[256]; 113 char width_msg[256]; 114 char speed_msg[256]; 115 char ext_port_str[256]; 116 int iwidth, ispeed, fdr10, espeed, istate, iphystate, cap_mask; 117 int n = 0; 118 uint8_t *info = NULL; 119 120 if (!port) 121 return; 122 123 iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F); 124 ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F); 125 fdr10 = mad_get_field(port->ext_info, 0, 126 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10; 127 128 if (port->node->type == IB_NODE_SWITCH) { 129 if (port->node->ports[0]) 130 info = (uint8_t *)&port->node->ports[0]->info; 131 } 132 else 133 info = (uint8_t *)&port->info; 134 135 if (info) { 136 cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F); 137 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS)) 138 espeed = mad_get_field(port->info, 0, 139 IB_PORT_LINK_SPEED_EXT_ACTIVE_F); 140 else 141 espeed = 0; 142 } else { 143 ispeed = 0; 144 iwidth = 0; 145 espeed = 0; 146 } 147 148 istate = mad_get_field(port->info, 0, IB_PORT_STATE_F); 149 iphystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F); 150 151 remote_guid_str[0] = '\0'; 152 remote_str[0] = '\0'; 153 link_str[0] = '\0'; 154 width_msg[0] = '\0'; 155 speed_msg[0] = '\0'; 156 157 if (istate == IB_LINK_DOWN 158 && filterdownports_fabric 159 && filterdownport_check(node, port)) 160 return; 161 162 /* C14-24.2.1 states that a down port allows for invalid data to be 163 * returned for all PortInfo components except PortState and 164 * PortPhysicalState */ 165 if (istate != IB_LINK_DOWN) { 166 if (!espeed) { 167 if (fdr10) 168 sprintf(speed, "10.0 Gbps (FDR10)"); 169 else 170 mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 171 64, &ispeed); 172 } else 173 mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed, 174 64, &espeed); 175 176 n = snprintf(link_str, 256, "(%3s %18s %6s/%8s)", 177 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, 178 &iwidth), 179 speed, 180 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate), 181 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, 182 &iphystate)); 183 } else { 184 n = snprintf(link_str, 256, "( %6s/%8s)", 185 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate), 186 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, 187 &iphystate)); 188 } 189 190 /* again default values due to C14-24.2.1 */ 191 if (add_sw_settings && istate != IB_LINK_DOWN) { 192 snprintf(link_str + n, 256 - n, 193 " (HOQ:%d VL_Stall:%d)", 194 mad_get_field(port->info, 0, 195 IB_PORT_HOQ_LIFE_F), 196 mad_get_field(port->info, 0, 197 IB_PORT_VL_STALL_COUNT_F)); 198 } 199 200 if (port->remoteport) { 201 char *remap = 202 remap_node_name(node_name_map, port->remoteport->node->guid, 203 port->remoteport->node->nodedesc); 204 205 if (port->remoteport->ext_portnum) 206 snprintf(ext_port_str, 256, "%d", 207 port->remoteport->ext_portnum); 208 else 209 ext_port_str[0] = '\0'; 210 211 get_max_msg(width_msg, speed_msg, 256, port); 212 213 if (line_mode) { 214 snprintf(remote_guid_str, 256, 215 "0x%016" PRIx64 " ", 216 port->remoteport->guid); 217 } 218 219 snprintf(remote_str, 256, "%s%6d %4d[%2s] \"%s\" (%s %s)\n", 220 remote_guid_str, port->remoteport->base_lid ? 221 port->remoteport->base_lid : 222 port->remoteport->node->smalid, 223 port->remoteport->portnum, ext_port_str, remap, 224 width_msg, speed_msg); 225 free(remap); 226 } else { 227 if (istate == IB_LINK_DOWN) 228 snprintf(remote_str, 256, " [ ] \"\" ( )\n"); 229 else 230 snprintf(remote_str, 256, " \"Port not available\"\n"); 231 } 232 233 if (port->ext_portnum) 234 snprintf(ext_port_str, 256, "%d", port->ext_portnum); 235 else 236 ext_port_str[0] = '\0'; 237 238 if (line_mode) { 239 char *remap = remap_node_name(node_name_map, node->guid, 240 node->nodedesc); 241 printf("%s0x%016" PRIx64 " \"%30s\" ", 242 out_prefix ? out_prefix : "", 243 port->guid, remap); 244 free(remap); 245 } else 246 printf("%s ", out_prefix ? out_prefix : ""); 247 248 if (port->node->type != IB_NODE_SWITCH) { 249 if (!line_mode) 250 printf("0x%016" PRIx64 " ", port->guid); 251 252 printf("%6d %4d[%2s] ==%s==> %s", 253 port->base_lid, 254 port->portnum, ext_port_str, link_str, remote_str); 255 } else 256 printf("%6d %4d[%2s] ==%s==> %s", 257 node->smalid, port->portnum, ext_port_str, 258 link_str, remote_str); 259 } 260 261 static inline const char *nodetype_str(ibnd_node_t * node) 262 { 263 switch (node->type) { 264 case IB_NODE_SWITCH: 265 return "Switch"; 266 case IB_NODE_CA: 267 return "CA"; 268 case IB_NODE_ROUTER: 269 return "Router"; 270 } 271 return "??"; 272 } 273 274 void print_node_header(ibnd_node_t *node, int *out_header_flag, 275 char *out_prefix) 276 { 277 uint64_t guid = 0; 278 if ((!out_header_flag || !(*out_header_flag)) && !line_mode) { 279 char *remap = 280 remap_node_name(node_name_map, node->guid, node->nodedesc); 281 if (node->type == IB_NODE_SWITCH) { 282 if (node->ports[0]) 283 guid = node->ports[0]->guid; 284 else /* if (node->info) */ 285 guid = mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F); 286 287 printf("%s%s: 0x%016" PRIx64 " %s:\n", 288 out_prefix ? out_prefix : "", 289 nodetype_str(node), 290 guid, 291 remap); 292 } else 293 printf("%s%s: %s:\n", 294 out_prefix ? out_prefix : "", 295 nodetype_str(node), remap); 296 if (out_header_flag) 297 (*out_header_flag)++; 298 free(remap); 299 } 300 } 301 302 void print_node(ibnd_node_t * node, void *user_data) 303 { 304 int i = 0; 305 int head_print = 0; 306 char *out_prefix = (char *)user_data; 307 308 for (i = 1; i <= node->numports; i++) { 309 ibnd_port_t *port = node->ports[i]; 310 if (!port) 311 continue; 312 if (!down_links_only || 313 mad_get_field(port->info, 0, 314 IB_PORT_STATE_F) == IB_LINK_DOWN) { 315 print_node_header(node, &head_print, out_prefix); 316 print_port(node, port, out_prefix); 317 } 318 } 319 } 320 321 struct iter_diff_data { 322 uint32_t diff_flags; 323 ibnd_fabric_t *fabric1; 324 ibnd_fabric_t *fabric2; 325 char *fabric1_prefix; 326 char *fabric2_prefix; 327 }; 328 329 void diff_node_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node, 330 int *head_print, struct iter_diff_data *data) 331 { 332 int i = 0; 333 334 for (i = 1; i <= fabric1_node->numports; i++) { 335 ibnd_port_t *fabric1_port, *fabric2_port; 336 int output_diff = 0; 337 338 fabric1_port = fabric1_node->ports[i]; 339 fabric2_port = fabric2_node->ports[i]; 340 341 if (!fabric1_port && !fabric2_port) 342 continue; 343 344 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) { 345 if ((fabric1_port && !fabric2_port) 346 || (!fabric1_port && fabric2_port) 347 || (fabric1_port->remoteport 348 && !fabric2_port->remoteport) 349 || (!fabric1_port->remoteport 350 && fabric2_port->remoteport) 351 || (fabric1_port->remoteport 352 && fabric2_port->remoteport 353 && fabric1_port->remoteport->guid != 354 fabric2_port->remoteport->guid)) 355 output_diff++; 356 } 357 358 /* if either fabric1_port or fabric2_port NULL, should be 359 * handled by port connection diff code 360 */ 361 if (data->diff_flags & DIFF_FLAG_PORT_STATE 362 && fabric1_port 363 && fabric2_port) { 364 int state1, state2; 365 366 state1 = mad_get_field(fabric1_port->info, 0, 367 IB_PORT_STATE_F); 368 state2 = mad_get_field(fabric2_port->info, 0, 369 IB_PORT_STATE_F); 370 371 if (state1 != state2) 372 output_diff++; 373 } 374 375 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION 376 && data->diff_flags & DIFF_FLAG_LID 377 && fabric1_port && fabric2_port 378 && fabric1_port->remoteport && fabric2_port->remoteport 379 && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid) 380 output_diff++; 381 382 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION 383 && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION 384 && fabric1_port && fabric2_port 385 && fabric1_port->remoteport && fabric2_port->remoteport 386 && memcmp(fabric1_port->remoteport->node->nodedesc, 387 fabric2_port->remoteport->node->nodedesc, 388 IB_SMP_DATA_SIZE)) 389 output_diff++; 390 391 if (output_diff && fabric1_port) { 392 print_node_header(fabric1_node, 393 head_print, 394 NULL); 395 print_port(fabric1_node, 396 fabric1_port, 397 data->fabric1_prefix); 398 } 399 400 if (output_diff && fabric2_port) { 401 print_node_header(fabric2_node, 402 head_print, 403 NULL); 404 print_port(fabric2_node, 405 fabric2_port, 406 data->fabric2_prefix); 407 } 408 } 409 } 410 411 void diff_node_iter(ibnd_node_t * fabric1_node, void *iter_user_data) 412 { 413 struct iter_diff_data *data = iter_user_data; 414 ibnd_node_t *fabric2_node; 415 int head_print = 0; 416 417 DEBUG("DEBUG: fabric1_node %p\n", fabric1_node); 418 419 fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid); 420 if (!fabric2_node) 421 print_node(fabric1_node, data->fabric1_prefix); 422 else if (data->diff_flags & 423 (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE 424 | DIFF_FLAG_LID | DIFF_FLAG_NODE_DESCRIPTION)) { 425 426 if ((fabric1_node->type == IB_NODE_SWITCH 427 && data->diff_flags & DIFF_FLAG_LID 428 && fabric1_node->smalid != fabric2_node->smalid) || 429 (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION 430 && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc, 431 IB_SMP_DATA_SIZE))) { 432 print_node_header(fabric1_node, 433 NULL, 434 data->fabric1_prefix); 435 print_node_header(fabric2_node, 436 NULL, 437 data->fabric2_prefix); 438 head_print++; 439 } 440 441 if (fabric1_node->numports != fabric2_node->numports) { 442 print_node_header(fabric1_node, 443 &head_print, 444 NULL); 445 printf("%snumports = %d\n", data->fabric1_prefix, 446 fabric1_node->numports); 447 printf("%snumports = %d\n", data->fabric2_prefix, 448 fabric2_node->numports); 449 return; 450 } 451 452 diff_node_ports(fabric1_node, fabric2_node, 453 &head_print, data); 454 } 455 } 456 457 int diff_node(ibnd_node_t * node, ibnd_fabric_t * orig_fabric, 458 ibnd_fabric_t * new_fabric) 459 { 460 struct iter_diff_data iter_diff_data; 461 462 iter_diff_data.diff_flags = diffcheck_flags; 463 iter_diff_data.fabric1 = orig_fabric; 464 iter_diff_data.fabric2 = new_fabric; 465 iter_diff_data.fabric1_prefix = "< "; 466 iter_diff_data.fabric2_prefix = "> "; 467 if (node) 468 diff_node_iter(node, &iter_diff_data); 469 else { 470 if (only_flag) 471 ibnd_iter_nodes_type(orig_fabric, diff_node_iter, 472 only_type, &iter_diff_data); 473 else 474 ibnd_iter_nodes(orig_fabric, diff_node_iter, 475 &iter_diff_data); 476 } 477 478 /* Do opposite diff to find existence of node types 479 * in new_fabric but not in orig_fabric. 480 * 481 * In this diff, we don't need to check port connections, 482 * port state, lids, or node descriptions since it has already 483 * been done (i.e. checks are only done when guid exists on both 484 * orig and new). 485 */ 486 iter_diff_data.diff_flags = diffcheck_flags & ~DIFF_FLAG_PORT_CONNECTION; 487 iter_diff_data.diff_flags &= ~DIFF_FLAG_PORT_STATE; 488 iter_diff_data.diff_flags &= ~DIFF_FLAG_LID; 489 iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION; 490 iter_diff_data.fabric1 = new_fabric; 491 iter_diff_data.fabric2 = orig_fabric; 492 iter_diff_data.fabric1_prefix = "> "; 493 iter_diff_data.fabric2_prefix = "< "; 494 if (node) 495 diff_node_iter(node, &iter_diff_data); 496 else { 497 if (only_flag) 498 ibnd_iter_nodes_type(new_fabric, diff_node_iter, 499 only_type, &iter_diff_data); 500 else 501 ibnd_iter_nodes(new_fabric, diff_node_iter, 502 &iter_diff_data); 503 } 504 505 return 0; 506 } 507 508 static int process_opt(void *context, int ch, char *optarg) 509 { 510 struct ibnd_config *cfg = context; 511 char *p; 512 513 switch (ch) { 514 case 1: 515 node_name_map_file = strdup(optarg); 516 break; 517 case 2: 518 load_cache_file = strdup(optarg); 519 break; 520 case 3: 521 diff_cache_file = strdup(optarg); 522 break; 523 case 4: 524 diffcheck_flags = 0; 525 p = strtok(optarg, ","); 526 while (p) { 527 if (!strcasecmp(p, "port")) 528 diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION; 529 else if (!strcasecmp(p, "state")) 530 diffcheck_flags |= DIFF_FLAG_PORT_STATE; 531 else if (!strcasecmp(p, "lid")) 532 diffcheck_flags |= DIFF_FLAG_LID; 533 else if (!strcasecmp(p, "nodedesc")) 534 diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION; 535 else { 536 fprintf(stderr, "invalid diff check key: %s\n", 537 p); 538 return -1; 539 } 540 p = strtok(NULL, ","); 541 } 542 break; 543 case 5: 544 filterdownports_cache_file = strdup(optarg); 545 break; 546 case 6: 547 only_flag = 1; 548 only_type = IB_NODE_SWITCH; 549 break; 550 case 7: 551 only_flag = 1; 552 only_type = IB_NODE_CA; 553 break; 554 case 'S': 555 case 'G': 556 guid_str = optarg; 557 guid = (uint64_t) strtoull(guid_str, 0, 0); 558 break; 559 case 'D': 560 dr_path = strdup(optarg); 561 break; 562 case 'a': 563 all = 1; 564 break; 565 case 'n': 566 cfg->max_hops = strtoul(optarg, NULL, 0); 567 break; 568 case 'd': 569 down_links_only = 1; 570 break; 571 case 'l': 572 line_mode = 1; 573 break; 574 case 'p': 575 add_sw_settings = 1; 576 break; 577 case 'R': /* nop */ 578 break; 579 case 'o': 580 cfg->max_smps = strtoul(optarg, NULL, 0); 581 break; 582 default: 583 return -1; 584 } 585 586 return 0; 587 } 588 589 int main(int argc, char **argv) 590 { 591 struct ibnd_config config = { 0 }; 592 int rc = 0; 593 int resolved = -1; 594 ibnd_fabric_t *fabric = NULL; 595 ibnd_fabric_t *diff_fabric = NULL; 596 struct ibmad_port *ibmad_port; 597 ib_portid_t port_id = { 0 }; 598 uint8_t ni[IB_SMP_DATA_SIZE] = { 0 }; 599 int mgmt_classes[3] = 600 { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS }; 601 602 const struct ibdiag_opt opts[] = { 603 {"node-name-map", 1, 1, "<file>", "node name map file"}, 604 {"switch", 'S', 1, "<port_guid>", 605 "start partial scan at the port specified by <port_guid> (hex format)"}, 606 {"port-guid", 'G', 1, "<port_guid>", 607 "(same as -S)"}, 608 {"Direct", 'D', 1, "<dr_path>", 609 "start partial scan at the port specified by <dr_path>"}, 610 {"all", 'a', 0, NULL, 611 "print all nodes found in a partial fabric scan"}, 612 {"hops", 'n', 1, "<hops>", 613 "Number of hops to include away from specified node"}, 614 {"down", 'd', 0, NULL, "print only down links"}, 615 {"line", 'l', 0, NULL, 616 "(line mode) print all information for each link on a single line"}, 617 {"additional", 'p', 0, NULL, 618 "print additional port settings (PktLifeTime, HoqLife, VLStallCount)"}, 619 {"load-cache", 2, 1, "<file>", 620 "filename of ibnetdiscover cache to load"}, 621 {"diff", 3, 1, "<file>", 622 "filename of ibnetdiscover cache to diff"}, 623 {"diffcheck", 4, 1, "<key(s)>", 624 "specify checks to execute for --diff"}, 625 {"filterdownports", 5, 1, "<file>", 626 "filename of ibnetdiscover cache to filter downports"}, 627 {"outstanding_smps", 'o', 1, NULL, 628 "specify the number of outstanding SMP's which should be " 629 "issued during the scan"}, 630 {"switches-only", 6, 0, NULL, 631 "Output only switches"}, 632 {"cas-only", 7, 0, NULL, 633 "Output only CAs"}, 634 {0} 635 }; 636 char usage_args[] = ""; 637 638 ibdiag_process_opts(argc, argv, &config, "aDdGgKLlnpRS", opts, 639 process_opt, usage_args, NULL); 640 641 argc -= optind; 642 argv += optind; 643 644 ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3); 645 if (!ibmad_port) { 646 fprintf(stderr, "Failed to open %s port %d\n", ibd_ca, 647 ibd_ca_port); 648 exit(1); 649 } 650 651 smp_mkey_set(ibmad_port, ibd_mkey); 652 653 if (ibd_timeout) { 654 mad_rpc_set_timeout(ibmad_port, ibd_timeout); 655 config.timeout_ms = ibd_timeout; 656 } 657 658 config.flags = ibd_ibnetdisc_flags; 659 config.mkey = ibd_mkey; 660 661 node_name_map = open_node_name_map(node_name_map_file); 662 663 if (dr_path && load_cache_file) { 664 mad_rpc_close_port(ibmad_port); 665 fprintf(stderr, "Cannot specify cache and direct route path\n"); 666 exit(1); 667 } 668 669 if (dr_path) { 670 /* only scan part of the fabric */ 671 if ((resolved = 672 resolve_portid_str(ibd_ca, ibd_ca_port, &port_id, dr_path, 673 IB_DEST_DRPATH, NULL, ibmad_port)) < 0) 674 IBWARN("Failed to resolve %s; attempting full scan", 675 dr_path); 676 } else if (guid_str) { 677 if ((resolved = 678 resolve_portid_str(ibd_ca, ibd_ca_port, &port_id, 679 guid_str, IB_DEST_GUID, NULL, 680 ibmad_port)) < 0) 681 IBWARN("Failed to resolve %s; attempting full scan\n", 682 guid_str); 683 } 684 685 if (!smp_query_via(ni, &port_id, IB_ATTR_NODE_INFO, 0, 686 ibd_timeout, ibmad_port)){ 687 mad_rpc_close_port(ibmad_port); 688 fprintf(stderr, 689 "Failed to get local Node Info\n"); 690 exit(1); 691 } 692 mad_rpc_close_port(ibmad_port); 693 694 if (diff_cache_file && 695 !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0))) 696 IBEXIT("loading cached fabric for diff failed\n"); 697 698 if (filterdownports_cache_file && 699 !(filterdownports_fabric = ibnd_load_fabric(filterdownports_cache_file, 0))) 700 IBEXIT("loading cached fabric for filterdownports failed\n"); 701 702 if (load_cache_file) { 703 if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) { 704 fprintf(stderr, "loading cached fabric failed\n"); 705 exit(1); 706 } 707 } else { 708 if (resolved >= 0) { 709 if (!config.max_hops) 710 config.max_hops = 1; 711 if (!(fabric = 712 ibnd_discover_fabric(ibd_ca, ibd_ca_port, &port_id, &config))) 713 IBWARN("Partial fabric scan failed;" 714 " attempting full scan\n"); 715 } 716 717 if (!fabric && 718 !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config))) { 719 fprintf(stderr, "discover failed\n"); 720 rc = 1; 721 goto close_port; 722 } 723 } 724 725 if (!all && guid_str) { 726 ibnd_port_t *p = ibnd_find_port_guid(fabric, guid); 727 if (p && (!only_flag || p->node->type == only_type)) { 728 ibnd_node_t *n = p->node; 729 if (diff_fabric) 730 diff_node(n, diff_fabric, fabric); 731 else 732 print_node(n, NULL); 733 } 734 else 735 fprintf(stderr, "Failed to find port: %s\n", guid_str); 736 } else if (!all && dr_path) { 737 ibnd_port_t *p = NULL; 738 mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(guid)); 739 740 p = ibnd_find_port_guid(fabric, guid); 741 if (p && (!only_flag || p->node->type == only_type)) { 742 ibnd_node_t *n = p->node; 743 if (diff_fabric) 744 diff_node(n, diff_fabric, fabric); 745 else 746 print_node(n, NULL); 747 } 748 else 749 fprintf(stderr, "Failed to find port: %s\n", dr_path); 750 } else { 751 if (diff_fabric) 752 diff_node(NULL, diff_fabric, fabric); 753 else { 754 if (only_flag) 755 ibnd_iter_nodes_type(fabric, print_node, 756 only_type, NULL); 757 else 758 ibnd_iter_nodes(fabric, print_node, NULL); 759 } 760 } 761 762 ibnd_destroy_fabric(fabric); 763 if (diff_fabric) 764 ibnd_destroy_fabric(diff_fabric); 765 766 close_port: 767 close_node_name_map(node_name_map); 768 exit(rc); 769 } 770