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