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
filterdownport_check(ibnd_node_t * node,ibnd_port_t * port)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
print_port(ibnd_node_t * node,ibnd_port_t * port,char * out_prefix)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
nodetype_str(ibnd_node_t * node)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
print_node_header(ibnd_node_t * node,int * out_header_flag,char * out_prefix)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
print_node(ibnd_node_t * node,void * user_data)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
diff_node_ports(ibnd_node_t * fabric1_node,ibnd_node_t * fabric2_node,int * head_print,struct iter_diff_data * data)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
diff_node_iter(ibnd_node_t * fabric1_node,void * iter_user_data)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
diff_node(ibnd_node_t * node,ibnd_fabric_t * orig_fabric,ibnd_fabric_t * new_fabric)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
process_opt(void * context,int ch,char * optarg)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
main(int argc,char ** argv)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