1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3321936Shselasky * Copyright (c) 2009-2011 Mellanox Technologies LTD.  All rights reserved.
4321936Shselasky * Copyright (c) 2013 Lawrence Livermore National Security.  All rights reserved.
5321936Shselasky *
6321936Shselasky * This software is available to you under a choice of one of two
7321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
8321936Shselasky * General Public License (GPL) Version 2, available from the file
9321936Shselasky * COPYING in the main directory of this source tree, or the
10321936Shselasky * OpenIB.org BSD license below:
11321936Shselasky *
12321936Shselasky *     Redistribution and use in source and binary forms, with or
13321936Shselasky *     without modification, are permitted provided that the following
14321936Shselasky *     conditions are met:
15321936Shselasky *
16321936Shselasky *      - Redistributions of source code must retain the above
17321936Shselasky *        copyright notice, this list of conditions and the following
18321936Shselasky *        disclaimer.
19321936Shselasky *
20321936Shselasky *      - Redistributions in binary form must reproduce the above
21321936Shselasky *        copyright notice, this list of conditions and the following
22321936Shselasky *        disclaimer in the documentation and/or other materials
23321936Shselasky *        provided with the distribution.
24321936Shselasky *
25321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32321936Shselasky * SOFTWARE.
33321936Shselasky *
34321936Shselasky */
35321936Shselasky
36321936Shselasky#if HAVE_CONFIG_H
37321936Shselasky#  include <config.h>
38321936Shselasky#endif				/* HAVE_CONFIG_H */
39321936Shselasky
40321936Shselasky#include <stdio.h>
41321936Shselasky#include <stdlib.h>
42321936Shselasky#include <unistd.h>
43321936Shselasky#include <string.h>
44321936Shselasky#include <inttypes.h>
45321936Shselasky#include <getopt.h>
46321936Shselasky#include <netinet/in.h>
47321936Shselasky#include <assert.h>
48321936Shselasky
49321936Shselasky#include <infiniband/umad.h>
50321936Shselasky#include <infiniband/mad.h>
51321936Shselasky#include <complib/cl_nodenamemap.h>
52321936Shselasky
53321936Shselasky#include <infiniband/ibnetdisc.h>
54321936Shselasky
55321936Shselasky#include "ibdiag_common.h"
56321936Shselasky
57321936Shselaskystruct ibmad_port *srcport;
58321936Shselasky
59321936Shselaskyunsigned startlid = 0, endlid = 0;
60321936Shselasky
61321936Shselaskystatic int brief, dump_all, multicast;
62321936Shselasky
63321936Shselaskystatic char *node_name_map_file = NULL;
64321936Shselaskystatic nn_map_t *node_name_map = NULL;
65321936Shselasky
66321936Shselasky#define IB_MLIDS_IN_BLOCK	(IB_SMP_DATA_SIZE/2)
67321936Shselasky
68321936Shselaskyint dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
69321936Shselasky	      uint16_t mft[16][IB_MLIDS_IN_BLOCK])
70321936Shselasky{
71321936Shselasky	uint16_t mask;
72321936Shselasky	unsigned i, chunk, bit, nonzero = 0;
73321936Shselasky
74321936Shselasky	if (brief) {
75321936Shselasky		int n = 0;
76321936Shselasky		unsigned chunks = ALIGN(nports + 1, 16) / 16;
77321936Shselasky		for (i = 0; i < chunks; i++) {
78321936Shselasky			mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
79321936Shselasky			if (mask)
80321936Shselasky				nonzero++;
81321936Shselasky			n += snprintf(str + n, strlen - n, "%04hx", mask);
82321936Shselasky			if (n >= strlen) {
83321936Shselasky				n = strlen;
84321936Shselasky				break;
85321936Shselasky			}
86321936Shselasky		}
87321936Shselasky		if (!nonzero && !dump_all) {
88321936Shselasky			str[0] = 0;
89321936Shselasky			return 0;
90321936Shselasky		}
91321936Shselasky		return n;
92321936Shselasky	}
93321936Shselasky	for (i = 0; i <= nports; i++) {
94321936Shselasky		chunk = i / 16;
95321936Shselasky		bit = i % 16;
96321936Shselasky
97321936Shselasky		mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
98321936Shselasky		if (mask)
99321936Shselasky			nonzero++;
100321936Shselasky		str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
101321936Shselasky		str[i * 2 + 1] = ' ';
102321936Shselasky	}
103321936Shselasky	if (!nonzero && !dump_all) {
104321936Shselasky		str[0] = 0;
105321936Shselasky		return 0;
106321936Shselasky	}
107321936Shselasky	str[i * 2] = 0;
108321936Shselasky	return i * 2;
109321936Shselasky}
110321936Shselasky
111321936Shselaskyuint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
112321936Shselasky
113321936Shselaskyvoid dump_multicast_tables(ibnd_node_t * node, unsigned startlid,
114321936Shselasky			    unsigned endlid, struct ibmad_port * mad_port)
115321936Shselasky{
116321936Shselasky	ib_portid_t *portid = &node->path_portid;
117321936Shselasky	char nd[IB_SMP_DATA_SIZE] = { 0 };
118321936Shselasky	char str[512];
119321936Shselasky	char *s;
120321936Shselasky	uint64_t nodeguid;
121321936Shselasky	uint32_t mod;
122321936Shselasky	unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
123321936Shselasky	    top;
124321936Shselasky	char *mapnd = NULL;
125321936Shselasky	int n = 0;
126321936Shselasky
127321936Shselasky	memcpy(nd, node->nodedesc, strlen(node->nodedesc));
128321936Shselasky	nports = node->numports;
129321936Shselasky	nodeguid = node->guid;
130321936Shselasky
131321936Shselasky	mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_CAP_F, &cap);
132321936Shselasky	mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_TOP_F, &top);
133321936Shselasky
134321936Shselasky	if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)
135321936Shselasky		endlid = IB_MIN_MCAST_LID + cap - 1;
136321936Shselasky	if (!dump_all && top && top < endlid) {
137321936Shselasky		if (top < IB_MIN_MCAST_LID - 1)
138321936Shselasky			IBWARN("illegal top mlid %x", top);
139321936Shselasky		else
140321936Shselasky			endlid = top;
141321936Shselasky	}
142321936Shselasky
143321936Shselasky	if (!startlid)
144321936Shselasky		startlid = IB_MIN_MCAST_LID;
145321936Shselasky	else if (startlid < IB_MIN_MCAST_LID) {
146321936Shselasky		IBWARN("illegal start mlid %x, set to %x", startlid,
147321936Shselasky		       IB_MIN_MCAST_LID);
148321936Shselasky		startlid = IB_MIN_MCAST_LID;
149321936Shselasky	}
150321936Shselasky
151321936Shselasky	if (endlid > IB_MAX_MCAST_LID) {
152321936Shselasky		IBWARN("illegal end mlid %x, truncate to %x", endlid,
153321936Shselasky		       IB_MAX_MCAST_LID);
154321936Shselasky		endlid = IB_MAX_MCAST_LID;
155321936Shselasky	}
156321936Shselasky
157321936Shselasky	mapnd = remap_node_name(node_name_map, nodeguid, nd);
158321936Shselasky
159321936Shselasky	printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
160321936Shselasky	       " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
161321936Shselasky	       mapnd);
162321936Shselasky
163321936Shselasky	if (brief)
164321936Shselasky		printf(" MLid       Port Mask\n");
165321936Shselasky	else {
166321936Shselasky		if (nports > 9) {
167321936Shselasky			for (i = 0, s = str; i <= nports; i++) {
168321936Shselasky				*s++ = (i % 10) ? ' ' : '0' + i / 10;
169321936Shselasky				*s++ = ' ';
170321936Shselasky			}
171321936Shselasky			*s = 0;
172321936Shselasky			printf("            %s\n", str);
173321936Shselasky		}
174321936Shselasky		for (i = 0, s = str; i <= nports; i++)
175321936Shselasky			s += sprintf(s, "%d ", i % 10);
176321936Shselasky		printf("     Ports: %s\n", str);
177321936Shselasky		printf(" MLid\n");
178321936Shselasky	}
179321936Shselasky	if (ibverbose)
180321936Shselasky		printf("Switch multicast mlid capability is %d top is 0x%x\n",
181321936Shselasky		       cap, top);
182321936Shselasky
183321936Shselasky	chunks = ALIGN(nports + 1, 16) / 16;
184321936Shselasky
185321936Shselasky	startblock = startlid / IB_MLIDS_IN_BLOCK;
186321936Shselasky	lastblock = endlid / IB_MLIDS_IN_BLOCK;
187321936Shselasky	for (block = startblock; block <= lastblock; block++) {
188321936Shselasky		for (j = 0; j < chunks; j++) {
189321936Shselasky			int status;
190321936Shselasky			mod = (block - IB_MIN_MCAST_LID / IB_MLIDS_IN_BLOCK)
191321936Shselasky			    | (j << 28);
192321936Shselasky
193321936Shselasky			DEBUG("reading block %x chunk %d mod %x", block, j,
194321936Shselasky			      mod);
195321936Shselasky			if (!smp_query_status_via
196321936Shselasky			    (mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0,
197321936Shselasky			     &status, mad_port)) {
198321936Shselasky				fprintf(stderr, "SubnGet(MFT) failed on switch "
199321936Shselasky						"'%s' %s Node GUID 0x%"PRIx64
200321936Shselasky						" SMA LID %d; MAD status 0x%x "
201321936Shselasky						"AM 0x%x\n",
202321936Shselasky						mapnd, portid2str(portid),
203321936Shselasky						node->guid, node->smalid,
204321936Shselasky						status, mod);
205321936Shselasky			}
206321936Shselasky		}
207321936Shselasky
208321936Shselasky		i = block * IB_MLIDS_IN_BLOCK;
209321936Shselasky		e = i + IB_MLIDS_IN_BLOCK;
210321936Shselasky		if (i < startlid)
211321936Shselasky			i = startlid;
212321936Shselasky		if (e > endlid + 1)
213321936Shselasky			e = endlid + 1;
214321936Shselasky
215321936Shselasky		for (; i < e; i++) {
216321936Shselasky			if (dump_mlid(str, sizeof str, i, nports, mft) == 0)
217321936Shselasky				continue;
218321936Shselasky			printf("0x%04x      %s\n", i, str);
219321936Shselasky			n++;
220321936Shselasky		}
221321936Shselasky	}
222321936Shselasky
223321936Shselasky	printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
224321936Shselasky
225321936Shselasky	free(mapnd);
226321936Shselasky}
227321936Shselasky
228321936Shselaskyint dump_lid(char *str, int str_len, int lid, int valid,
229321936Shselasky		ibnd_fabric_t *fabric,
230321936Shselasky		int * last_port_lid, int * base_port_lid,
231321936Shselasky		uint64_t * portguid)
232321936Shselasky{
233321936Shselasky	char nd[IB_SMP_DATA_SIZE] = { 0 };
234321936Shselasky
235321936Shselasky	ibnd_port_t *port = NULL;
236321936Shselasky
237321936Shselasky	char ntype[50], sguid[30];
238321936Shselasky	uint64_t nodeguid;
239321936Shselasky	int baselid, lmc, type;
240321936Shselasky	char *mapnd = NULL;
241321936Shselasky	int rc;
242321936Shselasky
243321936Shselasky	if (brief) {
244321936Shselasky		str[0] = 0;
245321936Shselasky		return 0;
246321936Shselasky	}
247321936Shselasky
248321936Shselasky	if (lid <= *last_port_lid) {
249321936Shselasky		if (!valid)
250321936Shselasky			return snprintf(str, str_len,
251321936Shselasky					": (path #%d - illegal port)",
252321936Shselasky					lid - *base_port_lid);
253321936Shselasky		else if (!*portguid)
254321936Shselasky			return snprintf(str, str_len,
255321936Shselasky					": (path #%d out of %d)",
256321936Shselasky					lid - *base_port_lid + 1,
257321936Shselasky					*last_port_lid - *base_port_lid + 1);
258321936Shselasky		else {
259321936Shselasky			return snprintf(str, str_len,
260321936Shselasky					": (path #%d out of %d: portguid %s)",
261321936Shselasky					lid - *base_port_lid + 1,
262321936Shselasky					*last_port_lid - *base_port_lid + 1,
263321936Shselasky					mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
264321936Shselasky						     sizeof sguid, portguid));
265321936Shselasky		}
266321936Shselasky	}
267321936Shselasky
268321936Shselasky	if (!valid)
269321936Shselasky		return snprintf(str, str_len, ": (illegal port)");
270321936Shselasky
271321936Shselasky	*portguid = 0;
272321936Shselasky
273321936Shselasky	port = ibnd_find_port_lid(fabric, lid);
274321936Shselasky	if (!port) {
275321936Shselasky		return snprintf(str, str_len, ": (node info not available fabric scan)");
276321936Shselasky	}
277321936Shselasky
278321936Shselasky	nodeguid = port->node->guid;
279321936Shselasky	*portguid = port->guid;
280321936Shselasky	type = port->node->type;
281321936Shselasky
282321936Shselasky	baselid = port->base_lid;
283321936Shselasky	lmc = port->lmc;
284321936Shselasky
285321936Shselasky	memcpy(nd, port->node->nodedesc, strlen(port->node->nodedesc));
286321936Shselasky
287321936Shselasky	if (lmc > 0) {
288321936Shselasky		*base_port_lid = baselid;
289321936Shselasky		*last_port_lid = baselid + (1 << lmc) - 1;
290321936Shselasky	}
291321936Shselasky
292321936Shselasky	mapnd = remap_node_name(node_name_map, nodeguid, nd);
293321936Shselasky
294321936Shselasky	rc = snprintf(str, str_len, ": (%s portguid %s: '%s')",
295321936Shselasky		      mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype,
296321936Shselasky				   &type), mad_dump_val(IB_NODE_PORT_GUID_F,
297321936Shselasky							sguid, sizeof sguid,
298321936Shselasky							portguid),
299321936Shselasky		      mapnd);
300321936Shselasky
301321936Shselasky	free(mapnd);
302321936Shselasky	return rc;
303321936Shselasky}
304321936Shselasky
305321936Shselaskyvoid dump_unicast_tables(ibnd_node_t * node, int startlid, int endlid,
306321936Shselasky			struct ibmad_port *mad_port, ibnd_fabric_t *fabric)
307321936Shselasky{
308321936Shselasky	ib_portid_t * portid = &node->path_portid;
309321936Shselasky	char lft[IB_SMP_DATA_SIZE] = { 0 };
310321936Shselasky	char nd[IB_SMP_DATA_SIZE] = { 0 };
311321936Shselasky	char str[200];
312321936Shselasky	uint64_t nodeguid;
313321936Shselasky	int block, i, e, top;
314321936Shselasky	unsigned nports;
315321936Shselasky	int n = 0, startblock, endblock;
316321936Shselasky	char *mapnd = NULL;
317321936Shselasky	int last_port_lid = 0, base_port_lid = 0;
318321936Shselasky	uint64_t portguid = 0;
319321936Shselasky
320321936Shselasky	mad_decode_field(node->switchinfo, IB_SW_LINEAR_FDB_TOP_F, &top);
321321936Shselasky	nodeguid = node->guid;
322321936Shselasky	nports = node->numports;
323321936Shselasky	memcpy(nd, node->nodedesc, strlen(node->nodedesc));
324321936Shselasky
325321936Shselasky	if (!endlid || endlid > top)
326321936Shselasky		endlid = top;
327321936Shselasky
328321936Shselasky	if (endlid > IB_MAX_UCAST_LID) {
329321936Shselasky		IBWARN("illegal lft top %d, truncate to %d", endlid,
330321936Shselasky		       IB_MAX_UCAST_LID);
331321936Shselasky		endlid = IB_MAX_UCAST_LID;
332321936Shselasky	}
333321936Shselasky
334321936Shselasky	mapnd = remap_node_name(node_name_map, nodeguid, nd);
335321936Shselasky
336321936Shselasky	printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
337321936Shselasky	       " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
338321936Shselasky	       mapnd);
339321936Shselasky
340321936Shselasky	DEBUG("Switch top is 0x%x\n", top);
341321936Shselasky
342321936Shselasky	printf("  Lid  Out   Destination\n");
343321936Shselasky	printf("       Port     Info \n");
344321936Shselasky	startblock = startlid / IB_SMP_DATA_SIZE;
345321936Shselasky	endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;
346321936Shselasky	for (block = startblock; block < endblock; block++) {
347321936Shselasky		int status;
348321936Shselasky		DEBUG("reading block %d", block);
349321936Shselasky		if (!smp_query_status_via(lft, portid, IB_ATTR_LINEARFORWTBL, block,
350321936Shselasky				   0, &status, mad_port)) {
351321936Shselasky			fprintf(stderr, "SubnGet(LFT) failed on switch "
352321936Shselasky					"'%s' %s Node GUID 0x%"PRIx64
353321936Shselasky					" SMA LID %d; MAD status 0x%x AM 0x%x\n",
354321936Shselasky					mapnd, portid2str(portid),
355321936Shselasky					node->guid, node->smalid,
356321936Shselasky					status, block);
357321936Shselasky		}
358321936Shselasky		i = block * IB_SMP_DATA_SIZE;
359321936Shselasky		e = i + IB_SMP_DATA_SIZE;
360321936Shselasky		if (i < startlid)
361321936Shselasky			i = startlid;
362321936Shselasky		if (e > endlid + 1)
363321936Shselasky			e = endlid + 1;
364321936Shselasky
365321936Shselasky		for (; i < e; i++) {
366321936Shselasky			unsigned outport = lft[i % IB_SMP_DATA_SIZE];
367321936Shselasky			unsigned valid = (outport <= nports);
368321936Shselasky
369321936Shselasky			if (!valid && !dump_all)
370321936Shselasky				continue;
371321936Shselasky			dump_lid(str, sizeof str, i, valid, fabric,
372321936Shselasky				&last_port_lid, &base_port_lid, &portguid);
373321936Shselasky			printf("0x%04x %03u %s\n", i, outport & 0xff, str);
374321936Shselasky			n++;
375321936Shselasky		}
376321936Shselasky	}
377321936Shselasky
378321936Shselasky	printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
379321936Shselasky	free(mapnd);
380321936Shselasky}
381321936Shselasky
382321936Shselaskyvoid dump_node(ibnd_node_t *node, struct ibmad_port *mad_port,
383321936Shselasky		ibnd_fabric_t *fabric)
384321936Shselasky{
385321936Shselasky	if (multicast)
386321936Shselasky		dump_multicast_tables(node, startlid, endlid, mad_port);
387321936Shselasky	else
388321936Shselasky		dump_unicast_tables(node, startlid, endlid,
389321936Shselasky						mad_port, fabric);
390321936Shselasky}
391321936Shselasky
392321936Shselaskyvoid process_switch(ibnd_node_t * node, void *fabric)
393321936Shselasky{
394321936Shselasky	dump_node(node, srcport, (ibnd_fabric_t *)fabric);
395321936Shselasky}
396321936Shselasky
397321936Shselaskystatic int process_opt(void *context, int ch, char *optarg)
398321936Shselasky{
399321936Shselasky	switch (ch) {
400321936Shselasky	case 'a':
401321936Shselasky		dump_all++;
402321936Shselasky		break;
403321936Shselasky	case 'M':
404321936Shselasky		multicast++;
405321936Shselasky		break;
406321936Shselasky	case 'n':
407321936Shselasky		brief++;
408321936Shselasky		break;
409321936Shselasky	case 1:
410321936Shselasky		node_name_map_file = strdup(optarg);
411321936Shselasky		break;
412321936Shselasky	default:
413321936Shselasky		return -1;
414321936Shselasky	}
415321936Shselasky	return 0;
416321936Shselasky}
417321936Shselasky
418321936Shselaskyint main(int argc, char **argv)
419321936Shselasky{
420321936Shselasky	int rc = 0;
421321936Shselasky	int mgmt_classes[3] =
422321936Shselasky	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
423321936Shselasky
424321936Shselasky	struct ibnd_config config = { 0 };
425321936Shselasky	ibnd_fabric_t *fabric = NULL;
426321936Shselasky
427321936Shselasky	const struct ibdiag_opt opts[] = {
428321936Shselasky		{"all", 'a', 0, NULL, "show all lids, even invalid entries"},
429321936Shselasky		{"no_dests", 'n', 0, NULL,
430321936Shselasky		 "do not try to resolve destinations"},
431321936Shselasky		{"Multicast", 'M', 0, NULL, "show multicast forwarding tables"},
432321936Shselasky		{"node-name-map", 1, 1, "<file>", "node name map file"},
433321936Shselasky		{0}
434321936Shselasky	};
435321936Shselasky	char usage_args[] = "[<dest dr_path|lid|guid> [<startlid> [<endlid>]]]";
436321936Shselasky	const char *usage_examples[] = {
437321936Shselasky		" -- Unicast examples:",
438321936Shselasky		"-a\t# same, but dump all lids, even with invalid out ports",
439321936Shselasky		"-n\t# simple dump format - no destination resolving",
440321936Shselasky		"10\t# dump lids starting from 10",
441321936Shselasky		"0x10 0x20\t# dump lid range",
442321936Shselasky		" -- Multicast examples:",
443321936Shselasky		"-M\t# dump all non empty mlids of switch with lid 4",
444321936Shselasky		"-M 0xc010 0xc020\t# same, but with range",
445321936Shselasky		"-M -n\t# simple dump format",
446321936Shselasky		NULL,
447321936Shselasky	};
448321936Shselasky
449321936Shselasky	ibdiag_process_opts(argc, argv, &config, "KGDLs", opts, process_opt,
450321936Shselasky			    usage_args, usage_examples);
451321936Shselasky
452321936Shselasky	argc -= optind;
453321936Shselasky	argv += optind;
454321936Shselasky
455321936Shselasky	if (argc > 0)
456321936Shselasky		startlid = strtoul(argv[0], 0, 0);
457321936Shselasky	if (argc > 1)
458321936Shselasky		endlid = strtoul(argv[1], 0, 0);
459321936Shselasky
460321936Shselasky	node_name_map = open_node_name_map(node_name_map_file);
461321936Shselasky
462321936Shselasky	if (ibd_timeout)
463321936Shselasky		config.timeout_ms = ibd_timeout;
464321936Shselasky
465321936Shselasky	config.flags = ibd_ibnetdisc_flags;
466321936Shselasky	config.mkey = ibd_mkey;
467321936Shselasky
468321936Shselasky	if ((fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL,
469321936Shselasky						&config)) != NULL) {
470321936Shselasky
471321936Shselasky		srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
472321936Shselasky		if (!srcport) {
473321936Shselasky			fprintf(stderr,
474321936Shselasky				"Failed to open '%s' port '%d'\n", ibd_ca, ibd_ca_port);
475321936Shselasky			rc = -1;
476321936Shselasky			goto Exit;
477321936Shselasky		}
478321936Shselasky		smp_mkey_set(srcport, ibd_mkey);
479321936Shselasky
480321936Shselasky		if (ibd_timeout) {
481321936Shselasky			mad_rpc_set_timeout(srcport, ibd_timeout);
482321936Shselasky		}
483321936Shselasky
484321936Shselasky		ibnd_iter_nodes_type(fabric, process_switch, IB_NODE_SWITCH, fabric);
485321936Shselasky
486321936Shselasky		mad_rpc_close_port(srcport);
487321936Shselasky
488321936Shselasky	} else {
489321936Shselasky		fprintf(stderr, "Failed to discover fabric\n");
490321936Shselasky		rc = -1;
491321936Shselasky	}
492321936ShselaskyExit:
493321936Shselasky	ibnd_destroy_fabric(fabric);
494321936Shselasky
495321936Shselasky	close_node_name_map(node_name_map);
496321936Shselasky	exit(rc);
497321936Shselasky}
498