xref: /freebsd/contrib/ofed/infiniband-diags/src/ibnetdiscover.c (revision 87181516ef48be852d5e5fee53c6e0dbfc62f21e)
1*d6b92ffaSHans Petter Selasky /*
2*d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3*d6b92ffaSHans Petter Selasky  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4*d6b92ffaSHans Petter Selasky  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
5*d6b92ffaSHans Petter Selasky  * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
6*d6b92ffaSHans Petter Selasky  *
7*d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
8*d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
9*d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
10*d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
11*d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
12*d6b92ffaSHans Petter Selasky  *
13*d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
14*d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
15*d6b92ffaSHans Petter Selasky  *     conditions are met:
16*d6b92ffaSHans Petter Selasky  *
17*d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
18*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
19*d6b92ffaSHans Petter Selasky  *        disclaimer.
20*d6b92ffaSHans Petter Selasky  *
21*d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
22*d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
23*d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
24*d6b92ffaSHans Petter Selasky  *        provided with the distribution.
25*d6b92ffaSHans Petter Selasky  *
26*d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27*d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28*d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29*d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30*d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31*d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32*d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33*d6b92ffaSHans Petter Selasky  * SOFTWARE.
34*d6b92ffaSHans Petter Selasky  *
35*d6b92ffaSHans Petter Selasky  */
36*d6b92ffaSHans Petter Selasky 
37*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
38*d6b92ffaSHans Petter Selasky #include <config.h>
39*d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
40*d6b92ffaSHans Petter Selasky 
41*d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
42*d6b92ffaSHans Petter Selasky #include <stdio.h>
43*d6b92ffaSHans Petter Selasky #include <stdlib.h>
44*d6b92ffaSHans Petter Selasky #include <unistd.h>
45*d6b92ffaSHans Petter Selasky #include <time.h>
46*d6b92ffaSHans Petter Selasky #include <string.h>
47*d6b92ffaSHans Petter Selasky #include <getopt.h>
48*d6b92ffaSHans Petter Selasky #include <inttypes.h>
49*d6b92ffaSHans Petter Selasky 
50*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
51*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
52*d6b92ffaSHans Petter Selasky #include <complib/cl_nodenamemap.h>
53*d6b92ffaSHans Petter Selasky #include <infiniband/ibnetdisc.h>
54*d6b92ffaSHans Petter Selasky 
55*d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
56*d6b92ffaSHans Petter Selasky 
57*d6b92ffaSHans Petter Selasky #define LIST_CA_NODE	 (1 << IB_NODE_CA)
58*d6b92ffaSHans Petter Selasky #define LIST_SWITCH_NODE (1 << IB_NODE_SWITCH)
59*d6b92ffaSHans Petter Selasky #define LIST_ROUTER_NODE (1 << IB_NODE_ROUTER)
60*d6b92ffaSHans Petter Selasky 
61*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_SWITCH           0x01
62*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_CA               0x02
63*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_ROUTER           0x04
64*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_PORT_CONNECTION  0x08
65*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_LID              0x10
66*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_NODE_DESCRIPTION 0x20
67*d6b92ffaSHans Petter Selasky 
68*d6b92ffaSHans Petter Selasky #define DIFF_FLAG_DEFAULT (DIFF_FLAG_SWITCH | DIFF_FLAG_CA | DIFF_FLAG_ROUTER \
69*d6b92ffaSHans Petter Selasky 			   | DIFF_FLAG_PORT_CONNECTION)
70*d6b92ffaSHans Petter Selasky 
71*d6b92ffaSHans Petter Selasky static FILE *f;
72*d6b92ffaSHans Petter Selasky 
73*d6b92ffaSHans Petter Selasky static char *node_name_map_file = NULL;
74*d6b92ffaSHans Petter Selasky static nn_map_t *node_name_map = NULL;
75*d6b92ffaSHans Petter Selasky static char *cache_file = NULL;
76*d6b92ffaSHans Petter Selasky static char *load_cache_file = NULL;
77*d6b92ffaSHans Petter Selasky static char *diff_cache_file = NULL;
78*d6b92ffaSHans Petter Selasky static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
79*d6b92ffaSHans Petter Selasky 
80*d6b92ffaSHans Petter Selasky static int report_max_hops = 0;
81*d6b92ffaSHans Petter Selasky static int full_info;
82*d6b92ffaSHans Petter Selasky 
83*d6b92ffaSHans Petter Selasky /**
84*d6b92ffaSHans Petter Selasky  * Define our own conversion functions to maintain compatibility with the old
85*d6b92ffaSHans Petter Selasky  * ibnetdiscover which did not use the ibmad conversion functions.
86*d6b92ffaSHans Petter Selasky  */
dump_linkspeed_compat(uint32_t speed)87*d6b92ffaSHans Petter Selasky char *dump_linkspeed_compat(uint32_t speed)
88*d6b92ffaSHans Petter Selasky {
89*d6b92ffaSHans Petter Selasky 	switch (speed) {
90*d6b92ffaSHans Petter Selasky 	case 1:
91*d6b92ffaSHans Petter Selasky 		return ("SDR");
92*d6b92ffaSHans Petter Selasky 		break;
93*d6b92ffaSHans Petter Selasky 	case 2:
94*d6b92ffaSHans Petter Selasky 		return ("DDR");
95*d6b92ffaSHans Petter Selasky 		break;
96*d6b92ffaSHans Petter Selasky 	case 4:
97*d6b92ffaSHans Petter Selasky 		return ("QDR");
98*d6b92ffaSHans Petter Selasky 		break;
99*d6b92ffaSHans Petter Selasky 	}
100*d6b92ffaSHans Petter Selasky 	return ("???");
101*d6b92ffaSHans Petter Selasky }
102*d6b92ffaSHans Petter Selasky 
dump_linkspeedext_compat(uint32_t espeed,uint32_t speed,uint32_t fdr10)103*d6b92ffaSHans Petter Selasky char *dump_linkspeedext_compat(uint32_t espeed, uint32_t speed, uint32_t fdr10)
104*d6b92ffaSHans Petter Selasky {
105*d6b92ffaSHans Petter Selasky 	switch (espeed) {
106*d6b92ffaSHans Petter Selasky 	case 0:
107*d6b92ffaSHans Petter Selasky 		if (fdr10 & FDR10)
108*d6b92ffaSHans Petter Selasky 			return ("FDR10");
109*d6b92ffaSHans Petter Selasky 		else
110*d6b92ffaSHans Petter Selasky 			return dump_linkspeed_compat(speed);
111*d6b92ffaSHans Petter Selasky 		break;
112*d6b92ffaSHans Petter Selasky 	case 1:
113*d6b92ffaSHans Petter Selasky 		return ("FDR");
114*d6b92ffaSHans Petter Selasky 		break;
115*d6b92ffaSHans Petter Selasky 	case 2:
116*d6b92ffaSHans Petter Selasky 		return ("EDR");
117*d6b92ffaSHans Petter Selasky 		break;
118*d6b92ffaSHans Petter Selasky 	}
119*d6b92ffaSHans Petter Selasky 	return ("???");
120*d6b92ffaSHans Petter Selasky }
121*d6b92ffaSHans Petter Selasky 
dump_linkwidth_compat(uint32_t width)122*d6b92ffaSHans Petter Selasky char *dump_linkwidth_compat(uint32_t width)
123*d6b92ffaSHans Petter Selasky {
124*d6b92ffaSHans Petter Selasky 	switch (width) {
125*d6b92ffaSHans Petter Selasky 	case 1:
126*d6b92ffaSHans Petter Selasky 		return ("1x");
127*d6b92ffaSHans Petter Selasky 		break;
128*d6b92ffaSHans Petter Selasky 	case 2:
129*d6b92ffaSHans Petter Selasky 		return ("4x");
130*d6b92ffaSHans Petter Selasky 		break;
131*d6b92ffaSHans Petter Selasky 	case 4:
132*d6b92ffaSHans Petter Selasky 		return ("8x");
133*d6b92ffaSHans Petter Selasky 		break;
134*d6b92ffaSHans Petter Selasky 	case 8:
135*d6b92ffaSHans Petter Selasky 		return ("12x");
136*d6b92ffaSHans Petter Selasky 		break;
137*d6b92ffaSHans Petter Selasky 	case 16:
138*d6b92ffaSHans Petter Selasky 		return ("2x");
139*d6b92ffaSHans Petter Selasky 		break;
140*d6b92ffaSHans Petter Selasky 	}
141*d6b92ffaSHans Petter Selasky 	return ("??");
142*d6b92ffaSHans Petter Selasky }
143*d6b92ffaSHans Petter Selasky 
ports_nt_str_compat(ibnd_node_t * node)144*d6b92ffaSHans Petter Selasky static inline const char *ports_nt_str_compat(ibnd_node_t * node)
145*d6b92ffaSHans Petter Selasky {
146*d6b92ffaSHans Petter Selasky 	switch (node->type) {
147*d6b92ffaSHans Petter Selasky 	case IB_NODE_SWITCH:
148*d6b92ffaSHans Petter Selasky 		return "SW";
149*d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
150*d6b92ffaSHans Petter Selasky 		return "CA";
151*d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
152*d6b92ffaSHans Petter Selasky 		return "RT";
153*d6b92ffaSHans Petter Selasky 	}
154*d6b92ffaSHans Petter Selasky 	return "??";
155*d6b92ffaSHans Petter Selasky }
156*d6b92ffaSHans Petter Selasky 
node_name(ibnd_node_t * node)157*d6b92ffaSHans Petter Selasky char *node_name(ibnd_node_t * node)
158*d6b92ffaSHans Petter Selasky {
159*d6b92ffaSHans Petter Selasky 	static char buf[256];
160*d6b92ffaSHans Petter Selasky 
161*d6b92ffaSHans Petter Selasky 	switch (node->type) {
162*d6b92ffaSHans Petter Selasky 	case IB_NODE_SWITCH:
163*d6b92ffaSHans Petter Selasky 		sprintf(buf, "\"%s", "S");
164*d6b92ffaSHans Petter Selasky 		break;
165*d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
166*d6b92ffaSHans Petter Selasky 		sprintf(buf, "\"%s", "H");
167*d6b92ffaSHans Petter Selasky 		break;
168*d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
169*d6b92ffaSHans Petter Selasky 		sprintf(buf, "\"%s", "R");
170*d6b92ffaSHans Petter Selasky 		break;
171*d6b92ffaSHans Petter Selasky 	default:
172*d6b92ffaSHans Petter Selasky 		sprintf(buf, "\"%s", "?");
173*d6b92ffaSHans Petter Selasky 		break;
174*d6b92ffaSHans Petter Selasky 	}
175*d6b92ffaSHans Petter Selasky 	sprintf(buf + 2, "-%016" PRIx64 "\"", node->guid);
176*d6b92ffaSHans Petter Selasky 
177*d6b92ffaSHans Petter Selasky 	return buf;
178*d6b92ffaSHans Petter Selasky }
179*d6b92ffaSHans Petter Selasky 
list_node(ibnd_node_t * node,void * user_data)180*d6b92ffaSHans Petter Selasky void list_node(ibnd_node_t * node, void *user_data)
181*d6b92ffaSHans Petter Selasky {
182*d6b92ffaSHans Petter Selasky 	char *node_type;
183*d6b92ffaSHans Petter Selasky 	char *nodename = remap_node_name(node_name_map, node->guid,
184*d6b92ffaSHans Petter Selasky 					 node->nodedesc);
185*d6b92ffaSHans Petter Selasky 
186*d6b92ffaSHans Petter Selasky 	switch (node->type) {
187*d6b92ffaSHans Petter Selasky 	case IB_NODE_SWITCH:
188*d6b92ffaSHans Petter Selasky 		node_type = "Switch";
189*d6b92ffaSHans Petter Selasky 		break;
190*d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
191*d6b92ffaSHans Petter Selasky 		node_type = "Ca";
192*d6b92ffaSHans Petter Selasky 		break;
193*d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
194*d6b92ffaSHans Petter Selasky 		node_type = "Router";
195*d6b92ffaSHans Petter Selasky 		break;
196*d6b92ffaSHans Petter Selasky 	default:
197*d6b92ffaSHans Petter Selasky 		node_type = "???";
198*d6b92ffaSHans Petter Selasky 		break;
199*d6b92ffaSHans Petter Selasky 	}
200*d6b92ffaSHans Petter Selasky 	fprintf(f,
201*d6b92ffaSHans Petter Selasky 		"%s\t : 0x%016" PRIx64
202*d6b92ffaSHans Petter Selasky 		" ports %d devid 0x%x vendid 0x%x \"%s\"\n", node_type,
203*d6b92ffaSHans Petter Selasky 		node->guid, node->numports, mad_get_field(node->info, 0,
204*d6b92ffaSHans Petter Selasky 							  IB_NODE_DEVID_F),
205*d6b92ffaSHans Petter Selasky 		mad_get_field(node->info, 0, IB_NODE_VENDORID_F), nodename);
206*d6b92ffaSHans Petter Selasky 
207*d6b92ffaSHans Petter Selasky 	free(nodename);
208*d6b92ffaSHans Petter Selasky }
209*d6b92ffaSHans Petter Selasky 
list_nodes(ibnd_fabric_t * fabric,int list)210*d6b92ffaSHans Petter Selasky void list_nodes(ibnd_fabric_t * fabric, int list)
211*d6b92ffaSHans Petter Selasky {
212*d6b92ffaSHans Petter Selasky 	if (list & LIST_CA_NODE)
213*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes_type(fabric, list_node, IB_NODE_CA, NULL);
214*d6b92ffaSHans Petter Selasky 	if (list & LIST_SWITCH_NODE)
215*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes_type(fabric, list_node, IB_NODE_SWITCH, NULL);
216*d6b92ffaSHans Petter Selasky 	if (list & LIST_ROUTER_NODE)
217*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes_type(fabric, list_node, IB_NODE_ROUTER, NULL);
218*d6b92ffaSHans Petter Selasky }
219*d6b92ffaSHans Petter Selasky 
out_ids(ibnd_node_t * node,int group,char * chname,char * out_prefix)220*d6b92ffaSHans Petter Selasky void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix)
221*d6b92ffaSHans Petter Selasky {
222*d6b92ffaSHans Petter Selasky 	uint64_t sysimgguid =
223*d6b92ffaSHans Petter Selasky 	    mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
224*d6b92ffaSHans Petter Selasky 
225*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n%svendid=0x%x\n", out_prefix ? out_prefix : "",
226*d6b92ffaSHans Petter Selasky 		mad_get_field(node->info, 0, IB_NODE_VENDORID_F));
227*d6b92ffaSHans Petter Selasky 	fprintf(f, "%sdevid=0x%x\n", out_prefix ? out_prefix : "",
228*d6b92ffaSHans Petter Selasky 		mad_get_field(node->info, 0, IB_NODE_DEVID_F));
229*d6b92ffaSHans Petter Selasky 	if (sysimgguid)
230*d6b92ffaSHans Petter Selasky 		fprintf(f, "%ssysimgguid=0x%" PRIx64,
231*d6b92ffaSHans Petter Selasky 			out_prefix ? out_prefix : "", sysimgguid);
232*d6b92ffaSHans Petter Selasky 	if (group && node->chassis && node->chassis->chassisnum) {
233*d6b92ffaSHans Petter Selasky 		fprintf(f, "\t\t# Chassis %d", node->chassis->chassisnum);
234*d6b92ffaSHans Petter Selasky 		if (chname)
235*d6b92ffaSHans Petter Selasky 			fprintf(f, " (%s)", clean_nodedesc(chname));
236*d6b92ffaSHans Petter Selasky 		if (ibnd_is_xsigo_tca(node->guid) && node->ports[1] &&
237*d6b92ffaSHans Petter Selasky 		    node->ports[1]->remoteport)
238*d6b92ffaSHans Petter Selasky 			fprintf(f, " slot %d",
239*d6b92ffaSHans Petter Selasky 				node->ports[1]->remoteport->portnum);
240*d6b92ffaSHans Petter Selasky 	}
241*d6b92ffaSHans Petter Selasky 	if (sysimgguid ||
242*d6b92ffaSHans Petter Selasky 	    (group && node->chassis && node->chassis->chassisnum))
243*d6b92ffaSHans Petter Selasky 		fprintf(f, "\n");
244*d6b92ffaSHans Petter Selasky }
245*d6b92ffaSHans Petter Selasky 
out_chassis(ibnd_fabric_t * fabric,unsigned char chassisnum)246*d6b92ffaSHans Petter Selasky uint64_t out_chassis(ibnd_fabric_t * fabric, unsigned char chassisnum)
247*d6b92ffaSHans Petter Selasky {
248*d6b92ffaSHans Petter Selasky 	uint64_t guid;
249*d6b92ffaSHans Petter Selasky 
250*d6b92ffaSHans Petter Selasky 	fprintf(f, "\nChassis %u", chassisnum);
251*d6b92ffaSHans Petter Selasky 	guid = ibnd_get_chassis_guid(fabric, chassisnum);
252*d6b92ffaSHans Petter Selasky 	if (guid)
253*d6b92ffaSHans Petter Selasky 		fprintf(f, " (guid 0x%" PRIx64 ")", guid);
254*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
255*d6b92ffaSHans Petter Selasky 	return guid;
256*d6b92ffaSHans Petter Selasky }
257*d6b92ffaSHans Petter Selasky 
out_switch_detail(ibnd_node_t * node,char * sw_prefix)258*d6b92ffaSHans Petter Selasky void out_switch_detail(ibnd_node_t * node, char *sw_prefix)
259*d6b92ffaSHans Petter Selasky {
260*d6b92ffaSHans Petter Selasky 	char *nodename = NULL;
261*d6b92ffaSHans Petter Selasky 
262*d6b92ffaSHans Petter Selasky 	nodename = remap_node_name(node_name_map, node->guid, node->nodedesc);
263*d6b92ffaSHans Petter Selasky 
264*d6b92ffaSHans Petter Selasky 	fprintf(f, "%sSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d",
265*d6b92ffaSHans Petter Selasky 		sw_prefix ? sw_prefix : "", node->numports, node_name(node),
266*d6b92ffaSHans Petter Selasky 		nodename, node->smaenhsp0 ? "enhanced" : "base",
267*d6b92ffaSHans Petter Selasky 		node->smalid, node->smalmc);
268*d6b92ffaSHans Petter Selasky 
269*d6b92ffaSHans Petter Selasky 	free(nodename);
270*d6b92ffaSHans Petter Selasky }
271*d6b92ffaSHans Petter Selasky 
out_switch(ibnd_node_t * node,int group,char * chname,char * id_prefix,char * sw_prefix)272*d6b92ffaSHans Petter Selasky void out_switch(ibnd_node_t * node, int group, char *chname, char *id_prefix,
273*d6b92ffaSHans Petter Selasky 		char *sw_prefix)
274*d6b92ffaSHans Petter Selasky {
275*d6b92ffaSHans Petter Selasky 	char *str;
276*d6b92ffaSHans Petter Selasky 	char str2[256];
277*d6b92ffaSHans Petter Selasky 
278*d6b92ffaSHans Petter Selasky 	out_ids(node, group, chname, id_prefix);
279*d6b92ffaSHans Petter Selasky 	fprintf(f, "%sswitchguid=0x%" PRIx64,
280*d6b92ffaSHans Petter Selasky 		id_prefix ? id_prefix : "", node->guid);
281*d6b92ffaSHans Petter Selasky 	fprintf(f, "(%" PRIx64 ")",
282*d6b92ffaSHans Petter Selasky 		mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F));
283*d6b92ffaSHans Petter Selasky 	if (group) {
284*d6b92ffaSHans Petter Selasky 		fprintf(f, "\t# ");
285*d6b92ffaSHans Petter Selasky 		str = ibnd_get_chassis_type(node);
286*d6b92ffaSHans Petter Selasky 		if (str)
287*d6b92ffaSHans Petter Selasky 			fprintf(f, "%s ", str);
288*d6b92ffaSHans Petter Selasky 		str = ibnd_get_chassis_slot_str(node, str2, 256);
289*d6b92ffaSHans Petter Selasky 		if (str)
290*d6b92ffaSHans Petter Selasky 			fprintf(f, "%s", str);
291*d6b92ffaSHans Petter Selasky 	}
292*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
293*d6b92ffaSHans Petter Selasky 
294*d6b92ffaSHans Petter Selasky 	out_switch_detail(node, sw_prefix);
295*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
296*d6b92ffaSHans Petter Selasky }
297*d6b92ffaSHans Petter Selasky 
out_ca_detail(ibnd_node_t * node,char * ca_prefix)298*d6b92ffaSHans Petter Selasky void out_ca_detail(ibnd_node_t * node, char *ca_prefix)
299*d6b92ffaSHans Petter Selasky {
300*d6b92ffaSHans Petter Selasky 	char *node_type;
301*d6b92ffaSHans Petter Selasky 
302*d6b92ffaSHans Petter Selasky 	switch (node->type) {
303*d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
304*d6b92ffaSHans Petter Selasky 		node_type = "Ca";
305*d6b92ffaSHans Petter Selasky 		break;
306*d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
307*d6b92ffaSHans Petter Selasky 		node_type = "Rt";
308*d6b92ffaSHans Petter Selasky 		break;
309*d6b92ffaSHans Petter Selasky 	default:
310*d6b92ffaSHans Petter Selasky 		node_type = "???";
311*d6b92ffaSHans Petter Selasky 		break;
312*d6b92ffaSHans Petter Selasky 	}
313*d6b92ffaSHans Petter Selasky 
314*d6b92ffaSHans Petter Selasky 	fprintf(f, "%s%s\t%d %s\t\t# \"%s\"", ca_prefix ? ca_prefix : "",
315*d6b92ffaSHans Petter Selasky 		node_type, node->numports, node_name(node),
316*d6b92ffaSHans Petter Selasky 		clean_nodedesc(node->nodedesc));
317*d6b92ffaSHans Petter Selasky }
318*d6b92ffaSHans Petter Selasky 
out_ca(ibnd_node_t * node,int group,char * chname,char * id_prefix,char * ca_prefix)319*d6b92ffaSHans Petter Selasky void out_ca(ibnd_node_t * node, int group, char *chname, char *id_prefix,
320*d6b92ffaSHans Petter Selasky 	    char *ca_prefix)
321*d6b92ffaSHans Petter Selasky {
322*d6b92ffaSHans Petter Selasky 	char *node_type;
323*d6b92ffaSHans Petter Selasky 
324*d6b92ffaSHans Petter Selasky 	out_ids(node, group, chname, id_prefix);
325*d6b92ffaSHans Petter Selasky 	switch (node->type) {
326*d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
327*d6b92ffaSHans Petter Selasky 		node_type = "ca";
328*d6b92ffaSHans Petter Selasky 		break;
329*d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
330*d6b92ffaSHans Petter Selasky 		node_type = "rt";
331*d6b92ffaSHans Petter Selasky 		break;
332*d6b92ffaSHans Petter Selasky 	default:
333*d6b92ffaSHans Petter Selasky 		node_type = "???";
334*d6b92ffaSHans Petter Selasky 		break;
335*d6b92ffaSHans Petter Selasky 	}
336*d6b92ffaSHans Petter Selasky 
337*d6b92ffaSHans Petter Selasky 	fprintf(f, "%s%sguid=0x%" PRIx64 "\n",
338*d6b92ffaSHans Petter Selasky 		id_prefix ? id_prefix : "", node_type, node->guid);
339*d6b92ffaSHans Petter Selasky 	out_ca_detail(node, ca_prefix);
340*d6b92ffaSHans Petter Selasky 	if (group && ibnd_is_xsigo_hca(node->guid))
341*d6b92ffaSHans Petter Selasky 		fprintf(f, " (scp)");
342*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
343*d6b92ffaSHans Petter Selasky }
344*d6b92ffaSHans Petter Selasky 
345*d6b92ffaSHans Petter Selasky #define OUT_BUFFER_SIZE 16
out_ext_port(ibnd_port_t * port,int group)346*d6b92ffaSHans Petter Selasky static char *out_ext_port(ibnd_port_t * port, int group)
347*d6b92ffaSHans Petter Selasky {
348*d6b92ffaSHans Petter Selasky 	static char mapping[OUT_BUFFER_SIZE];
349*d6b92ffaSHans Petter Selasky 
350*d6b92ffaSHans Petter Selasky 	if (group && port->ext_portnum != 0) {
351*d6b92ffaSHans Petter Selasky 		snprintf(mapping, OUT_BUFFER_SIZE,
352*d6b92ffaSHans Petter Selasky 			 "[ext %d]", port->ext_portnum);
353*d6b92ffaSHans Petter Selasky 		return (mapping);
354*d6b92ffaSHans Petter Selasky 	}
355*d6b92ffaSHans Petter Selasky 
356*d6b92ffaSHans Petter Selasky 	return (NULL);
357*d6b92ffaSHans Petter Selasky }
358*d6b92ffaSHans Petter Selasky 
out_switch_port(ibnd_port_t * port,int group,char * out_prefix)359*d6b92ffaSHans Petter Selasky void out_switch_port(ibnd_port_t * port, int group, char *out_prefix)
360*d6b92ffaSHans Petter Selasky {
361*d6b92ffaSHans Petter Selasky 	char *ext_port_str = NULL;
362*d6b92ffaSHans Petter Selasky 	char *rem_nodename = NULL;
363*d6b92ffaSHans Petter Selasky 	uint32_t iwidth = mad_get_field(port->info, 0,
364*d6b92ffaSHans Petter Selasky 					IB_PORT_LINK_WIDTH_ACTIVE_F);
365*d6b92ffaSHans Petter Selasky 	uint32_t ispeed = mad_get_field(port->info, 0,
366*d6b92ffaSHans Petter Selasky 					IB_PORT_LINK_SPEED_ACTIVE_F);
367*d6b92ffaSHans Petter Selasky 	uint32_t vlcap = mad_get_field(port->info, 0,
368*d6b92ffaSHans Petter Selasky 				       IB_PORT_VL_CAP_F);
369*d6b92ffaSHans Petter Selasky 	uint32_t fdr10 = mad_get_field(port->ext_info, 0,
370*d6b92ffaSHans Petter Selasky 				       IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
371*d6b92ffaSHans Petter Selasky 	uint32_t cap_mask, espeed;
372*d6b92ffaSHans Petter Selasky 
373*d6b92ffaSHans Petter Selasky 	DEBUG("port %p:%d remoteport %p\n", port, port->portnum,
374*d6b92ffaSHans Petter Selasky 	      port->remoteport);
375*d6b92ffaSHans Petter Selasky 	fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
376*d6b92ffaSHans Petter Selasky 
377*d6b92ffaSHans Petter Selasky 	ext_port_str = out_ext_port(port, group);
378*d6b92ffaSHans Petter Selasky 	if (ext_port_str)
379*d6b92ffaSHans Petter Selasky 		fprintf(f, "%s", ext_port_str);
380*d6b92ffaSHans Petter Selasky 
381*d6b92ffaSHans Petter Selasky 	rem_nodename = remap_node_name(node_name_map,
382*d6b92ffaSHans Petter Selasky 				       port->remoteport->node->guid,
383*d6b92ffaSHans Petter Selasky 				       port->remoteport->node->nodedesc);
384*d6b92ffaSHans Petter Selasky 
385*d6b92ffaSHans Petter Selasky 	ext_port_str = out_ext_port(port->remoteport, group);
386*d6b92ffaSHans Petter Selasky 
387*d6b92ffaSHans Petter Selasky 	if (!port->node->ports[0]) {
388*d6b92ffaSHans Petter Selasky 		cap_mask = 0;
389*d6b92ffaSHans Petter Selasky 		ispeed = 0;
390*d6b92ffaSHans Petter Selasky 		espeed = 0;
391*d6b92ffaSHans Petter Selasky 	} else {
392*d6b92ffaSHans Petter Selasky 		cap_mask = mad_get_field(port->node->ports[0]->info, 0,
393*d6b92ffaSHans Petter Selasky 					 IB_PORT_CAPMASK_F);
394*d6b92ffaSHans Petter Selasky 		if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
395*d6b92ffaSHans Petter Selasky 			espeed = mad_get_field(port->info, 0,
396*d6b92ffaSHans Petter Selasky 					       IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
397*d6b92ffaSHans Petter Selasky 		else
398*d6b92ffaSHans Petter Selasky 			espeed = 0;
399*d6b92ffaSHans Petter Selasky 	}
400*d6b92ffaSHans Petter Selasky 	fprintf(f, "\t%s[%d]%s",
401*d6b92ffaSHans Petter Selasky 		node_name(port->remoteport->node), port->remoteport->portnum,
402*d6b92ffaSHans Petter Selasky 		ext_port_str ? ext_port_str : "");
403*d6b92ffaSHans Petter Selasky 	if (port->remoteport->node->type != IB_NODE_SWITCH)
404*d6b92ffaSHans Petter Selasky 		fprintf(f, "(%" PRIx64 ") ", port->remoteport->guid);
405*d6b92ffaSHans Petter Selasky 	fprintf(f, "\t\t# \"%s\" lid %d %s%s",
406*d6b92ffaSHans Petter Selasky 		rem_nodename,
407*d6b92ffaSHans Petter Selasky 		port->remoteport->node->type == IB_NODE_SWITCH ?
408*d6b92ffaSHans Petter Selasky 		port->remoteport->node->smalid :
409*d6b92ffaSHans Petter Selasky 		port->remoteport->base_lid,
410*d6b92ffaSHans Petter Selasky 		dump_linkwidth_compat(iwidth),
411*d6b92ffaSHans Petter Selasky 		(ispeed != 4 && !espeed) ?
412*d6b92ffaSHans Petter Selasky 			dump_linkspeed_compat(ispeed) :
413*d6b92ffaSHans Petter Selasky 			dump_linkspeedext_compat(espeed, ispeed, fdr10));
414*d6b92ffaSHans Petter Selasky 
415*d6b92ffaSHans Petter Selasky 	if (full_info) {
416*d6b92ffaSHans Petter Selasky 		fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
417*d6b92ffaSHans Petter Selasky 		if (espeed)
418*d6b92ffaSHans Petter Selasky 			fprintf(f, " e=%d", espeed);
419*d6b92ffaSHans Petter Selasky 	}
420*d6b92ffaSHans Petter Selasky 
421*d6b92ffaSHans Petter Selasky 	if (ibnd_is_xsigo_tca(port->remoteport->guid))
422*d6b92ffaSHans Petter Selasky 		fprintf(f, " slot %d", port->portnum);
423*d6b92ffaSHans Petter Selasky 	else if (ibnd_is_xsigo_hca(port->remoteport->guid))
424*d6b92ffaSHans Petter Selasky 		fprintf(f, " (scp)");
425*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
426*d6b92ffaSHans Petter Selasky 
427*d6b92ffaSHans Petter Selasky 	free(rem_nodename);
428*d6b92ffaSHans Petter Selasky }
429*d6b92ffaSHans Petter Selasky 
out_ca_port(ibnd_port_t * port,int group,char * out_prefix)430*d6b92ffaSHans Petter Selasky void out_ca_port(ibnd_port_t * port, int group, char *out_prefix)
431*d6b92ffaSHans Petter Selasky {
432*d6b92ffaSHans Petter Selasky 	char *str = NULL;
433*d6b92ffaSHans Petter Selasky 	char *rem_nodename = NULL;
434*d6b92ffaSHans Petter Selasky 	uint32_t iwidth = mad_get_field(port->info, 0,
435*d6b92ffaSHans Petter Selasky 					IB_PORT_LINK_WIDTH_ACTIVE_F);
436*d6b92ffaSHans Petter Selasky 	uint32_t ispeed = mad_get_field(port->info, 0,
437*d6b92ffaSHans Petter Selasky 					IB_PORT_LINK_SPEED_ACTIVE_F);
438*d6b92ffaSHans Petter Selasky 	uint32_t vlcap = mad_get_field(port->info, 0,
439*d6b92ffaSHans Petter Selasky 				       IB_PORT_VL_CAP_F);
440*d6b92ffaSHans Petter Selasky 	uint32_t fdr10 = mad_get_field(port->ext_info, 0,
441*d6b92ffaSHans Petter Selasky 				       IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
442*d6b92ffaSHans Petter Selasky 	uint32_t cap_mask, espeed;
443*d6b92ffaSHans Petter Selasky 
444*d6b92ffaSHans Petter Selasky 	fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
445*d6b92ffaSHans Petter Selasky 	if (port->node->type != IB_NODE_SWITCH)
446*d6b92ffaSHans Petter Selasky 		fprintf(f, "(%" PRIx64 ") ", port->guid);
447*d6b92ffaSHans Petter Selasky 	fprintf(f, "\t%s[%d]",
448*d6b92ffaSHans Petter Selasky 		node_name(port->remoteport->node), port->remoteport->portnum);
449*d6b92ffaSHans Petter Selasky 	str = out_ext_port(port->remoteport, group);
450*d6b92ffaSHans Petter Selasky 	if (str)
451*d6b92ffaSHans Petter Selasky 		fprintf(f, "%s", str);
452*d6b92ffaSHans Petter Selasky 	if (port->remoteport->node->type != IB_NODE_SWITCH)
453*d6b92ffaSHans Petter Selasky 		fprintf(f, " (%" PRIx64 ") ", port->remoteport->guid);
454*d6b92ffaSHans Petter Selasky 
455*d6b92ffaSHans Petter Selasky 	rem_nodename = remap_node_name(node_name_map,
456*d6b92ffaSHans Petter Selasky 				       port->remoteport->node->guid,
457*d6b92ffaSHans Petter Selasky 				       port->remoteport->node->nodedesc);
458*d6b92ffaSHans Petter Selasky 
459*d6b92ffaSHans Petter Selasky 	cap_mask = mad_get_field(port->info, 0, IB_PORT_CAPMASK_F);
460*d6b92ffaSHans Petter Selasky 	if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
461*d6b92ffaSHans Petter Selasky 		espeed = mad_get_field(port->info, 0,
462*d6b92ffaSHans Petter Selasky 				       IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
463*d6b92ffaSHans Petter Selasky 	else
464*d6b92ffaSHans Petter Selasky 		espeed = 0;
465*d6b92ffaSHans Petter Selasky 
466*d6b92ffaSHans Petter Selasky 	fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s",
467*d6b92ffaSHans Petter Selasky 		port->base_lid, port->lmc, rem_nodename,
468*d6b92ffaSHans Petter Selasky 		port->remoteport->node->type == IB_NODE_SWITCH ?
469*d6b92ffaSHans Petter Selasky 		port->remoteport->node->smalid :
470*d6b92ffaSHans Petter Selasky 		port->remoteport->base_lid,
471*d6b92ffaSHans Petter Selasky 		dump_linkwidth_compat(iwidth),
472*d6b92ffaSHans Petter Selasky 		(ispeed != 4 && !espeed) ?
473*d6b92ffaSHans Petter Selasky 			dump_linkspeed_compat(ispeed) :
474*d6b92ffaSHans Petter Selasky 			dump_linkspeedext_compat(espeed, ispeed, fdr10));
475*d6b92ffaSHans Petter Selasky 
476*d6b92ffaSHans Petter Selasky 	if (full_info) {
477*d6b92ffaSHans Petter Selasky 		fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
478*d6b92ffaSHans Petter Selasky 		if (espeed)
479*d6b92ffaSHans Petter Selasky 			fprintf(f, " e=%d", espeed);
480*d6b92ffaSHans Petter Selasky 	}
481*d6b92ffaSHans Petter Selasky 
482*d6b92ffaSHans Petter Selasky 	fprintf(f, "\n");
483*d6b92ffaSHans Petter Selasky 
484*d6b92ffaSHans Petter Selasky 	free(rem_nodename);
485*d6b92ffaSHans Petter Selasky }
486*d6b92ffaSHans Petter Selasky 
487*d6b92ffaSHans Petter Selasky struct iter_user_data {
488*d6b92ffaSHans Petter Selasky 	int group;
489*d6b92ffaSHans Petter Selasky 	int skip_chassis_nodes;
490*d6b92ffaSHans Petter Selasky };
491*d6b92ffaSHans Petter Selasky 
switch_iter_func(ibnd_node_t * node,void * iter_user_data)492*d6b92ffaSHans Petter Selasky static void switch_iter_func(ibnd_node_t * node, void *iter_user_data)
493*d6b92ffaSHans Petter Selasky {
494*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
495*d6b92ffaSHans Petter Selasky 	int p = 0;
496*d6b92ffaSHans Petter Selasky 	struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
497*d6b92ffaSHans Petter Selasky 
498*d6b92ffaSHans Petter Selasky 	DEBUG("SWITCH: node %p\n", node);
499*d6b92ffaSHans Petter Selasky 
500*d6b92ffaSHans Petter Selasky 	/* skip chassis based switches if flagged */
501*d6b92ffaSHans Petter Selasky 	if (data->skip_chassis_nodes && node->chassis
502*d6b92ffaSHans Petter Selasky 	    && node->chassis->chassisnum)
503*d6b92ffaSHans Petter Selasky 		return;
504*d6b92ffaSHans Petter Selasky 
505*d6b92ffaSHans Petter Selasky 	out_switch(node, data->group, NULL, NULL, NULL);
506*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= node->numports; p++) {
507*d6b92ffaSHans Petter Selasky 		port = node->ports[p];
508*d6b92ffaSHans Petter Selasky 		if (port && port->remoteport)
509*d6b92ffaSHans Petter Selasky 			out_switch_port(port, data->group, NULL);
510*d6b92ffaSHans Petter Selasky 	}
511*d6b92ffaSHans Petter Selasky }
512*d6b92ffaSHans Petter Selasky 
ca_iter_func(ibnd_node_t * node,void * iter_user_data)513*d6b92ffaSHans Petter Selasky static void ca_iter_func(ibnd_node_t * node, void *iter_user_data)
514*d6b92ffaSHans Petter Selasky {
515*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
516*d6b92ffaSHans Petter Selasky 	int p = 0;
517*d6b92ffaSHans Petter Selasky 	struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
518*d6b92ffaSHans Petter Selasky 
519*d6b92ffaSHans Petter Selasky 	DEBUG("CA: node %p\n", node);
520*d6b92ffaSHans Petter Selasky 	/* Now, skip chassis based CAs */
521*d6b92ffaSHans Petter Selasky 	if (data->group && node->chassis && node->chassis->chassisnum)
522*d6b92ffaSHans Petter Selasky 		return;
523*d6b92ffaSHans Petter Selasky 	out_ca(node, data->group, NULL, NULL, NULL);
524*d6b92ffaSHans Petter Selasky 
525*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= node->numports; p++) {
526*d6b92ffaSHans Petter Selasky 		port = node->ports[p];
527*d6b92ffaSHans Petter Selasky 		if (port && port->remoteport)
528*d6b92ffaSHans Petter Selasky 			out_ca_port(port, data->group, NULL);
529*d6b92ffaSHans Petter Selasky 	}
530*d6b92ffaSHans Petter Selasky }
531*d6b92ffaSHans Petter Selasky 
router_iter_func(ibnd_node_t * node,void * iter_user_data)532*d6b92ffaSHans Petter Selasky static void router_iter_func(ibnd_node_t * node, void *iter_user_data)
533*d6b92ffaSHans Petter Selasky {
534*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
535*d6b92ffaSHans Petter Selasky 	int p = 0;
536*d6b92ffaSHans Petter Selasky 	struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
537*d6b92ffaSHans Petter Selasky 
538*d6b92ffaSHans Petter Selasky 	DEBUG("RT: node %p\n", node);
539*d6b92ffaSHans Petter Selasky 	/* Now, skip chassis based RTs */
540*d6b92ffaSHans Petter Selasky 	if (data->group && node->chassis && node->chassis->chassisnum)
541*d6b92ffaSHans Petter Selasky 		return;
542*d6b92ffaSHans Petter Selasky 	out_ca(node, data->group, NULL, NULL, NULL);
543*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= node->numports; p++) {
544*d6b92ffaSHans Petter Selasky 		port = node->ports[p];
545*d6b92ffaSHans Petter Selasky 		if (port && port->remoteport)
546*d6b92ffaSHans Petter Selasky 			out_ca_port(port, data->group, NULL);
547*d6b92ffaSHans Petter Selasky 	}
548*d6b92ffaSHans Petter Selasky }
549*d6b92ffaSHans Petter Selasky 
dump_topology(int group,ibnd_fabric_t * fabric)550*d6b92ffaSHans Petter Selasky int dump_topology(int group, ibnd_fabric_t * fabric)
551*d6b92ffaSHans Petter Selasky {
552*d6b92ffaSHans Petter Selasky 	ibnd_node_t *node;
553*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port;
554*d6b92ffaSHans Petter Selasky 	int i = 0, p = 0;
555*d6b92ffaSHans Petter Selasky 	time_t t = time(0);
556*d6b92ffaSHans Petter Selasky 	uint64_t chguid;
557*d6b92ffaSHans Petter Selasky 	char *chname = NULL;
558*d6b92ffaSHans Petter Selasky 	struct iter_user_data iter_user_data;
559*d6b92ffaSHans Petter Selasky 
560*d6b92ffaSHans Petter Selasky 	fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));
561*d6b92ffaSHans Petter Selasky 	if (report_max_hops)
562*d6b92ffaSHans Petter Selasky 		fprintf(f, "# Reported max hops discovered: %u\n"
563*d6b92ffaSHans Petter Selasky 			"# Total MADs used: %u\n",
564*d6b92ffaSHans Petter Selasky 			fabric->maxhops_discovered, fabric->total_mads_used);
565*d6b92ffaSHans Petter Selasky 	fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n",
566*d6b92ffaSHans Petter Selasky 		fabric->from_node->guid,
567*d6b92ffaSHans Petter Selasky 		mad_get_field64(fabric->from_node->info, 0,
568*d6b92ffaSHans Petter Selasky 				IB_NODE_PORT_GUID_F));
569*d6b92ffaSHans Petter Selasky 
570*d6b92ffaSHans Petter Selasky 	/* Make pass on switches */
571*d6b92ffaSHans Petter Selasky 	if (group) {
572*d6b92ffaSHans Petter Selasky 		ibnd_chassis_t *ch = NULL;
573*d6b92ffaSHans Petter Selasky 
574*d6b92ffaSHans Petter Selasky 		/* Chassis based switches first */
575*d6b92ffaSHans Petter Selasky 		for (ch = fabric->chassis; ch; ch = ch->next) {
576*d6b92ffaSHans Petter Selasky 			int n = 0;
577*d6b92ffaSHans Petter Selasky 
578*d6b92ffaSHans Petter Selasky 			if (!ch->chassisnum)
579*d6b92ffaSHans Petter Selasky 				continue;
580*d6b92ffaSHans Petter Selasky 			chguid = out_chassis(fabric, ch->chassisnum);
581*d6b92ffaSHans Petter Selasky 			chname = NULL;
582*d6b92ffaSHans Petter Selasky 			if (ibnd_is_xsigo_guid(chguid)) {
583*d6b92ffaSHans Petter Selasky 				for (node = ch->nodes; node;
584*d6b92ffaSHans Petter Selasky 				     node = node->next_chassis_node) {
585*d6b92ffaSHans Petter Selasky 					if (ibnd_is_xsigo_hca(node->guid)) {
586*d6b92ffaSHans Petter Selasky 						chname = node->nodedesc;
587*d6b92ffaSHans Petter Selasky 						fprintf(f, "Hostname: %s\n",
588*d6b92ffaSHans Petter Selasky 							clean_nodedesc
589*d6b92ffaSHans Petter Selasky 							(node->nodedesc));
590*d6b92ffaSHans Petter Selasky 					}
591*d6b92ffaSHans Petter Selasky 				}
592*d6b92ffaSHans Petter Selasky 			}
593*d6b92ffaSHans Petter Selasky 
594*d6b92ffaSHans Petter Selasky 			fprintf(f, "\n# Spine Nodes");
595*d6b92ffaSHans Petter Selasky 			for (n = 1; n <= SPINES_MAX_NUM; n++) {
596*d6b92ffaSHans Petter Selasky 				if (ch->spinenode[n]) {
597*d6b92ffaSHans Petter Selasky 					out_switch(ch->spinenode[n], group,
598*d6b92ffaSHans Petter Selasky 						   chname, NULL, NULL);
599*d6b92ffaSHans Petter Selasky 					for (p = 1;
600*d6b92ffaSHans Petter Selasky 					     p <= ch->spinenode[n]->numports;
601*d6b92ffaSHans Petter Selasky 					     p++) {
602*d6b92ffaSHans Petter Selasky 						port =
603*d6b92ffaSHans Petter Selasky 						    ch->spinenode[n]->ports[p];
604*d6b92ffaSHans Petter Selasky 						if (port && port->remoteport)
605*d6b92ffaSHans Petter Selasky 							out_switch_port(port,
606*d6b92ffaSHans Petter Selasky 									group,
607*d6b92ffaSHans Petter Selasky 									NULL);
608*d6b92ffaSHans Petter Selasky 					}
609*d6b92ffaSHans Petter Selasky 				}
610*d6b92ffaSHans Petter Selasky 			}
611*d6b92ffaSHans Petter Selasky 			fprintf(f, "\n# Line Nodes");
612*d6b92ffaSHans Petter Selasky 			for (n = 1; n <= LINES_MAX_NUM; n++) {
613*d6b92ffaSHans Petter Selasky 				if (ch->linenode[n]) {
614*d6b92ffaSHans Petter Selasky 					out_switch(ch->linenode[n], group,
615*d6b92ffaSHans Petter Selasky 						   chname, NULL, NULL);
616*d6b92ffaSHans Petter Selasky 					for (p = 1;
617*d6b92ffaSHans Petter Selasky 					     p <= ch->linenode[n]->numports;
618*d6b92ffaSHans Petter Selasky 					     p++) {
619*d6b92ffaSHans Petter Selasky 						port =
620*d6b92ffaSHans Petter Selasky 						    ch->linenode[n]->ports[p];
621*d6b92ffaSHans Petter Selasky 						if (port && port->remoteport)
622*d6b92ffaSHans Petter Selasky 							out_switch_port(port,
623*d6b92ffaSHans Petter Selasky 									group,
624*d6b92ffaSHans Petter Selasky 									NULL);
625*d6b92ffaSHans Petter Selasky 					}
626*d6b92ffaSHans Petter Selasky 				}
627*d6b92ffaSHans Petter Selasky 			}
628*d6b92ffaSHans Petter Selasky 
629*d6b92ffaSHans Petter Selasky 			fprintf(f, "\n# Chassis Switches");
630*d6b92ffaSHans Petter Selasky 			for (node = ch->nodes; node;
631*d6b92ffaSHans Petter Selasky 			     node = node->next_chassis_node) {
632*d6b92ffaSHans Petter Selasky 				if (node->type == IB_NODE_SWITCH) {
633*d6b92ffaSHans Petter Selasky 					out_switch(node, group, chname, NULL,
634*d6b92ffaSHans Petter Selasky 						   NULL);
635*d6b92ffaSHans Petter Selasky 					for (p = 1; p <= node->numports; p++) {
636*d6b92ffaSHans Petter Selasky 						port = node->ports[p];
637*d6b92ffaSHans Petter Selasky 						if (port && port->remoteport)
638*d6b92ffaSHans Petter Selasky 							out_switch_port(port,
639*d6b92ffaSHans Petter Selasky 									group,
640*d6b92ffaSHans Petter Selasky 									NULL);
641*d6b92ffaSHans Petter Selasky 					}
642*d6b92ffaSHans Petter Selasky 				}
643*d6b92ffaSHans Petter Selasky 
644*d6b92ffaSHans Petter Selasky 			}
645*d6b92ffaSHans Petter Selasky 
646*d6b92ffaSHans Petter Selasky 			fprintf(f, "\n# Chassis CAs");
647*d6b92ffaSHans Petter Selasky 			for (node = ch->nodes; node;
648*d6b92ffaSHans Petter Selasky 			     node = node->next_chassis_node) {
649*d6b92ffaSHans Petter Selasky 				if (node->type == IB_NODE_CA) {
650*d6b92ffaSHans Petter Selasky 					out_ca(node, group, chname, NULL, NULL);
651*d6b92ffaSHans Petter Selasky 					for (p = 1; p <= node->numports; p++) {
652*d6b92ffaSHans Petter Selasky 						port = node->ports[p];
653*d6b92ffaSHans Petter Selasky 						if (port && port->remoteport)
654*d6b92ffaSHans Petter Selasky 							out_ca_port(port, group,
655*d6b92ffaSHans Petter Selasky 								    NULL);
656*d6b92ffaSHans Petter Selasky 					}
657*d6b92ffaSHans Petter Selasky 				}
658*d6b92ffaSHans Petter Selasky 			}
659*d6b92ffaSHans Petter Selasky 
660*d6b92ffaSHans Petter Selasky 		}
661*d6b92ffaSHans Petter Selasky 
662*d6b92ffaSHans Petter Selasky 	} else {		/* !group */
663*d6b92ffaSHans Petter Selasky 		iter_user_data.group = group;
664*d6b92ffaSHans Petter Selasky 		iter_user_data.skip_chassis_nodes = 0;
665*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
666*d6b92ffaSHans Petter Selasky 				     &iter_user_data);
667*d6b92ffaSHans Petter Selasky 	}
668*d6b92ffaSHans Petter Selasky 
669*d6b92ffaSHans Petter Selasky 	chname = NULL;
670*d6b92ffaSHans Petter Selasky 	if (group) {
671*d6b92ffaSHans Petter Selasky 		iter_user_data.group = group;
672*d6b92ffaSHans Petter Selasky 		iter_user_data.skip_chassis_nodes = 1;
673*d6b92ffaSHans Petter Selasky 
674*d6b92ffaSHans Petter Selasky 		fprintf(f, "\nNon-Chassis Nodes\n");
675*d6b92ffaSHans Petter Selasky 
676*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
677*d6b92ffaSHans Petter Selasky 				     &iter_user_data);
678*d6b92ffaSHans Petter Selasky 	}
679*d6b92ffaSHans Petter Selasky 
680*d6b92ffaSHans Petter Selasky 	iter_user_data.group = group;
681*d6b92ffaSHans Petter Selasky 	iter_user_data.skip_chassis_nodes = 0;
682*d6b92ffaSHans Petter Selasky 	/* Make pass on CAs */
683*d6b92ffaSHans Petter Selasky 	ibnd_iter_nodes_type(fabric, ca_iter_func, IB_NODE_CA, &iter_user_data);
684*d6b92ffaSHans Petter Selasky 
685*d6b92ffaSHans Petter Selasky 	/* Make pass on routers */
686*d6b92ffaSHans Petter Selasky 	ibnd_iter_nodes_type(fabric, router_iter_func, IB_NODE_ROUTER,
687*d6b92ffaSHans Petter Selasky 			     &iter_user_data);
688*d6b92ffaSHans Petter Selasky 
689*d6b92ffaSHans Petter Selasky 	return i;
690*d6b92ffaSHans Petter Selasky }
691*d6b92ffaSHans Petter Selasky 
dump_ports_report(ibnd_node_t * node,void * user_data)692*d6b92ffaSHans Petter Selasky void dump_ports_report(ibnd_node_t * node, void *user_data)
693*d6b92ffaSHans Petter Selasky {
694*d6b92ffaSHans Petter Selasky 	int p = 0;
695*d6b92ffaSHans Petter Selasky 	ibnd_port_t *port = NULL;
696*d6b92ffaSHans Petter Selasky 	char *nodename = NULL;
697*d6b92ffaSHans Petter Selasky 	char *rem_nodename = NULL;
698*d6b92ffaSHans Petter Selasky 
699*d6b92ffaSHans Petter Selasky 	/* for each port */
700*d6b92ffaSHans Petter Selasky 	for (p = node->numports, port = node->ports[p]; p > 0;
701*d6b92ffaSHans Petter Selasky 	     port = node->ports[--p]) {
702*d6b92ffaSHans Petter Selasky 		uint32_t iwidth, ispeed, fdr10, espeed, cap_mask;
703*d6b92ffaSHans Petter Selasky 		uint8_t *info = NULL;
704*d6b92ffaSHans Petter Selasky 		if (port == NULL)
705*d6b92ffaSHans Petter Selasky 			continue;
706*d6b92ffaSHans Petter Selasky 		iwidth =
707*d6b92ffaSHans Petter Selasky 		    mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
708*d6b92ffaSHans Petter Selasky 		ispeed =
709*d6b92ffaSHans Petter Selasky 		    mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
710*d6b92ffaSHans Petter Selasky 		if (port->node->type == IB_NODE_SWITCH) {
711*d6b92ffaSHans Petter Selasky 			if (port->node->ports[0])
712*d6b92ffaSHans Petter Selasky 				info = (uint8_t *)&port->node->ports[0]->info;
713*d6b92ffaSHans Petter Selasky 		}
714*d6b92ffaSHans Petter Selasky 		else
715*d6b92ffaSHans Petter Selasky 			info = (uint8_t *)&port->info;
716*d6b92ffaSHans Petter Selasky 		if (info) {
717*d6b92ffaSHans Petter Selasky 			cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
718*d6b92ffaSHans Petter Selasky 			if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
719*d6b92ffaSHans Petter Selasky 				espeed = mad_get_field(port->info, 0,
720*d6b92ffaSHans Petter Selasky 						       IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
721*d6b92ffaSHans Petter Selasky 			else
722*d6b92ffaSHans Petter Selasky 				espeed = 0;
723*d6b92ffaSHans Petter Selasky 		} else {
724*d6b92ffaSHans Petter Selasky 			ispeed = 0;
725*d6b92ffaSHans Petter Selasky 			iwidth = 0;
726*d6b92ffaSHans Petter Selasky 			espeed = 0;
727*d6b92ffaSHans Petter Selasky 		}
728*d6b92ffaSHans Petter Selasky 		fdr10 = mad_get_field(port->ext_info, 0,
729*d6b92ffaSHans Petter Selasky 				      IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
730*d6b92ffaSHans Petter Selasky 		nodename = remap_node_name(node_name_map,
731*d6b92ffaSHans Petter Selasky 					   port->node->guid,
732*d6b92ffaSHans Petter Selasky 					   port->node->nodedesc);
733*d6b92ffaSHans Petter Selasky 		fprintf(stdout, "%2s %5d %2d 0x%016" PRIx64 " %s %s",
734*d6b92ffaSHans Petter Selasky 			ports_nt_str_compat(node),
735*d6b92ffaSHans Petter Selasky 			node->type ==
736*d6b92ffaSHans Petter Selasky 			IB_NODE_SWITCH ? node->smalid : port->base_lid,
737*d6b92ffaSHans Petter Selasky 			port->portnum, port->guid,
738*d6b92ffaSHans Petter Selasky 			dump_linkwidth_compat(iwidth),
739*d6b92ffaSHans Petter Selasky 			(ispeed != 4 && !espeed) ?
740*d6b92ffaSHans Petter Selasky 				dump_linkspeed_compat(ispeed) :
741*d6b92ffaSHans Petter Selasky 				dump_linkspeedext_compat(espeed, ispeed, fdr10));
742*d6b92ffaSHans Petter Selasky 		if (port->remoteport) {
743*d6b92ffaSHans Petter Selasky 			rem_nodename = remap_node_name(node_name_map,
744*d6b92ffaSHans Petter Selasky 					      port->remoteport->node->guid,
745*d6b92ffaSHans Petter Selasky 					      port->remoteport->node->nodedesc);
746*d6b92ffaSHans Petter Selasky 			fprintf(stdout,
747*d6b92ffaSHans Petter Selasky 				" - %2s %5d %2d 0x%016" PRIx64
748*d6b92ffaSHans Petter Selasky 				" ( '%s' - '%s' )\n",
749*d6b92ffaSHans Petter Selasky 				ports_nt_str_compat(port->remoteport->node),
750*d6b92ffaSHans Petter Selasky 				port->remoteport->node->type == IB_NODE_SWITCH ?
751*d6b92ffaSHans Petter Selasky 				port->remoteport->node->smalid :
752*d6b92ffaSHans Petter Selasky 				port->remoteport->base_lid,
753*d6b92ffaSHans Petter Selasky 				port->remoteport->portnum,
754*d6b92ffaSHans Petter Selasky 				port->remoteport->guid, nodename, rem_nodename);
755*d6b92ffaSHans Petter Selasky 			free(rem_nodename);
756*d6b92ffaSHans Petter Selasky 		} else
757*d6b92ffaSHans Petter Selasky 			fprintf(stdout, "%36s'%s'\n", "", nodename);
758*d6b92ffaSHans Petter Selasky 
759*d6b92ffaSHans Petter Selasky 		free(nodename);
760*d6b92ffaSHans Petter Selasky 	}
761*d6b92ffaSHans Petter Selasky }
762*d6b92ffaSHans Petter Selasky 
763*d6b92ffaSHans Petter Selasky struct iter_diff_data {
764*d6b92ffaSHans Petter Selasky 	uint32_t diff_flags;
765*d6b92ffaSHans Petter Selasky 	ibnd_fabric_t *fabric1;
766*d6b92ffaSHans Petter Selasky 	ibnd_fabric_t *fabric2;
767*d6b92ffaSHans Petter Selasky 	char *fabric1_prefix;
768*d6b92ffaSHans Petter Selasky 	char *fabric2_prefix;
769*d6b92ffaSHans Petter Selasky 	void (*out_header) (ibnd_node_t *, int, char *, char *, char *);
770*d6b92ffaSHans Petter Selasky 	void (*out_header_detail) (ibnd_node_t *, char *);
771*d6b92ffaSHans Petter Selasky 	void (*out_port) (ibnd_port_t *, int, char *);
772*d6b92ffaSHans Petter Selasky };
773*d6b92ffaSHans Petter Selasky 
diff_iter_out_header(ibnd_node_t * node,struct iter_diff_data * data,int * out_header_flag)774*d6b92ffaSHans Petter Selasky static void diff_iter_out_header(ibnd_node_t * node,
775*d6b92ffaSHans Petter Selasky 				 struct iter_diff_data *data,
776*d6b92ffaSHans Petter Selasky 				 int *out_header_flag)
777*d6b92ffaSHans Petter Selasky {
778*d6b92ffaSHans Petter Selasky 	if (!(*out_header_flag)) {
779*d6b92ffaSHans Petter Selasky 		(*data->out_header) (node, 0, NULL, NULL, NULL);
780*d6b92ffaSHans Petter Selasky 		(*out_header_flag)++;
781*d6b92ffaSHans Petter Selasky 	}
782*d6b92ffaSHans Petter Selasky }
783*d6b92ffaSHans Petter Selasky 
diff_ports(ibnd_node_t * fabric1_node,ibnd_node_t * fabric2_node,int * out_header_flag,struct iter_diff_data * data)784*d6b92ffaSHans Petter Selasky static void diff_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
785*d6b92ffaSHans Petter Selasky 		       int *out_header_flag, struct iter_diff_data *data)
786*d6b92ffaSHans Petter Selasky {
787*d6b92ffaSHans Petter Selasky 	ibnd_port_t *fabric1_port;
788*d6b92ffaSHans Petter Selasky 	ibnd_port_t *fabric2_port;
789*d6b92ffaSHans Petter Selasky 	int p;
790*d6b92ffaSHans Petter Selasky 
791*d6b92ffaSHans Petter Selasky 	for (p = 1; p <= fabric1_node->numports; p++) {
792*d6b92ffaSHans Petter Selasky 		int fabric1_out = 0, fabric2_out = 0;
793*d6b92ffaSHans Petter Selasky 
794*d6b92ffaSHans Petter Selasky 		fabric1_port = fabric1_node->ports[p];
795*d6b92ffaSHans Petter Selasky 		fabric2_port = fabric2_node->ports[p];
796*d6b92ffaSHans Petter Selasky 
797*d6b92ffaSHans Petter Selasky 		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
798*d6b92ffaSHans Petter Selasky 			if ((fabric1_port && !fabric2_port)
799*d6b92ffaSHans Petter Selasky 			    || ((fabric1_port && fabric2_port)
800*d6b92ffaSHans Petter Selasky 				&& (fabric1_port->remoteport
801*d6b92ffaSHans Petter Selasky 				    && !fabric2_port->remoteport)))
802*d6b92ffaSHans Petter Selasky 				fabric1_out++;
803*d6b92ffaSHans Petter Selasky 			else if ((!fabric1_port && fabric2_port)
804*d6b92ffaSHans Petter Selasky 				 || ((fabric1_port && fabric2_port)
805*d6b92ffaSHans Petter Selasky 				     && (!fabric1_port->remoteport
806*d6b92ffaSHans Petter Selasky 					 && fabric2_port->remoteport)))
807*d6b92ffaSHans Petter Selasky 				fabric2_out++;
808*d6b92ffaSHans Petter Selasky 			else if ((fabric1_port && fabric2_port)
809*d6b92ffaSHans Petter Selasky 				 && ((fabric1_port->guid != fabric2_port->guid)
810*d6b92ffaSHans Petter Selasky 				     ||
811*d6b92ffaSHans Petter Selasky 				     ((fabric1_port->remoteport
812*d6b92ffaSHans Petter Selasky 				       && fabric2_port->remoteport)
813*d6b92ffaSHans Petter Selasky 				      && (fabric1_port->remoteport->guid !=
814*d6b92ffaSHans Petter Selasky 					  fabric2_port->remoteport->guid)))) {
815*d6b92ffaSHans Petter Selasky 				fabric1_out++;
816*d6b92ffaSHans Petter Selasky 				fabric2_out++;
817*d6b92ffaSHans Petter Selasky 			}
818*d6b92ffaSHans Petter Selasky 		}
819*d6b92ffaSHans Petter Selasky 
820*d6b92ffaSHans Petter Selasky 		if ((data->diff_flags & DIFF_FLAG_LID)
821*d6b92ffaSHans Petter Selasky 		    && fabric1_port && fabric2_port
822*d6b92ffaSHans Petter Selasky 		    && fabric1_port->base_lid != fabric2_port->base_lid) {
823*d6b92ffaSHans Petter Selasky 			fabric1_out++;
824*d6b92ffaSHans Petter Selasky 			fabric2_out++;
825*d6b92ffaSHans Petter Selasky 		}
826*d6b92ffaSHans Petter Selasky 
827*d6b92ffaSHans Petter Selasky 		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
828*d6b92ffaSHans Petter Selasky 		    && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
829*d6b92ffaSHans Petter Selasky 		    && fabric1_port && fabric2_port
830*d6b92ffaSHans Petter Selasky 		    && fabric1_port->remoteport && fabric2_port->remoteport
831*d6b92ffaSHans Petter Selasky 		    && memcmp(fabric1_port->remoteport->node->nodedesc,
832*d6b92ffaSHans Petter Selasky 			      fabric2_port->remoteport->node->nodedesc,
833*d6b92ffaSHans Petter Selasky 			      IB_SMP_DATA_SIZE)) {
834*d6b92ffaSHans Petter Selasky 			fabric1_out++;
835*d6b92ffaSHans Petter Selasky 			fabric2_out++;
836*d6b92ffaSHans Petter Selasky 		}
837*d6b92ffaSHans Petter Selasky 
838*d6b92ffaSHans Petter Selasky 		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
839*d6b92ffaSHans Petter Selasky 		    && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
840*d6b92ffaSHans Petter Selasky 		    && fabric1_port && fabric2_port
841*d6b92ffaSHans Petter Selasky 		    && fabric1_port->remoteport && fabric2_port->remoteport
842*d6b92ffaSHans Petter Selasky 		    && memcmp(fabric1_port->remoteport->node->nodedesc,
843*d6b92ffaSHans Petter Selasky 			      fabric2_port->remoteport->node->nodedesc,
844*d6b92ffaSHans Petter Selasky 			      IB_SMP_DATA_SIZE)) {
845*d6b92ffaSHans Petter Selasky 			fabric1_out++;
846*d6b92ffaSHans Petter Selasky 			fabric2_out++;
847*d6b92ffaSHans Petter Selasky 		}
848*d6b92ffaSHans Petter Selasky 
849*d6b92ffaSHans Petter Selasky 		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
850*d6b92ffaSHans Petter Selasky 		    && data->diff_flags & DIFF_FLAG_LID
851*d6b92ffaSHans Petter Selasky 		    && fabric1_port && fabric2_port
852*d6b92ffaSHans Petter Selasky 		    && fabric1_port->remoteport && fabric2_port->remoteport
853*d6b92ffaSHans Petter Selasky 		    && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid) {
854*d6b92ffaSHans Petter Selasky 			fabric1_out++;
855*d6b92ffaSHans Petter Selasky 			fabric2_out++;
856*d6b92ffaSHans Petter Selasky 		}
857*d6b92ffaSHans Petter Selasky 
858*d6b92ffaSHans Petter Selasky 		if (fabric1_out) {
859*d6b92ffaSHans Petter Selasky 			diff_iter_out_header(fabric1_node, data,
860*d6b92ffaSHans Petter Selasky 					     out_header_flag);
861*d6b92ffaSHans Petter Selasky 			(*data->out_port) (fabric1_port, 0,
862*d6b92ffaSHans Petter Selasky 					   data->fabric1_prefix);
863*d6b92ffaSHans Petter Selasky 		}
864*d6b92ffaSHans Petter Selasky 		if (fabric2_out) {
865*d6b92ffaSHans Petter Selasky 			diff_iter_out_header(fabric1_node, data,
866*d6b92ffaSHans Petter Selasky 					     out_header_flag);
867*d6b92ffaSHans Petter Selasky 			(*data->out_port) (fabric2_port, 0,
868*d6b92ffaSHans Petter Selasky 					   data->fabric2_prefix);
869*d6b92ffaSHans Petter Selasky 		}
870*d6b92ffaSHans Petter Selasky 	}
871*d6b92ffaSHans Petter Selasky }
872*d6b92ffaSHans Petter Selasky 
diff_iter_func(ibnd_node_t * fabric1_node,void * iter_user_data)873*d6b92ffaSHans Petter Selasky static void diff_iter_func(ibnd_node_t * fabric1_node, void *iter_user_data)
874*d6b92ffaSHans Petter Selasky {
875*d6b92ffaSHans Petter Selasky 	struct iter_diff_data *data = iter_user_data;
876*d6b92ffaSHans Petter Selasky 	ibnd_node_t *fabric2_node;
877*d6b92ffaSHans Petter Selasky 	ibnd_port_t *fabric1_port;
878*d6b92ffaSHans Petter Selasky 	int p;
879*d6b92ffaSHans Petter Selasky 
880*d6b92ffaSHans Petter Selasky 	DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
881*d6b92ffaSHans Petter Selasky 
882*d6b92ffaSHans Petter Selasky 	fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
883*d6b92ffaSHans Petter Selasky 	if (!fabric2_node) {
884*d6b92ffaSHans Petter Selasky 		(*data->out_header) (fabric1_node, 0, NULL,
885*d6b92ffaSHans Petter Selasky 				     data->fabric1_prefix,
886*d6b92ffaSHans Petter Selasky 				     data->fabric1_prefix);
887*d6b92ffaSHans Petter Selasky 		for (p = 1; p <= fabric1_node->numports; p++) {
888*d6b92ffaSHans Petter Selasky 			fabric1_port = fabric1_node->ports[p];
889*d6b92ffaSHans Petter Selasky 			if (fabric1_port && fabric1_port->remoteport)
890*d6b92ffaSHans Petter Selasky 				(*data->out_port) (fabric1_port, 0,
891*d6b92ffaSHans Petter Selasky 						   data->fabric1_prefix);
892*d6b92ffaSHans Petter Selasky 		}
893*d6b92ffaSHans Petter Selasky 	} else if (data->diff_flags &
894*d6b92ffaSHans Petter Selasky 		   (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_LID
895*d6b92ffaSHans Petter Selasky 		    | DIFF_FLAG_NODE_DESCRIPTION)) {
896*d6b92ffaSHans Petter Selasky 		int out_header_flag = 0;
897*d6b92ffaSHans Petter Selasky 
898*d6b92ffaSHans Petter Selasky 		if ((data->diff_flags & DIFF_FLAG_LID
899*d6b92ffaSHans Petter Selasky 		     && fabric1_node->smalid != fabric2_node->smalid) ||
900*d6b92ffaSHans Petter Selasky 		    (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
901*d6b92ffaSHans Petter Selasky 		     && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
902*d6b92ffaSHans Petter Selasky 			       IB_SMP_DATA_SIZE))) {
903*d6b92ffaSHans Petter Selasky 			(*data->out_header) (fabric1_node, 0, NULL, NULL,
904*d6b92ffaSHans Petter Selasky 					     data->fabric1_prefix);
905*d6b92ffaSHans Petter Selasky 			(*data->out_header_detail) (fabric2_node,
906*d6b92ffaSHans Petter Selasky 						    data->fabric2_prefix);
907*d6b92ffaSHans Petter Selasky 			fprintf(f, "\n");
908*d6b92ffaSHans Petter Selasky 			out_header_flag++;
909*d6b92ffaSHans Petter Selasky 		}
910*d6b92ffaSHans Petter Selasky 
911*d6b92ffaSHans Petter Selasky 		if (fabric1_node->numports != fabric2_node->numports) {
912*d6b92ffaSHans Petter Selasky 			diff_iter_out_header(fabric1_node, data,
913*d6b92ffaSHans Petter Selasky 					     &out_header_flag);
914*d6b92ffaSHans Petter Selasky 			fprintf(f, "%snumports = %d\n", data->fabric1_prefix,
915*d6b92ffaSHans Petter Selasky 				fabric1_node->numports);
916*d6b92ffaSHans Petter Selasky 			fprintf(f, "%snumports = %d\n", data->fabric2_prefix,
917*d6b92ffaSHans Petter Selasky 				fabric2_node->numports);
918*d6b92ffaSHans Petter Selasky 			return;
919*d6b92ffaSHans Petter Selasky 		}
920*d6b92ffaSHans Petter Selasky 
921*d6b92ffaSHans Petter Selasky 		if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
922*d6b92ffaSHans Petter Selasky 		    || data->diff_flags & DIFF_FLAG_LID)
923*d6b92ffaSHans Petter Selasky 			diff_ports(fabric1_node, fabric2_node, &out_header_flag,
924*d6b92ffaSHans Petter Selasky 				   data);
925*d6b92ffaSHans Petter Selasky 	}
926*d6b92ffaSHans Petter Selasky }
927*d6b92ffaSHans Petter Selasky 
diff_common(ibnd_fabric_t * orig_fabric,ibnd_fabric_t * new_fabric,int node_type,uint32_t diff_flags,void (* out_header)(ibnd_node_t *,int,char *,char *,char *),void (* out_header_detail)(ibnd_node_t *,char *),void (* out_port)(ibnd_port_t *,int,char *))928*d6b92ffaSHans Petter Selasky static int diff_common(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric,
929*d6b92ffaSHans Petter Selasky 		       int node_type, uint32_t diff_flags,
930*d6b92ffaSHans Petter Selasky 		       void (*out_header) (ibnd_node_t *, int, char *, char *,
931*d6b92ffaSHans Petter Selasky 					   char *),
932*d6b92ffaSHans Petter Selasky 		       void (*out_header_detail) (ibnd_node_t *, char *),
933*d6b92ffaSHans Petter Selasky 		       void (*out_port) (ibnd_port_t *, int, char *))
934*d6b92ffaSHans Petter Selasky {
935*d6b92ffaSHans Petter Selasky 	struct iter_diff_data iter_diff_data;
936*d6b92ffaSHans Petter Selasky 
937*d6b92ffaSHans Petter Selasky 	iter_diff_data.diff_flags = diff_flags;
938*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric1 = orig_fabric;
939*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric2 = new_fabric;
940*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric1_prefix = "< ";
941*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric2_prefix = "> ";
942*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_header = out_header;
943*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_header_detail = out_header_detail;
944*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_port = out_port;
945*d6b92ffaSHans Petter Selasky 	ibnd_iter_nodes_type(orig_fabric, diff_iter_func, node_type,
946*d6b92ffaSHans Petter Selasky 			     &iter_diff_data);
947*d6b92ffaSHans Petter Selasky 
948*d6b92ffaSHans Petter Selasky 	/* Do opposite diff to find existence of node types
949*d6b92ffaSHans Petter Selasky 	 * in new_fabric but not in orig_fabric.
950*d6b92ffaSHans Petter Selasky 	 *
951*d6b92ffaSHans Petter Selasky 	 * In this diff, we don't need to check port connections,
952*d6b92ffaSHans Petter Selasky 	 * lids, or node descriptions since it has already been
953*d6b92ffaSHans Petter Selasky 	 * done (i.e. checks are only done when guid exists on both
954*d6b92ffaSHans Petter Selasky 	 * orig and new).
955*d6b92ffaSHans Petter Selasky 	 */
956*d6b92ffaSHans Petter Selasky 	iter_diff_data.diff_flags = diff_flags & ~DIFF_FLAG_PORT_CONNECTION;
957*d6b92ffaSHans Petter Selasky 	iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
958*d6b92ffaSHans Petter Selasky 	iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
959*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric1 = new_fabric;
960*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric2 = orig_fabric;
961*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric1_prefix = "> ";
962*d6b92ffaSHans Petter Selasky 	iter_diff_data.fabric2_prefix = "< ";
963*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_header = out_header;
964*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_header_detail = out_header_detail;
965*d6b92ffaSHans Petter Selasky 	iter_diff_data.out_port = out_port;
966*d6b92ffaSHans Petter Selasky 	ibnd_iter_nodes_type(new_fabric, diff_iter_func, node_type,
967*d6b92ffaSHans Petter Selasky 			     &iter_diff_data);
968*d6b92ffaSHans Petter Selasky 
969*d6b92ffaSHans Petter Selasky 	return 0;
970*d6b92ffaSHans Petter Selasky }
971*d6b92ffaSHans Petter Selasky 
diff(ibnd_fabric_t * orig_fabric,ibnd_fabric_t * new_fabric)972*d6b92ffaSHans Petter Selasky int diff(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric)
973*d6b92ffaSHans Petter Selasky {
974*d6b92ffaSHans Petter Selasky 	if (diffcheck_flags & DIFF_FLAG_SWITCH)
975*d6b92ffaSHans Petter Selasky 		diff_common(orig_fabric, new_fabric, IB_NODE_SWITCH,
976*d6b92ffaSHans Petter Selasky 			    diffcheck_flags, out_switch, out_switch_detail,
977*d6b92ffaSHans Petter Selasky 			    out_switch_port);
978*d6b92ffaSHans Petter Selasky 
979*d6b92ffaSHans Petter Selasky 	if (diffcheck_flags & DIFF_FLAG_CA)
980*d6b92ffaSHans Petter Selasky 		diff_common(orig_fabric, new_fabric, IB_NODE_CA,
981*d6b92ffaSHans Petter Selasky 			    diffcheck_flags, out_ca, out_ca_detail,
982*d6b92ffaSHans Petter Selasky 			    out_ca_port);
983*d6b92ffaSHans Petter Selasky 
984*d6b92ffaSHans Petter Selasky 	if (diffcheck_flags & DIFF_FLAG_ROUTER)
985*d6b92ffaSHans Petter Selasky 		diff_common(orig_fabric, new_fabric, IB_NODE_ROUTER,
986*d6b92ffaSHans Petter Selasky 			    diffcheck_flags, out_ca, out_ca_detail,
987*d6b92ffaSHans Petter Selasky 			    out_ca_port);
988*d6b92ffaSHans Petter Selasky 
989*d6b92ffaSHans Petter Selasky 	return 0;
990*d6b92ffaSHans Petter Selasky }
991*d6b92ffaSHans Petter Selasky 
992*d6b92ffaSHans Petter Selasky static int list, group, ports_report;
993*d6b92ffaSHans Petter Selasky 
process_opt(void * context,int ch,char * optarg)994*d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
995*d6b92ffaSHans Petter Selasky {
996*d6b92ffaSHans Petter Selasky 	struct ibnd_config *cfg = context;
997*d6b92ffaSHans Petter Selasky 	char *p;
998*d6b92ffaSHans Petter Selasky 
999*d6b92ffaSHans Petter Selasky 	switch (ch) {
1000*d6b92ffaSHans Petter Selasky 	case 1:
1001*d6b92ffaSHans Petter Selasky 		node_name_map_file = strdup(optarg);
1002*d6b92ffaSHans Petter Selasky 		break;
1003*d6b92ffaSHans Petter Selasky 	case 2:
1004*d6b92ffaSHans Petter Selasky 		cache_file = strdup(optarg);
1005*d6b92ffaSHans Petter Selasky 		break;
1006*d6b92ffaSHans Petter Selasky 	case 3:
1007*d6b92ffaSHans Petter Selasky 		load_cache_file = strdup(optarg);
1008*d6b92ffaSHans Petter Selasky 		break;
1009*d6b92ffaSHans Petter Selasky 	case 4:
1010*d6b92ffaSHans Petter Selasky 		diff_cache_file = strdup(optarg);
1011*d6b92ffaSHans Petter Selasky 		break;
1012*d6b92ffaSHans Petter Selasky 	case 5:
1013*d6b92ffaSHans Petter Selasky 		diffcheck_flags = 0;
1014*d6b92ffaSHans Petter Selasky 		p = strtok(optarg, ",");
1015*d6b92ffaSHans Petter Selasky 		while (p) {
1016*d6b92ffaSHans Petter Selasky 			if (!strcasecmp(p, "sw"))
1017*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_SWITCH;
1018*d6b92ffaSHans Petter Selasky 			else if (!strcasecmp(p, "ca"))
1019*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_CA;
1020*d6b92ffaSHans Petter Selasky 			else if (!strcasecmp(p, "router"))
1021*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_ROUTER;
1022*d6b92ffaSHans Petter Selasky 			else if (!strcasecmp(p, "port"))
1023*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
1024*d6b92ffaSHans Petter Selasky 			else if (!strcasecmp(p, "lid"))
1025*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_LID;
1026*d6b92ffaSHans Petter Selasky 			else if (!strcasecmp(p, "nodedesc"))
1027*d6b92ffaSHans Petter Selasky 				diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
1028*d6b92ffaSHans Petter Selasky 			else {
1029*d6b92ffaSHans Petter Selasky 				fprintf(stderr, "invalid diff check key: %s\n",
1030*d6b92ffaSHans Petter Selasky 					p);
1031*d6b92ffaSHans Petter Selasky 				return -1;
1032*d6b92ffaSHans Petter Selasky 			}
1033*d6b92ffaSHans Petter Selasky 			p = strtok(NULL, ",");
1034*d6b92ffaSHans Petter Selasky 		}
1035*d6b92ffaSHans Petter Selasky 		break;
1036*d6b92ffaSHans Petter Selasky 	case 's':
1037*d6b92ffaSHans Petter Selasky 		cfg->show_progress = 1;
1038*d6b92ffaSHans Petter Selasky 		break;
1039*d6b92ffaSHans Petter Selasky 	case 'f':
1040*d6b92ffaSHans Petter Selasky 		full_info = 1;
1041*d6b92ffaSHans Petter Selasky 		break;
1042*d6b92ffaSHans Petter Selasky 	case 'l':
1043*d6b92ffaSHans Petter Selasky 		list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
1044*d6b92ffaSHans Petter Selasky 		break;
1045*d6b92ffaSHans Petter Selasky 	case 'g':
1046*d6b92ffaSHans Petter Selasky 		group = 1;
1047*d6b92ffaSHans Petter Selasky 		break;
1048*d6b92ffaSHans Petter Selasky 	case 'S':
1049*d6b92ffaSHans Petter Selasky 		list = LIST_SWITCH_NODE;
1050*d6b92ffaSHans Petter Selasky 		break;
1051*d6b92ffaSHans Petter Selasky 	case 'H':
1052*d6b92ffaSHans Petter Selasky 		list = LIST_CA_NODE;
1053*d6b92ffaSHans Petter Selasky 		break;
1054*d6b92ffaSHans Petter Selasky 	case 'R':
1055*d6b92ffaSHans Petter Selasky 		list = LIST_ROUTER_NODE;
1056*d6b92ffaSHans Petter Selasky 		break;
1057*d6b92ffaSHans Petter Selasky 	case 'p':
1058*d6b92ffaSHans Petter Selasky 		ports_report = 1;
1059*d6b92ffaSHans Petter Selasky 		break;
1060*d6b92ffaSHans Petter Selasky 	case 'm':
1061*d6b92ffaSHans Petter Selasky 		report_max_hops = 1;
1062*d6b92ffaSHans Petter Selasky 		break;
1063*d6b92ffaSHans Petter Selasky 	case 'o':
1064*d6b92ffaSHans Petter Selasky 		cfg->max_smps = strtoul(optarg, NULL, 0);
1065*d6b92ffaSHans Petter Selasky 		break;
1066*d6b92ffaSHans Petter Selasky 	default:
1067*d6b92ffaSHans Petter Selasky 		return -1;
1068*d6b92ffaSHans Petter Selasky 	}
1069*d6b92ffaSHans Petter Selasky 
1070*d6b92ffaSHans Petter Selasky 	return 0;
1071*d6b92ffaSHans Petter Selasky }
1072*d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)1073*d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
1074*d6b92ffaSHans Petter Selasky {
1075*d6b92ffaSHans Petter Selasky 	struct ibnd_config config = { 0 };
1076*d6b92ffaSHans Petter Selasky 	ibnd_fabric_t *fabric = NULL;
1077*d6b92ffaSHans Petter Selasky 	ibnd_fabric_t *diff_fabric = NULL;
1078*d6b92ffaSHans Petter Selasky 
1079*d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
1080*d6b92ffaSHans Petter Selasky 		{"full", 'f', 0, NULL, "show full information (ports' speed and width, vlcap)"},
1081*d6b92ffaSHans Petter Selasky 		{"show", 's', 0, NULL, "show more information"},
1082*d6b92ffaSHans Petter Selasky 		{"list", 'l', 0, NULL, "list of connected nodes"},
1083*d6b92ffaSHans Petter Selasky 		{"grouping", 'g', 0, NULL, "show grouping"},
1084*d6b92ffaSHans Petter Selasky 		{"Hca_list", 'H', 0, NULL, "list of connected CAs"},
1085*d6b92ffaSHans Petter Selasky 		{"Switch_list", 'S', 0, NULL, "list of connected switches"},
1086*d6b92ffaSHans Petter Selasky 		{"Router_list", 'R', 0, NULL, "list of connected routers"},
1087*d6b92ffaSHans Petter Selasky 		{"node-name-map", 1, 1, "<file>", "node name map file"},
1088*d6b92ffaSHans Petter Selasky 		{"cache", 2, 1, "<file>",
1089*d6b92ffaSHans Petter Selasky 		 "filename to cache ibnetdiscover data to"},
1090*d6b92ffaSHans Petter Selasky 		{"load-cache", 3, 1, "<file>",
1091*d6b92ffaSHans Petter Selasky 		 "filename of ibnetdiscover cache to load"},
1092*d6b92ffaSHans Petter Selasky 		{"diff", 4, 1, "<file>",
1093*d6b92ffaSHans Petter Selasky 		 "filename of ibnetdiscover cache to diff"},
1094*d6b92ffaSHans Petter Selasky 		{"diffcheck", 5, 1, "<key(s)>",
1095*d6b92ffaSHans Petter Selasky 		 "specify checks to execute for --diff"},
1096*d6b92ffaSHans Petter Selasky 		{"ports", 'p', 0, NULL, "obtain a ports report"},
1097*d6b92ffaSHans Petter Selasky 		{"max_hops", 'm', 0, NULL,
1098*d6b92ffaSHans Petter Selasky 		 "report max hops discovered by the library"},
1099*d6b92ffaSHans Petter Selasky 		{"outstanding_smps", 'o', 1, NULL,
1100*d6b92ffaSHans Petter Selasky 		 "specify the number of outstanding SMP's which should be "
1101*d6b92ffaSHans Petter Selasky 		 "issued during the scan"},
1102*d6b92ffaSHans Petter Selasky 		{0}
1103*d6b92ffaSHans Petter Selasky 	};
1104*d6b92ffaSHans Petter Selasky 	char usage_args[] = "[topology-file]";
1105*d6b92ffaSHans Petter Selasky 
1106*d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, &config, "DGKLs", opts, process_opt,
1107*d6b92ffaSHans Petter Selasky 			    usage_args, NULL);
1108*d6b92ffaSHans Petter Selasky 
1109*d6b92ffaSHans Petter Selasky 	f = stdout;
1110*d6b92ffaSHans Petter Selasky 
1111*d6b92ffaSHans Petter Selasky 	argc -= optind;
1112*d6b92ffaSHans Petter Selasky 	argv += optind;
1113*d6b92ffaSHans Petter Selasky 
1114*d6b92ffaSHans Petter Selasky 	if (ibd_timeout)
1115*d6b92ffaSHans Petter Selasky 		config.timeout_ms = ibd_timeout;
1116*d6b92ffaSHans Petter Selasky 
1117*d6b92ffaSHans Petter Selasky 	config.flags = ibd_ibnetdisc_flags;
1118*d6b92ffaSHans Petter Selasky 
1119*d6b92ffaSHans Petter Selasky 	if (argc && !(f = fopen(argv[0], "w")))
1120*d6b92ffaSHans Petter Selasky 		IBEXIT("can't open file %s for writing", argv[0]);
1121*d6b92ffaSHans Petter Selasky 
1122*d6b92ffaSHans Petter Selasky 	config.mkey = ibd_mkey;
1123*d6b92ffaSHans Petter Selasky 
1124*d6b92ffaSHans Petter Selasky 	node_name_map = open_node_name_map(node_name_map_file);
1125*d6b92ffaSHans Petter Selasky 
1126*d6b92ffaSHans Petter Selasky 	if (diff_cache_file &&
1127*d6b92ffaSHans Petter Selasky 	    !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
1128*d6b92ffaSHans Petter Selasky 		IBEXIT("loading cached fabric for diff failed\n");
1129*d6b92ffaSHans Petter Selasky 
1130*d6b92ffaSHans Petter Selasky 	if (load_cache_file) {
1131*d6b92ffaSHans Petter Selasky 		if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL)
1132*d6b92ffaSHans Petter Selasky 			IBEXIT("loading cached fabric failed\n");
1133*d6b92ffaSHans Petter Selasky 	} else {
1134*d6b92ffaSHans Petter Selasky 		if ((fabric =
1135*d6b92ffaSHans Petter Selasky 		     ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config)) == NULL)
1136*d6b92ffaSHans Petter Selasky 			IBEXIT("discover failed\n");
1137*d6b92ffaSHans Petter Selasky 	}
1138*d6b92ffaSHans Petter Selasky 
1139*d6b92ffaSHans Petter Selasky 	if (ports_report)
1140*d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes(fabric, dump_ports_report, NULL);
1141*d6b92ffaSHans Petter Selasky 	else if (list)
1142*d6b92ffaSHans Petter Selasky 		list_nodes(fabric, list);
1143*d6b92ffaSHans Petter Selasky 	else if (diff_fabric)
1144*d6b92ffaSHans Petter Selasky 		diff(diff_fabric, fabric);
1145*d6b92ffaSHans Petter Selasky 	else
1146*d6b92ffaSHans Petter Selasky 		dump_topology(group, fabric);
1147*d6b92ffaSHans Petter Selasky 
1148*d6b92ffaSHans Petter Selasky 	if (cache_file)
1149*d6b92ffaSHans Petter Selasky 		if (ibnd_cache_fabric(fabric, cache_file, 0) < 0)
1150*d6b92ffaSHans Petter Selasky 			IBEXIT("caching ibnetdiscover data failed\n");
1151*d6b92ffaSHans Petter Selasky 
1152*d6b92ffaSHans Petter Selasky 	ibnd_destroy_fabric(fabric);
1153*d6b92ffaSHans Petter Selasky 	if (diff_fabric)
1154*d6b92ffaSHans Petter Selasky 		ibnd_destroy_fabric(diff_fabric);
1155*d6b92ffaSHans Petter Selasky 	close_node_name_map(node_name_map);
1156*d6b92ffaSHans Petter Selasky 	exit(0);
1157*d6b92ffaSHans Petter Selasky }
1158