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