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.
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:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
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.
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
39 #endif /* HAVE_CONFIG_H */
50 #include <infiniband/umad.h>
51 #include <infiniband/mad.h>
52 #include <complib/cl_nodenamemap.h>
53 #include <infiniband/ibnetdisc.h>
55 #include "ibdiag_common.h"
57 #define LIST_CA_NODE (1 << IB_NODE_CA)
58 #define LIST_SWITCH_NODE (1 << IB_NODE_SWITCH)
59 #define LIST_ROUTER_NODE (1 << IB_NODE_ROUTER)
61 #define DIFF_FLAG_SWITCH 0x01
62 #define DIFF_FLAG_CA 0x02
63 #define DIFF_FLAG_ROUTER 0x04
64 #define DIFF_FLAG_PORT_CONNECTION 0x08
65 #define DIFF_FLAG_LID 0x10
66 #define DIFF_FLAG_NODE_DESCRIPTION 0x20
68 #define DIFF_FLAG_DEFAULT (DIFF_FLAG_SWITCH | DIFF_FLAG_CA | DIFF_FLAG_ROUTER \
69 | DIFF_FLAG_PORT_CONNECTION)
73 static char *node_name_map_file = NULL;
74 static nn_map_t *node_name_map = NULL;
75 static char *cache_file = NULL;
76 static char *load_cache_file = NULL;
77 static char *diff_cache_file = NULL;
78 static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
80 static int report_max_hops = 0;
84 * Define our own conversion functions to maintain compatibility with the old
85 * ibnetdiscover which did not use the ibmad conversion functions.
87 char *dump_linkspeed_compat(uint32_t speed)
103 char *dump_linkspeedext_compat(uint32_t espeed, uint32_t speed, uint32_t fdr10)
110 return dump_linkspeed_compat(speed);
122 char *dump_linkwidth_compat(uint32_t width)
144 static inline const char *ports_nt_str_compat(ibnd_node_t * node)
146 switch (node->type) {
157 char *node_name(ibnd_node_t * node)
159 static char buf[256];
161 switch (node->type) {
163 sprintf(buf, "\"%s", "S");
166 sprintf(buf, "\"%s", "H");
169 sprintf(buf, "\"%s", "R");
172 sprintf(buf, "\"%s", "?");
175 sprintf(buf + 2, "-%016" PRIx64 "\"", node->guid);
180 void list_node(ibnd_node_t * node, void *user_data)
183 char *nodename = remap_node_name(node_name_map, node->guid,
186 switch (node->type) {
188 node_type = "Switch";
194 node_type = "Router";
201 "%s\t : 0x%016" PRIx64
202 " ports %d devid 0x%x vendid 0x%x \"%s\"\n", node_type,
203 node->guid, node->numports, mad_get_field(node->info, 0,
205 mad_get_field(node->info, 0, IB_NODE_VENDORID_F), nodename);
210 void list_nodes(ibnd_fabric_t * fabric, int list)
212 if (list & LIST_CA_NODE)
213 ibnd_iter_nodes_type(fabric, list_node, IB_NODE_CA, NULL);
214 if (list & LIST_SWITCH_NODE)
215 ibnd_iter_nodes_type(fabric, list_node, IB_NODE_SWITCH, NULL);
216 if (list & LIST_ROUTER_NODE)
217 ibnd_iter_nodes_type(fabric, list_node, IB_NODE_ROUTER, NULL);
220 void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix)
222 uint64_t sysimgguid =
223 mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
225 fprintf(f, "\n%svendid=0x%x\n", out_prefix ? out_prefix : "",
226 mad_get_field(node->info, 0, IB_NODE_VENDORID_F));
227 fprintf(f, "%sdevid=0x%x\n", out_prefix ? out_prefix : "",
228 mad_get_field(node->info, 0, IB_NODE_DEVID_F));
230 fprintf(f, "%ssysimgguid=0x%" PRIx64,
231 out_prefix ? out_prefix : "", sysimgguid);
232 if (group && node->chassis && node->chassis->chassisnum) {
233 fprintf(f, "\t\t# Chassis %d", node->chassis->chassisnum);
235 fprintf(f, " (%s)", clean_nodedesc(chname));
236 if (ibnd_is_xsigo_tca(node->guid) && node->ports[1] &&
237 node->ports[1]->remoteport)
238 fprintf(f, " slot %d",
239 node->ports[1]->remoteport->portnum);
242 (group && node->chassis && node->chassis->chassisnum))
246 uint64_t out_chassis(ibnd_fabric_t * fabric, unsigned char chassisnum)
250 fprintf(f, "\nChassis %u", chassisnum);
251 guid = ibnd_get_chassis_guid(fabric, chassisnum);
253 fprintf(f, " (guid 0x%" PRIx64 ")", guid);
258 void out_switch_detail(ibnd_node_t * node, char *sw_prefix)
260 char *nodename = NULL;
262 nodename = remap_node_name(node_name_map, node->guid, node->nodedesc);
264 fprintf(f, "%sSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d",
265 sw_prefix ? sw_prefix : "", node->numports, node_name(node),
266 nodename, node->smaenhsp0 ? "enhanced" : "base",
267 node->smalid, node->smalmc);
272 void out_switch(ibnd_node_t * node, int group, char *chname, char *id_prefix,
278 out_ids(node, group, chname, id_prefix);
279 fprintf(f, "%sswitchguid=0x%" PRIx64,
280 id_prefix ? id_prefix : "", node->guid);
281 fprintf(f, "(%" PRIx64 ")",
282 mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F));
285 str = ibnd_get_chassis_type(node);
287 fprintf(f, "%s ", str);
288 str = ibnd_get_chassis_slot_str(node, str2, 256);
290 fprintf(f, "%s", str);
294 out_switch_detail(node, sw_prefix);
298 void out_ca_detail(ibnd_node_t * node, char *ca_prefix)
302 switch (node->type) {
314 fprintf(f, "%s%s\t%d %s\t\t# \"%s\"", ca_prefix ? ca_prefix : "",
315 node_type, node->numports, node_name(node),
316 clean_nodedesc(node->nodedesc));
319 void out_ca(ibnd_node_t * node, int group, char *chname, char *id_prefix,
324 out_ids(node, group, chname, id_prefix);
325 switch (node->type) {
337 fprintf(f, "%s%sguid=0x%" PRIx64 "\n",
338 id_prefix ? id_prefix : "", node_type, node->guid);
339 out_ca_detail(node, ca_prefix);
340 if (group && ibnd_is_xsigo_hca(node->guid))
341 fprintf(f, " (scp)");
345 #define OUT_BUFFER_SIZE 16
346 static char *out_ext_port(ibnd_port_t * port, int group)
348 static char mapping[OUT_BUFFER_SIZE];
350 if (group && port->ext_portnum != 0) {
351 snprintf(mapping, OUT_BUFFER_SIZE,
352 "[ext %d]", port->ext_portnum);
359 void out_switch_port(ibnd_port_t * port, int group, char *out_prefix)
361 char *ext_port_str = NULL;
362 char *rem_nodename = NULL;
363 uint32_t iwidth = mad_get_field(port->info, 0,
364 IB_PORT_LINK_WIDTH_ACTIVE_F);
365 uint32_t ispeed = mad_get_field(port->info, 0,
366 IB_PORT_LINK_SPEED_ACTIVE_F);
367 uint32_t vlcap = mad_get_field(port->info, 0,
369 uint32_t fdr10 = mad_get_field(port->ext_info, 0,
370 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
371 uint32_t cap_mask, espeed;
373 DEBUG("port %p:%d remoteport %p\n", port, port->portnum,
375 fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
377 ext_port_str = out_ext_port(port, group);
379 fprintf(f, "%s", ext_port_str);
381 rem_nodename = remap_node_name(node_name_map,
382 port->remoteport->node->guid,
383 port->remoteport->node->nodedesc);
385 ext_port_str = out_ext_port(port->remoteport, group);
387 if (!port->node->ports[0]) {
392 cap_mask = mad_get_field(port->node->ports[0]->info, 0,
394 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
395 espeed = mad_get_field(port->info, 0,
396 IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
400 fprintf(f, "\t%s[%d]%s",
401 node_name(port->remoteport->node), port->remoteport->portnum,
402 ext_port_str ? ext_port_str : "");
403 if (port->remoteport->node->type != IB_NODE_SWITCH)
404 fprintf(f, "(%" PRIx64 ") ", port->remoteport->guid);
405 fprintf(f, "\t\t# \"%s\" lid %d %s%s",
407 port->remoteport->node->type == IB_NODE_SWITCH ?
408 port->remoteport->node->smalid :
409 port->remoteport->base_lid,
410 dump_linkwidth_compat(iwidth),
411 (ispeed != 4 && !espeed) ?
412 dump_linkspeed_compat(ispeed) :
413 dump_linkspeedext_compat(espeed, ispeed, fdr10));
416 fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
418 fprintf(f, " e=%d", espeed);
421 if (ibnd_is_xsigo_tca(port->remoteport->guid))
422 fprintf(f, " slot %d", port->portnum);
423 else if (ibnd_is_xsigo_hca(port->remoteport->guid))
424 fprintf(f, " (scp)");
430 void out_ca_port(ibnd_port_t * port, int group, char *out_prefix)
433 char *rem_nodename = NULL;
434 uint32_t iwidth = mad_get_field(port->info, 0,
435 IB_PORT_LINK_WIDTH_ACTIVE_F);
436 uint32_t ispeed = mad_get_field(port->info, 0,
437 IB_PORT_LINK_SPEED_ACTIVE_F);
438 uint32_t vlcap = mad_get_field(port->info, 0,
440 uint32_t fdr10 = mad_get_field(port->ext_info, 0,
441 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
442 uint32_t cap_mask, espeed;
444 fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
445 if (port->node->type != IB_NODE_SWITCH)
446 fprintf(f, "(%" PRIx64 ") ", port->guid);
447 fprintf(f, "\t%s[%d]",
448 node_name(port->remoteport->node), port->remoteport->portnum);
449 str = out_ext_port(port->remoteport, group);
451 fprintf(f, "%s", str);
452 if (port->remoteport->node->type != IB_NODE_SWITCH)
453 fprintf(f, " (%" PRIx64 ") ", port->remoteport->guid);
455 rem_nodename = remap_node_name(node_name_map,
456 port->remoteport->node->guid,
457 port->remoteport->node->nodedesc);
459 cap_mask = mad_get_field(port->info, 0, IB_PORT_CAPMASK_F);
460 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
461 espeed = mad_get_field(port->info, 0,
462 IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
466 fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s",
467 port->base_lid, port->lmc, rem_nodename,
468 port->remoteport->node->type == IB_NODE_SWITCH ?
469 port->remoteport->node->smalid :
470 port->remoteport->base_lid,
471 dump_linkwidth_compat(iwidth),
472 (ispeed != 4 && !espeed) ?
473 dump_linkspeed_compat(ispeed) :
474 dump_linkspeedext_compat(espeed, ispeed, fdr10));
477 fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
479 fprintf(f, " e=%d", espeed);
487 struct iter_user_data {
489 int skip_chassis_nodes;
492 static void switch_iter_func(ibnd_node_t * node, void *iter_user_data)
496 struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
498 DEBUG("SWITCH: node %p\n", node);
500 /* skip chassis based switches if flagged */
501 if (data->skip_chassis_nodes && node->chassis
502 && node->chassis->chassisnum)
505 out_switch(node, data->group, NULL, NULL, NULL);
506 for (p = 1; p <= node->numports; p++) {
507 port = node->ports[p];
508 if (port && port->remoteport)
509 out_switch_port(port, data->group, NULL);
513 static void ca_iter_func(ibnd_node_t * node, void *iter_user_data)
517 struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
519 DEBUG("CA: node %p\n", node);
520 /* Now, skip chassis based CAs */
521 if (data->group && node->chassis && node->chassis->chassisnum)
523 out_ca(node, data->group, NULL, NULL, NULL);
525 for (p = 1; p <= node->numports; p++) {
526 port = node->ports[p];
527 if (port && port->remoteport)
528 out_ca_port(port, data->group, NULL);
532 static void router_iter_func(ibnd_node_t * node, void *iter_user_data)
536 struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
538 DEBUG("RT: node %p\n", node);
539 /* Now, skip chassis based RTs */
540 if (data->group && node->chassis && node->chassis->chassisnum)
542 out_ca(node, data->group, NULL, NULL, NULL);
543 for (p = 1; p <= node->numports; p++) {
544 port = node->ports[p];
545 if (port && port->remoteport)
546 out_ca_port(port, data->group, NULL);
550 int dump_topology(int group, ibnd_fabric_t * fabric)
558 struct iter_user_data iter_user_data;
560 fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));
562 fprintf(f, "# Reported max hops discovered: %u\n"
563 "# Total MADs used: %u\n",
564 fabric->maxhops_discovered, fabric->total_mads_used);
565 fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n",
566 fabric->from_node->guid,
567 mad_get_field64(fabric->from_node->info, 0,
568 IB_NODE_PORT_GUID_F));
570 /* Make pass on switches */
572 ibnd_chassis_t *ch = NULL;
574 /* Chassis based switches first */
575 for (ch = fabric->chassis; ch; ch = ch->next) {
580 chguid = out_chassis(fabric, ch->chassisnum);
582 if (ibnd_is_xsigo_guid(chguid)) {
583 for (node = ch->nodes; node;
584 node = node->next_chassis_node) {
585 if (ibnd_is_xsigo_hca(node->guid)) {
586 chname = node->nodedesc;
587 fprintf(f, "Hostname: %s\n",
594 fprintf(f, "\n# Spine Nodes");
595 for (n = 1; n <= SPINES_MAX_NUM; n++) {
596 if (ch->spinenode[n]) {
597 out_switch(ch->spinenode[n], group,
600 p <= ch->spinenode[n]->numports;
603 ch->spinenode[n]->ports[p];
604 if (port && port->remoteport)
605 out_switch_port(port,
611 fprintf(f, "\n# Line Nodes");
612 for (n = 1; n <= LINES_MAX_NUM; n++) {
613 if (ch->linenode[n]) {
614 out_switch(ch->linenode[n], group,
617 p <= ch->linenode[n]->numports;
620 ch->linenode[n]->ports[p];
621 if (port && port->remoteport)
622 out_switch_port(port,
629 fprintf(f, "\n# Chassis Switches");
630 for (node = ch->nodes; node;
631 node = node->next_chassis_node) {
632 if (node->type == IB_NODE_SWITCH) {
633 out_switch(node, group, chname, NULL,
635 for (p = 1; p <= node->numports; p++) {
636 port = node->ports[p];
637 if (port && port->remoteport)
638 out_switch_port(port,
646 fprintf(f, "\n# Chassis CAs");
647 for (node = ch->nodes; node;
648 node = node->next_chassis_node) {
649 if (node->type == IB_NODE_CA) {
650 out_ca(node, group, chname, NULL, NULL);
651 for (p = 1; p <= node->numports; p++) {
652 port = node->ports[p];
653 if (port && port->remoteport)
654 out_ca_port(port, group,
662 } else { /* !group */
663 iter_user_data.group = group;
664 iter_user_data.skip_chassis_nodes = 0;
665 ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
671 iter_user_data.group = group;
672 iter_user_data.skip_chassis_nodes = 1;
674 fprintf(f, "\nNon-Chassis Nodes\n");
676 ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
680 iter_user_data.group = group;
681 iter_user_data.skip_chassis_nodes = 0;
682 /* Make pass on CAs */
683 ibnd_iter_nodes_type(fabric, ca_iter_func, IB_NODE_CA, &iter_user_data);
685 /* Make pass on routers */
686 ibnd_iter_nodes_type(fabric, router_iter_func, IB_NODE_ROUTER,
692 void dump_ports_report(ibnd_node_t * node, void *user_data)
695 ibnd_port_t *port = NULL;
696 char *nodename = NULL;
697 char *rem_nodename = NULL;
700 for (p = node->numports, port = node->ports[p]; p > 0;
701 port = node->ports[--p]) {
702 uint32_t iwidth, ispeed, fdr10, espeed, cap_mask;
703 uint8_t *info = NULL;
707 mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
709 mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
710 if (port->node->type == IB_NODE_SWITCH) {
711 if (port->node->ports[0])
712 info = (uint8_t *)&port->node->ports[0]->info;
715 info = (uint8_t *)&port->info;
717 cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
718 if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
719 espeed = mad_get_field(port->info, 0,
720 IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
728 fdr10 = mad_get_field(port->ext_info, 0,
729 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
730 nodename = remap_node_name(node_name_map,
732 port->node->nodedesc);
733 fprintf(stdout, "%2s %5d %2d 0x%016" PRIx64 " %s %s",
734 ports_nt_str_compat(node),
736 IB_NODE_SWITCH ? node->smalid : port->base_lid,
737 port->portnum, port->guid,
738 dump_linkwidth_compat(iwidth),
739 (ispeed != 4 && !espeed) ?
740 dump_linkspeed_compat(ispeed) :
741 dump_linkspeedext_compat(espeed, ispeed, fdr10));
742 if (port->remoteport) {
743 rem_nodename = remap_node_name(node_name_map,
744 port->remoteport->node->guid,
745 port->remoteport->node->nodedesc);
747 " - %2s %5d %2d 0x%016" PRIx64
748 " ( '%s' - '%s' )\n",
749 ports_nt_str_compat(port->remoteport->node),
750 port->remoteport->node->type == IB_NODE_SWITCH ?
751 port->remoteport->node->smalid :
752 port->remoteport->base_lid,
753 port->remoteport->portnum,
754 port->remoteport->guid, nodename, rem_nodename);
757 fprintf(stdout, "%36s'%s'\n", "", nodename);
763 struct iter_diff_data {
765 ibnd_fabric_t *fabric1;
766 ibnd_fabric_t *fabric2;
767 char *fabric1_prefix;
768 char *fabric2_prefix;
769 void (*out_header) (ibnd_node_t *, int, char *, char *, char *);
770 void (*out_header_detail) (ibnd_node_t *, char *);
771 void (*out_port) (ibnd_port_t *, int, char *);
774 static void diff_iter_out_header(ibnd_node_t * node,
775 struct iter_diff_data *data,
776 int *out_header_flag)
778 if (!(*out_header_flag)) {
779 (*data->out_header) (node, 0, NULL, NULL, NULL);
780 (*out_header_flag)++;
784 static void diff_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
785 int *out_header_flag, struct iter_diff_data *data)
787 ibnd_port_t *fabric1_port;
788 ibnd_port_t *fabric2_port;
791 for (p = 1; p <= fabric1_node->numports; p++) {
792 int fabric1_out = 0, fabric2_out = 0;
794 fabric1_port = fabric1_node->ports[p];
795 fabric2_port = fabric2_node->ports[p];
797 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
798 if ((fabric1_port && !fabric2_port)
799 || ((fabric1_port && fabric2_port)
800 && (fabric1_port->remoteport
801 && !fabric2_port->remoteport)))
803 else if ((!fabric1_port && fabric2_port)
804 || ((fabric1_port && fabric2_port)
805 && (!fabric1_port->remoteport
806 && fabric2_port->remoteport)))
808 else if ((fabric1_port && fabric2_port)
809 && ((fabric1_port->guid != fabric2_port->guid)
811 ((fabric1_port->remoteport
812 && fabric2_port->remoteport)
813 && (fabric1_port->remoteport->guid !=
814 fabric2_port->remoteport->guid)))) {
820 if ((data->diff_flags & DIFF_FLAG_LID)
821 && fabric1_port && fabric2_port
822 && fabric1_port->base_lid != fabric2_port->base_lid) {
827 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
828 && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
829 && fabric1_port && fabric2_port
830 && fabric1_port->remoteport && fabric2_port->remoteport
831 && memcmp(fabric1_port->remoteport->node->nodedesc,
832 fabric2_port->remoteport->node->nodedesc,
838 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
839 && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
840 && fabric1_port && fabric2_port
841 && fabric1_port->remoteport && fabric2_port->remoteport
842 && memcmp(fabric1_port->remoteport->node->nodedesc,
843 fabric2_port->remoteport->node->nodedesc,
849 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
850 && data->diff_flags & DIFF_FLAG_LID
851 && fabric1_port && fabric2_port
852 && fabric1_port->remoteport && fabric2_port->remoteport
853 && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid) {
859 diff_iter_out_header(fabric1_node, data,
861 (*data->out_port) (fabric1_port, 0,
862 data->fabric1_prefix);
865 diff_iter_out_header(fabric1_node, data,
867 (*data->out_port) (fabric2_port, 0,
868 data->fabric2_prefix);
873 static void diff_iter_func(ibnd_node_t * fabric1_node, void *iter_user_data)
875 struct iter_diff_data *data = iter_user_data;
876 ibnd_node_t *fabric2_node;
877 ibnd_port_t *fabric1_port;
880 DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
882 fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
884 (*data->out_header) (fabric1_node, 0, NULL,
885 data->fabric1_prefix,
886 data->fabric1_prefix);
887 for (p = 1; p <= fabric1_node->numports; p++) {
888 fabric1_port = fabric1_node->ports[p];
889 if (fabric1_port && fabric1_port->remoteport)
890 (*data->out_port) (fabric1_port, 0,
891 data->fabric1_prefix);
893 } else if (data->diff_flags &
894 (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_LID
895 | DIFF_FLAG_NODE_DESCRIPTION)) {
896 int out_header_flag = 0;
898 if ((data->diff_flags & DIFF_FLAG_LID
899 && fabric1_node->smalid != fabric2_node->smalid) ||
900 (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
901 && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
902 IB_SMP_DATA_SIZE))) {
903 (*data->out_header) (fabric1_node, 0, NULL, NULL,
904 data->fabric1_prefix);
905 (*data->out_header_detail) (fabric2_node,
906 data->fabric2_prefix);
911 if (fabric1_node->numports != fabric2_node->numports) {
912 diff_iter_out_header(fabric1_node, data,
914 fprintf(f, "%snumports = %d\n", data->fabric1_prefix,
915 fabric1_node->numports);
916 fprintf(f, "%snumports = %d\n", data->fabric2_prefix,
917 fabric2_node->numports);
921 if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
922 || data->diff_flags & DIFF_FLAG_LID)
923 diff_ports(fabric1_node, fabric2_node, &out_header_flag,
928 static int diff_common(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric,
929 int node_type, uint32_t diff_flags,
930 void (*out_header) (ibnd_node_t *, int, char *, char *,
932 void (*out_header_detail) (ibnd_node_t *, char *),
933 void (*out_port) (ibnd_port_t *, int, char *))
935 struct iter_diff_data iter_diff_data;
937 iter_diff_data.diff_flags = diff_flags;
938 iter_diff_data.fabric1 = orig_fabric;
939 iter_diff_data.fabric2 = new_fabric;
940 iter_diff_data.fabric1_prefix = "< ";
941 iter_diff_data.fabric2_prefix = "> ";
942 iter_diff_data.out_header = out_header;
943 iter_diff_data.out_header_detail = out_header_detail;
944 iter_diff_data.out_port = out_port;
945 ibnd_iter_nodes_type(orig_fabric, diff_iter_func, node_type,
948 /* Do opposite diff to find existence of node types
949 * in new_fabric but not in orig_fabric.
951 * In this diff, we don't need to check port connections,
952 * lids, or node descriptions since it has already been
953 * done (i.e. checks are only done when guid exists on both
956 iter_diff_data.diff_flags = diff_flags & ~DIFF_FLAG_PORT_CONNECTION;
957 iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
958 iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
959 iter_diff_data.fabric1 = new_fabric;
960 iter_diff_data.fabric2 = orig_fabric;
961 iter_diff_data.fabric1_prefix = "> ";
962 iter_diff_data.fabric2_prefix = "< ";
963 iter_diff_data.out_header = out_header;
964 iter_diff_data.out_header_detail = out_header_detail;
965 iter_diff_data.out_port = out_port;
966 ibnd_iter_nodes_type(new_fabric, diff_iter_func, node_type,
972 int diff(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric)
974 if (diffcheck_flags & DIFF_FLAG_SWITCH)
975 diff_common(orig_fabric, new_fabric, IB_NODE_SWITCH,
976 diffcheck_flags, out_switch, out_switch_detail,
979 if (diffcheck_flags & DIFF_FLAG_CA)
980 diff_common(orig_fabric, new_fabric, IB_NODE_CA,
981 diffcheck_flags, out_ca, out_ca_detail,
984 if (diffcheck_flags & DIFF_FLAG_ROUTER)
985 diff_common(orig_fabric, new_fabric, IB_NODE_ROUTER,
986 diffcheck_flags, out_ca, out_ca_detail,
992 static int list, group, ports_report;
994 static int process_opt(void *context, int ch, char *optarg)
996 struct ibnd_config *cfg = context;
1001 node_name_map_file = strdup(optarg);
1004 cache_file = strdup(optarg);
1007 load_cache_file = strdup(optarg);
1010 diff_cache_file = strdup(optarg);
1013 diffcheck_flags = 0;
1014 p = strtok(optarg, ",");
1016 if (!strcasecmp(p, "sw"))
1017 diffcheck_flags |= DIFF_FLAG_SWITCH;
1018 else if (!strcasecmp(p, "ca"))
1019 diffcheck_flags |= DIFF_FLAG_CA;
1020 else if (!strcasecmp(p, "router"))
1021 diffcheck_flags |= DIFF_FLAG_ROUTER;
1022 else if (!strcasecmp(p, "port"))
1023 diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
1024 else if (!strcasecmp(p, "lid"))
1025 diffcheck_flags |= DIFF_FLAG_LID;
1026 else if (!strcasecmp(p, "nodedesc"))
1027 diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
1029 fprintf(stderr, "invalid diff check key: %s\n",
1033 p = strtok(NULL, ",");
1037 cfg->show_progress = 1;
1043 list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
1049 list = LIST_SWITCH_NODE;
1052 list = LIST_CA_NODE;
1055 list = LIST_ROUTER_NODE;
1061 report_max_hops = 1;
1064 cfg->max_smps = strtoul(optarg, NULL, 0);
1073 int main(int argc, char **argv)
1075 struct ibnd_config config = { 0 };
1076 ibnd_fabric_t *fabric = NULL;
1077 ibnd_fabric_t *diff_fabric = NULL;
1079 const struct ibdiag_opt opts[] = {
1080 {"full", 'f', 0, NULL, "show full information (ports' speed and width, vlcap)"},
1081 {"show", 's', 0, NULL, "show more information"},
1082 {"list", 'l', 0, NULL, "list of connected nodes"},
1083 {"grouping", 'g', 0, NULL, "show grouping"},
1084 {"Hca_list", 'H', 0, NULL, "list of connected CAs"},
1085 {"Switch_list", 'S', 0, NULL, "list of connected switches"},
1086 {"Router_list", 'R', 0, NULL, "list of connected routers"},
1087 {"node-name-map", 1, 1, "<file>", "node name map file"},
1088 {"cache", 2, 1, "<file>",
1089 "filename to cache ibnetdiscover data to"},
1090 {"load-cache", 3, 1, "<file>",
1091 "filename of ibnetdiscover cache to load"},
1092 {"diff", 4, 1, "<file>",
1093 "filename of ibnetdiscover cache to diff"},
1094 {"diffcheck", 5, 1, "<key(s)>",
1095 "specify checks to execute for --diff"},
1096 {"ports", 'p', 0, NULL, "obtain a ports report"},
1097 {"max_hops", 'm', 0, NULL,
1098 "report max hops discovered by the library"},
1099 {"outstanding_smps", 'o', 1, NULL,
1100 "specify the number of outstanding SMP's which should be "
1101 "issued during the scan"},
1104 char usage_args[] = "[topology-file]";
1106 ibdiag_process_opts(argc, argv, &config, "DGKLs", opts, process_opt,
1115 config.timeout_ms = ibd_timeout;
1117 config.flags = ibd_ibnetdisc_flags;
1119 if (argc && !(f = fopen(argv[0], "w")))
1120 IBEXIT("can't open file %s for writing", argv[0]);
1122 config.mkey = ibd_mkey;
1124 node_name_map = open_node_name_map(node_name_map_file);
1126 if (diff_cache_file &&
1127 !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
1128 IBEXIT("loading cached fabric for diff failed\n");
1130 if (load_cache_file) {
1131 if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL)
1132 IBEXIT("loading cached fabric failed\n");
1135 ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config)) == NULL)
1136 IBEXIT("discover failed\n");
1140 ibnd_iter_nodes(fabric, dump_ports_report, NULL);
1142 list_nodes(fabric, list);
1143 else if (diff_fabric)
1144 diff(diff_fabric, fabric);
1146 dump_topology(group, fabric);
1149 if (ibnd_cache_fabric(fabric, cache_file, 0) < 0)
1150 IBEXIT("caching ibnetdiscover data failed\n");
1152 ibnd_destroy_fabric(fabric);
1154 ibnd_destroy_fabric(diff_fabric);
1155 close_node_name_map(node_name_map);