xref: /freebsd/contrib/ofed/infiniband-diags/src/ibroute.c (revision 76cc4c20473495c839c4df9cfe0bf46632738f03)
1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2009-2011 Mellanox Technologies LTD.  All rights reserved.
4d6b92ffaSHans Petter Selasky  *
5d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
6d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
7d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
8d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
9d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
10d6b92ffaSHans Petter Selasky  *
11d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
12d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
13d6b92ffaSHans Petter Selasky  *     conditions are met:
14d6b92ffaSHans Petter Selasky  *
15d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
16d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
17d6b92ffaSHans Petter Selasky  *        disclaimer.
18d6b92ffaSHans Petter Selasky  *
19d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
20d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
21d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
22d6b92ffaSHans Petter Selasky  *        provided with the distribution.
23d6b92ffaSHans Petter Selasky  *
24d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31d6b92ffaSHans Petter Selasky  * SOFTWARE.
32d6b92ffaSHans Petter Selasky  *
33d6b92ffaSHans Petter Selasky  */
34d6b92ffaSHans Petter Selasky 
35d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
36d6b92ffaSHans Petter Selasky #  include <config.h>
37d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
38d6b92ffaSHans Petter Selasky 
39d6b92ffaSHans Petter Selasky #include <stdio.h>
40d6b92ffaSHans Petter Selasky #include <stdlib.h>
41d6b92ffaSHans Petter Selasky #include <unistd.h>
42d6b92ffaSHans Petter Selasky #include <string.h>
43d6b92ffaSHans Petter Selasky #include <inttypes.h>
44d6b92ffaSHans Petter Selasky #include <getopt.h>
45d6b92ffaSHans Petter Selasky #include <netinet/in.h>
46d6b92ffaSHans Petter Selasky 
47d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
48d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
49d6b92ffaSHans Petter Selasky #include <complib/cl_nodenamemap.h>
50d6b92ffaSHans Petter Selasky 
51d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
52d6b92ffaSHans Petter Selasky 
53d6b92ffaSHans Petter Selasky struct ibmad_port *srcport;
54d6b92ffaSHans Petter Selasky 
55d6b92ffaSHans Petter Selasky static int brief, dump_all, multicast;
56d6b92ffaSHans Petter Selasky 
57d6b92ffaSHans Petter Selasky static char *node_name_map_file = NULL;
58d6b92ffaSHans Petter Selasky static nn_map_t *node_name_map = NULL;
59d6b92ffaSHans Petter Selasky 
60d6b92ffaSHans Petter Selasky /*******************************************/
61d6b92ffaSHans Petter Selasky 
check_switch(ib_portid_t * portid,unsigned int * nports,uint64_t * guid,uint8_t * sw,char * nd)62d6b92ffaSHans Petter Selasky char *check_switch(ib_portid_t * portid, unsigned int *nports, uint64_t * guid,
63d6b92ffaSHans Petter Selasky 		   uint8_t * sw, char *nd)
64d6b92ffaSHans Petter Selasky {
65d6b92ffaSHans Petter Selasky 	uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
66d6b92ffaSHans Petter Selasky 	int type;
67d6b92ffaSHans Petter Selasky 
68d6b92ffaSHans Petter Selasky 	DEBUG("checking node type");
69d6b92ffaSHans Petter Selasky 	if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, 0, srcport)) {
70d6b92ffaSHans Petter Selasky 		xdump(stderr, "nodeinfo\n", ni, sizeof ni);
71d6b92ffaSHans Petter Selasky 		return "node info failed: valid addr?";
72d6b92ffaSHans Petter Selasky 	}
73d6b92ffaSHans Petter Selasky 
74d6b92ffaSHans Petter Selasky 	if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, 0, srcport))
75d6b92ffaSHans Petter Selasky 		return "node desc failed";
76d6b92ffaSHans Petter Selasky 
77d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_TYPE_F, &type);
78d6b92ffaSHans Petter Selasky 	if (type != IB_NODE_SWITCH)
79d6b92ffaSHans Petter Selasky 		return "not a switch";
80d6b92ffaSHans Petter Selasky 
81d6b92ffaSHans Petter Selasky 	DEBUG("Gathering information about switch");
82d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_NPORTS_F, nports);
83d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_GUID_F, guid);
84d6b92ffaSHans Petter Selasky 
85d6b92ffaSHans Petter Selasky 	if (!smp_query_via(sw, portid, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
86d6b92ffaSHans Petter Selasky 		return "switch info failed: is a switch node?";
87d6b92ffaSHans Petter Selasky 
88d6b92ffaSHans Petter Selasky 	return 0;
89d6b92ffaSHans Petter Selasky }
90d6b92ffaSHans Petter Selasky 
91d6b92ffaSHans Petter Selasky #define IB_MLIDS_IN_BLOCK	(IB_SMP_DATA_SIZE/2)
92d6b92ffaSHans Petter Selasky 
dump_mlid(char * str,int strlen,unsigned mlid,unsigned nports,uint16_t mft[16][IB_MLIDS_IN_BLOCK])93d6b92ffaSHans Petter Selasky int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
94d6b92ffaSHans Petter Selasky 	      uint16_t mft[16][IB_MLIDS_IN_BLOCK])
95d6b92ffaSHans Petter Selasky {
96d6b92ffaSHans Petter Selasky 	uint16_t mask;
97d6b92ffaSHans Petter Selasky 	unsigned i, chunk, bit, nonzero = 0;
98d6b92ffaSHans Petter Selasky 
99d6b92ffaSHans Petter Selasky 	if (brief) {
100d6b92ffaSHans Petter Selasky 		int n = 0;
101d6b92ffaSHans Petter Selasky 		unsigned chunks = ALIGN(nports + 1, 16) / 16;
102d6b92ffaSHans Petter Selasky 		for (i = 0; i < chunks; i++) {
103d6b92ffaSHans Petter Selasky 			mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
104d6b92ffaSHans Petter Selasky 			if (mask)
105d6b92ffaSHans Petter Selasky 				nonzero++;
106d6b92ffaSHans Petter Selasky 			n += snprintf(str + n, strlen - n, "%04hx", mask);
107d6b92ffaSHans Petter Selasky 			if (n >= strlen) {
108d6b92ffaSHans Petter Selasky 				n = strlen;
109d6b92ffaSHans Petter Selasky 				break;
110d6b92ffaSHans Petter Selasky 			}
111d6b92ffaSHans Petter Selasky 		}
112d6b92ffaSHans Petter Selasky 		if (!nonzero && !dump_all) {
113d6b92ffaSHans Petter Selasky 			str[0] = 0;
114d6b92ffaSHans Petter Selasky 			return 0;
115d6b92ffaSHans Petter Selasky 		}
116d6b92ffaSHans Petter Selasky 		return n;
117d6b92ffaSHans Petter Selasky 	}
118d6b92ffaSHans Petter Selasky 	for (i = 0; i <= nports; i++) {
119d6b92ffaSHans Petter Selasky 		chunk = i / 16;
120d6b92ffaSHans Petter Selasky 		bit = i % 16;
121d6b92ffaSHans Petter Selasky 
122d6b92ffaSHans Petter Selasky 		mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
123d6b92ffaSHans Petter Selasky 		if (mask)
124d6b92ffaSHans Petter Selasky 			nonzero++;
125d6b92ffaSHans Petter Selasky 		str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
126d6b92ffaSHans Petter Selasky 		str[i * 2 + 1] = ' ';
127d6b92ffaSHans Petter Selasky 	}
128d6b92ffaSHans Petter Selasky 	if (!nonzero && !dump_all) {
129d6b92ffaSHans Petter Selasky 		str[0] = 0;
130d6b92ffaSHans Petter Selasky 		return 0;
131d6b92ffaSHans Petter Selasky 	}
132d6b92ffaSHans Petter Selasky 	str[i * 2] = 0;
133d6b92ffaSHans Petter Selasky 	return i * 2;
134d6b92ffaSHans Petter Selasky }
135d6b92ffaSHans Petter Selasky 
136d6b92ffaSHans Petter Selasky uint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
137d6b92ffaSHans Petter Selasky 
dump_multicast_tables(ib_portid_t * portid,unsigned startlid,unsigned endlid)138d6b92ffaSHans Petter Selasky char *dump_multicast_tables(ib_portid_t * portid, unsigned startlid,
139d6b92ffaSHans Petter Selasky 			    unsigned endlid)
140d6b92ffaSHans Petter Selasky {
141d6b92ffaSHans Petter Selasky 	char nd[IB_SMP_DATA_SIZE] = { 0 };
142d6b92ffaSHans Petter Selasky 	uint8_t sw[IB_SMP_DATA_SIZE] = { 0 };
143d6b92ffaSHans Petter Selasky 	char str[512];
144d6b92ffaSHans Petter Selasky 	char *s;
145d6b92ffaSHans Petter Selasky 	uint64_t nodeguid;
146d6b92ffaSHans Petter Selasky 	uint32_t mod;
147d6b92ffaSHans Petter Selasky 	unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
148d6b92ffaSHans Petter Selasky 	    top;
149d6b92ffaSHans Petter Selasky 	char *mapnd = NULL;
150d6b92ffaSHans Petter Selasky 	int n = 0;
151d6b92ffaSHans Petter Selasky 
152d6b92ffaSHans Petter Selasky 	if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))
153d6b92ffaSHans Petter Selasky 		return s;
154d6b92ffaSHans Petter Selasky 
155d6b92ffaSHans Petter Selasky 	mad_decode_field(sw, IB_SW_MCAST_FDB_CAP_F, &cap);
156d6b92ffaSHans Petter Selasky 	mad_decode_field(sw, IB_SW_MCAST_FDB_TOP_F, &top);
157d6b92ffaSHans Petter Selasky 
158d6b92ffaSHans Petter Selasky 	if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)
159d6b92ffaSHans Petter Selasky 		endlid = IB_MIN_MCAST_LID + cap - 1;
160d6b92ffaSHans Petter Selasky 	if (!dump_all && top && top < endlid) {
161d6b92ffaSHans Petter Selasky 		if (top < IB_MIN_MCAST_LID - 1)
162d6b92ffaSHans Petter Selasky 			IBWARN("illegal top mlid %x", top);
163d6b92ffaSHans Petter Selasky 		else
164d6b92ffaSHans Petter Selasky 			endlid = top;
165d6b92ffaSHans Petter Selasky 	}
166d6b92ffaSHans Petter Selasky 
167d6b92ffaSHans Petter Selasky 	if (!startlid)
168d6b92ffaSHans Petter Selasky 		startlid = IB_MIN_MCAST_LID;
169d6b92ffaSHans Petter Selasky 	else if (startlid < IB_MIN_MCAST_LID) {
170d6b92ffaSHans Petter Selasky 		IBWARN("illegal start mlid %x, set to %x", startlid,
171d6b92ffaSHans Petter Selasky 		       IB_MIN_MCAST_LID);
172d6b92ffaSHans Petter Selasky 		startlid = IB_MIN_MCAST_LID;
173d6b92ffaSHans Petter Selasky 	}
174d6b92ffaSHans Petter Selasky 
175d6b92ffaSHans Petter Selasky 	if (endlid > IB_MAX_MCAST_LID) {
176d6b92ffaSHans Petter Selasky 		IBWARN("illegal end mlid %x, truncate to %x", endlid,
177d6b92ffaSHans Petter Selasky 		       IB_MAX_MCAST_LID);
178d6b92ffaSHans Petter Selasky 		endlid = IB_MAX_MCAST_LID;
179d6b92ffaSHans Petter Selasky 	}
180d6b92ffaSHans Petter Selasky 
181d6b92ffaSHans Petter Selasky 	mapnd = remap_node_name(node_name_map, nodeguid, nd);
182d6b92ffaSHans Petter Selasky 
183d6b92ffaSHans Petter Selasky 	printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
184d6b92ffaSHans Petter Selasky 	       " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
185d6b92ffaSHans Petter Selasky 	       mapnd);
186d6b92ffaSHans Petter Selasky 
187d6b92ffaSHans Petter Selasky 	if (brief)
188d6b92ffaSHans Petter Selasky 		printf(" MLid       Port Mask\n");
189d6b92ffaSHans Petter Selasky 	else {
190d6b92ffaSHans Petter Selasky 		if (nports > 9) {
191d6b92ffaSHans Petter Selasky 			for (i = 0, s = str; i <= nports; i++) {
192d6b92ffaSHans Petter Selasky 				*s++ = (i % 10) ? ' ' : '0' + i / 10;
193d6b92ffaSHans Petter Selasky 				*s++ = ' ';
194d6b92ffaSHans Petter Selasky 			}
195d6b92ffaSHans Petter Selasky 			*s = 0;
196d6b92ffaSHans Petter Selasky 			printf("            %s\n", str);
197d6b92ffaSHans Petter Selasky 		}
198d6b92ffaSHans Petter Selasky 		for (i = 0, s = str; i <= nports; i++)
199d6b92ffaSHans Petter Selasky 			s += sprintf(s, "%d ", i % 10);
200d6b92ffaSHans Petter Selasky 		printf("     Ports: %s\n", str);
201d6b92ffaSHans Petter Selasky 		printf(" MLid\n");
202d6b92ffaSHans Petter Selasky 	}
203d6b92ffaSHans Petter Selasky 	if (ibverbose)
204d6b92ffaSHans Petter Selasky 		printf("Switch multicast mlid capability is %d top is 0x%x\n",
205d6b92ffaSHans Petter Selasky 		       cap, top);
206d6b92ffaSHans Petter Selasky 
207d6b92ffaSHans Petter Selasky 	chunks = ALIGN(nports + 1, 16) / 16;
208d6b92ffaSHans Petter Selasky 
209d6b92ffaSHans Petter Selasky 	startblock = startlid / IB_MLIDS_IN_BLOCK;
210d6b92ffaSHans Petter Selasky 	lastblock = endlid / IB_MLIDS_IN_BLOCK;
211d6b92ffaSHans Petter Selasky 	for (block = startblock; block <= lastblock; block++) {
212d6b92ffaSHans Petter Selasky 		for (j = 0; j < chunks; j++) {
213d6b92ffaSHans Petter Selasky 			int status;
214d6b92ffaSHans Petter Selasky 			mod = (block - IB_MIN_MCAST_LID / IB_MLIDS_IN_BLOCK)
215d6b92ffaSHans Petter Selasky 			    | (j << 28);
216d6b92ffaSHans Petter Selasky 
217d6b92ffaSHans Petter Selasky 			DEBUG("reading block %x chunk %d mod %x", block, j,
218d6b92ffaSHans Petter Selasky 			      mod);
219d6b92ffaSHans Petter Selasky 			if (!smp_query_status_via
220d6b92ffaSHans Petter Selasky 			    (mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0,
221d6b92ffaSHans Petter Selasky 			     &status, srcport)) {
222d6b92ffaSHans Petter Selasky 				fprintf(stderr, "SubnGet() failed"
223d6b92ffaSHans Petter Selasky 						"; MAD status 0x%x AM 0x%x\n",
224d6b92ffaSHans Petter Selasky 						status, mod);
225*76cc4c20SEric van Gyzen 				free(mapnd);
226d6b92ffaSHans Petter Selasky 				return NULL;
227d6b92ffaSHans Petter Selasky 			}
228d6b92ffaSHans Petter Selasky 		}
229d6b92ffaSHans Petter Selasky 
230d6b92ffaSHans Petter Selasky 		i = block * IB_MLIDS_IN_BLOCK;
231d6b92ffaSHans Petter Selasky 		e = i + IB_MLIDS_IN_BLOCK;
232d6b92ffaSHans Petter Selasky 		if (i < startlid)
233d6b92ffaSHans Petter Selasky 			i = startlid;
234d6b92ffaSHans Petter Selasky 		if (e > endlid + 1)
235d6b92ffaSHans Petter Selasky 			e = endlid + 1;
236d6b92ffaSHans Petter Selasky 
237d6b92ffaSHans Petter Selasky 		for (; i < e; i++) {
238d6b92ffaSHans Petter Selasky 			if (dump_mlid(str, sizeof str, i, nports, mft) == 0)
239d6b92ffaSHans Petter Selasky 				continue;
240d6b92ffaSHans Petter Selasky 			printf("0x%04x      %s\n", i, str);
241d6b92ffaSHans Petter Selasky 			n++;
242d6b92ffaSHans Petter Selasky 		}
243d6b92ffaSHans Petter Selasky 	}
244d6b92ffaSHans Petter Selasky 
245d6b92ffaSHans Petter Selasky 	printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
246d6b92ffaSHans Petter Selasky 
247d6b92ffaSHans Petter Selasky 	free(mapnd);
248d6b92ffaSHans Petter Selasky 	return 0;
249d6b92ffaSHans Petter Selasky }
250d6b92ffaSHans Petter Selasky 
dump_lid(char * str,int strlen,int lid,int valid)251d6b92ffaSHans Petter Selasky int dump_lid(char *str, int strlen, int lid, int valid)
252d6b92ffaSHans Petter Selasky {
253d6b92ffaSHans Petter Selasky 	char nd[IB_SMP_DATA_SIZE] = { 0 };
254d6b92ffaSHans Petter Selasky 	uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
255d6b92ffaSHans Petter Selasky 	uint8_t pi[IB_SMP_DATA_SIZE] = { 0 };
256d6b92ffaSHans Petter Selasky 	ib_portid_t lidport = { 0 };
257d6b92ffaSHans Petter Selasky 	static int last_port_lid, base_port_lid;
258d6b92ffaSHans Petter Selasky 	char ntype[50], sguid[30];
259d6b92ffaSHans Petter Selasky 	static uint64_t portguid;
260d6b92ffaSHans Petter Selasky 	uint64_t nodeguid;
261d6b92ffaSHans Petter Selasky 	int baselid, lmc, type;
262d6b92ffaSHans Petter Selasky 	char *mapnd = NULL;
263d6b92ffaSHans Petter Selasky 	int rc;
264d6b92ffaSHans Petter Selasky 
265d6b92ffaSHans Petter Selasky 	if (brief) {
266d6b92ffaSHans Petter Selasky 		str[0] = 0;
267d6b92ffaSHans Petter Selasky 		return 0;
268d6b92ffaSHans Petter Selasky 	}
269d6b92ffaSHans Petter Selasky 
270d6b92ffaSHans Petter Selasky 	if (lid <= last_port_lid) {
271d6b92ffaSHans Petter Selasky 		if (!valid)
272d6b92ffaSHans Petter Selasky 			return snprintf(str, strlen,
273d6b92ffaSHans Petter Selasky 					": (path #%d - illegal port)",
274d6b92ffaSHans Petter Selasky 					lid - base_port_lid);
275d6b92ffaSHans Petter Selasky 		else if (!portguid)
276d6b92ffaSHans Petter Selasky 			return snprintf(str, strlen,
277d6b92ffaSHans Petter Selasky 					": (path #%d out of %d)",
278d6b92ffaSHans Petter Selasky 					lid - base_port_lid + 1,
279d6b92ffaSHans Petter Selasky 					last_port_lid - base_port_lid + 1);
280d6b92ffaSHans Petter Selasky 		else {
281d6b92ffaSHans Petter Selasky 			return snprintf(str, strlen,
282d6b92ffaSHans Petter Selasky 					": (path #%d out of %d: portguid %s)",
283d6b92ffaSHans Petter Selasky 					lid - base_port_lid + 1,
284d6b92ffaSHans Petter Selasky 					last_port_lid - base_port_lid + 1,
285d6b92ffaSHans Petter Selasky 					mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
286d6b92ffaSHans Petter Selasky 						     sizeof sguid, &portguid));
287d6b92ffaSHans Petter Selasky 		}
288d6b92ffaSHans Petter Selasky 	}
289d6b92ffaSHans Petter Selasky 
290d6b92ffaSHans Petter Selasky 	if (!valid)
291d6b92ffaSHans Petter Selasky 		return snprintf(str, strlen, ": (illegal port)");
292d6b92ffaSHans Petter Selasky 
293d6b92ffaSHans Petter Selasky 	portguid = 0;
294d6b92ffaSHans Petter Selasky 	lidport.lid = lid;
295d6b92ffaSHans Petter Selasky 
296d6b92ffaSHans Petter Selasky 	if (!smp_query_via(nd, &lidport, IB_ATTR_NODE_DESC, 0, 100, srcport) ||
297d6b92ffaSHans Petter Selasky 	    !smp_query_via(pi, &lidport, IB_ATTR_PORT_INFO, 0, 100, srcport) ||
298d6b92ffaSHans Petter Selasky 	    !smp_query_via(ni, &lidport, IB_ATTR_NODE_INFO, 0, 100, srcport))
299d6b92ffaSHans Petter Selasky 		return snprintf(str, strlen, ": (unknown node and type)");
300d6b92ffaSHans Petter Selasky 
301d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_GUID_F, &nodeguid);
302d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_PORT_GUID_F, &portguid);
303d6b92ffaSHans Petter Selasky 	mad_decode_field(ni, IB_NODE_TYPE_F, &type);
304d6b92ffaSHans Petter Selasky 
305d6b92ffaSHans Petter Selasky 	mad_decode_field(pi, IB_PORT_LID_F, &baselid);
306d6b92ffaSHans Petter Selasky 	mad_decode_field(pi, IB_PORT_LMC_F, &lmc);
307d6b92ffaSHans Petter Selasky 
308d6b92ffaSHans Petter Selasky 	if (lmc > 0) {
309d6b92ffaSHans Petter Selasky 		base_port_lid = baselid;
310d6b92ffaSHans Petter Selasky 		last_port_lid = baselid + (1 << lmc) - 1;
311d6b92ffaSHans Petter Selasky 	}
312d6b92ffaSHans Petter Selasky 
313d6b92ffaSHans Petter Selasky 	mapnd = remap_node_name(node_name_map, nodeguid, nd);
314d6b92ffaSHans Petter Selasky 
315d6b92ffaSHans Petter Selasky 	rc = snprintf(str, strlen, ": (%s portguid %s: '%s')",
316d6b92ffaSHans Petter Selasky 		      mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype,
317d6b92ffaSHans Petter Selasky 				   &type), mad_dump_val(IB_NODE_PORT_GUID_F,
318d6b92ffaSHans Petter Selasky 							sguid, sizeof sguid,
319d6b92ffaSHans Petter Selasky 							&portguid),
320d6b92ffaSHans Petter Selasky 		      mapnd);
321d6b92ffaSHans Petter Selasky 
322d6b92ffaSHans Petter Selasky 	free(mapnd);
323d6b92ffaSHans Petter Selasky 	return rc;
324d6b92ffaSHans Petter Selasky }
325d6b92ffaSHans Petter Selasky 
dump_unicast_tables(ib_portid_t * portid,int startlid,int endlid)326d6b92ffaSHans Petter Selasky char *dump_unicast_tables(ib_portid_t * portid, int startlid, int endlid)
327d6b92ffaSHans Petter Selasky {
328d6b92ffaSHans Petter Selasky 	char lft[IB_SMP_DATA_SIZE] = { 0 };
329d6b92ffaSHans Petter Selasky 	char nd[IB_SMP_DATA_SIZE] = { 0 };
330d6b92ffaSHans Petter Selasky 	uint8_t sw[IB_SMP_DATA_SIZE] = { 0 };
331d6b92ffaSHans Petter Selasky 	char str[200], *s;
332d6b92ffaSHans Petter Selasky 	uint64_t nodeguid;
333d6b92ffaSHans Petter Selasky 	int block, i, e, top;
334d6b92ffaSHans Petter Selasky 	unsigned nports;
335d6b92ffaSHans Petter Selasky 	int n = 0, startblock, endblock;
336d6b92ffaSHans Petter Selasky 	char *mapnd = NULL;
337d6b92ffaSHans Petter Selasky 
338d6b92ffaSHans Petter Selasky 	if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))
339d6b92ffaSHans Petter Selasky 		return s;
340d6b92ffaSHans Petter Selasky 
341d6b92ffaSHans Petter Selasky 	mad_decode_field(sw, IB_SW_LINEAR_FDB_TOP_F, &top);
342d6b92ffaSHans Petter Selasky 
343d6b92ffaSHans Petter Selasky 	if (!endlid || endlid > top)
344d6b92ffaSHans Petter Selasky 		endlid = top;
345d6b92ffaSHans Petter Selasky 
346d6b92ffaSHans Petter Selasky 	if (endlid > IB_MAX_UCAST_LID) {
347d6b92ffaSHans Petter Selasky 		IBWARN("illegal lft top %d, truncate to %d", endlid,
348d6b92ffaSHans Petter Selasky 		       IB_MAX_UCAST_LID);
349d6b92ffaSHans Petter Selasky 		endlid = IB_MAX_UCAST_LID;
350d6b92ffaSHans Petter Selasky 	}
351d6b92ffaSHans Petter Selasky 
352d6b92ffaSHans Petter Selasky 	mapnd = remap_node_name(node_name_map, nodeguid, nd);
353d6b92ffaSHans Petter Selasky 
354d6b92ffaSHans Petter Selasky 	printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
355d6b92ffaSHans Petter Selasky 	       " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
356d6b92ffaSHans Petter Selasky 	       mapnd);
357d6b92ffaSHans Petter Selasky 
358d13def78SEric van Gyzen 	free(mapnd);
359d13def78SEric van Gyzen 
360d6b92ffaSHans Petter Selasky 	DEBUG("Switch top is 0x%x\n", top);
361d6b92ffaSHans Petter Selasky 
362d6b92ffaSHans Petter Selasky 	printf("  Lid  Out   Destination\n");
363d6b92ffaSHans Petter Selasky 	printf("       Port     Info \n");
364d6b92ffaSHans Petter Selasky 	startblock = startlid / IB_SMP_DATA_SIZE;
365d6b92ffaSHans Petter Selasky 	endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;
366d6b92ffaSHans Petter Selasky 	for (block = startblock; block < endblock; block++) {
367d6b92ffaSHans Petter Selasky 		int status;
368d6b92ffaSHans Petter Selasky 		DEBUG("reading block %d", block);
369d6b92ffaSHans Petter Selasky 		if (!smp_query_status_via(lft, portid, IB_ATTR_LINEARFORWTBL, block,
370d6b92ffaSHans Petter Selasky 				   0, &status, srcport)) {
371d6b92ffaSHans Petter Selasky 			fprintf(stderr, "SubnGet() failed"
372d6b92ffaSHans Petter Selasky 					"; MAD status 0x%x AM 0x%x\n",
373d6b92ffaSHans Petter Selasky 					status, block);
374d6b92ffaSHans Petter Selasky 			return NULL;
375d6b92ffaSHans Petter Selasky 		}
376d6b92ffaSHans Petter Selasky 		i = block * IB_SMP_DATA_SIZE;
377d6b92ffaSHans Petter Selasky 		e = i + IB_SMP_DATA_SIZE;
378d6b92ffaSHans Petter Selasky 		if (i < startlid)
379d6b92ffaSHans Petter Selasky 			i = startlid;
380d6b92ffaSHans Petter Selasky 		if (e > endlid + 1)
381d6b92ffaSHans Petter Selasky 			e = endlid + 1;
382d6b92ffaSHans Petter Selasky 
383d6b92ffaSHans Petter Selasky 		for (; i < e; i++) {
384d6b92ffaSHans Petter Selasky 			unsigned outport = lft[i % IB_SMP_DATA_SIZE];
385d6b92ffaSHans Petter Selasky 			unsigned valid = (outport <= nports);
386d6b92ffaSHans Petter Selasky 
387d6b92ffaSHans Petter Selasky 			if (!valid && !dump_all)
388d6b92ffaSHans Petter Selasky 				continue;
389d6b92ffaSHans Petter Selasky 			dump_lid(str, sizeof str, i, valid);
390d6b92ffaSHans Petter Selasky 			printf("0x%04x %03u %s\n", i, outport & 0xff, str);
391d6b92ffaSHans Petter Selasky 			n++;
392d6b92ffaSHans Petter Selasky 		}
393d6b92ffaSHans Petter Selasky 	}
394d6b92ffaSHans Petter Selasky 
395d6b92ffaSHans Petter Selasky 	printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
396d6b92ffaSHans Petter Selasky 	return 0;
397d6b92ffaSHans Petter Selasky }
398d6b92ffaSHans Petter Selasky 
process_opt(void * context,int ch,char * optarg)399d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
400d6b92ffaSHans Petter Selasky {
401d6b92ffaSHans Petter Selasky 	switch (ch) {
402d6b92ffaSHans Petter Selasky 	case 'a':
403d6b92ffaSHans Petter Selasky 		dump_all++;
404d6b92ffaSHans Petter Selasky 		break;
405d6b92ffaSHans Petter Selasky 	case 'M':
406d6b92ffaSHans Petter Selasky 		multicast++;
407d6b92ffaSHans Petter Selasky 		break;
408d6b92ffaSHans Petter Selasky 	case 'n':
409d6b92ffaSHans Petter Selasky 		brief++;
410d6b92ffaSHans Petter Selasky 		break;
411d6b92ffaSHans Petter Selasky 	case 1:
412d6b92ffaSHans Petter Selasky 		node_name_map_file = strdup(optarg);
413d6b92ffaSHans Petter Selasky 		break;
414d6b92ffaSHans Petter Selasky 	default:
415d6b92ffaSHans Petter Selasky 		return -1;
416d6b92ffaSHans Petter Selasky 	}
417d6b92ffaSHans Petter Selasky 	return 0;
418d6b92ffaSHans Petter Selasky }
419d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)420d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
421d6b92ffaSHans Petter Selasky {
422d6b92ffaSHans Petter Selasky 	int mgmt_classes[3] =
423d6b92ffaSHans Petter Selasky 	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
424d6b92ffaSHans Petter Selasky 	ib_portid_t portid = { 0 };
425d6b92ffaSHans Petter Selasky 	unsigned startlid = 0, endlid = 0;
426d6b92ffaSHans Petter Selasky 	char *err;
427d6b92ffaSHans Petter Selasky 
428d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
429d6b92ffaSHans Petter Selasky 		{"all", 'a', 0, NULL, "show all lids, even invalid entries"},
430d6b92ffaSHans Petter Selasky 		{"no_dests", 'n', 0, NULL,
431d6b92ffaSHans Petter Selasky 		 "do not try to resolve destinations"},
432d6b92ffaSHans Petter Selasky 		{"Multicast", 'M', 0, NULL, "show multicast forwarding tables"},
433d6b92ffaSHans Petter Selasky 		{"node-name-map", 1, 1, "<file>", "node name map file"},
434d6b92ffaSHans Petter Selasky 		{0}
435d6b92ffaSHans Petter Selasky 	};
436d6b92ffaSHans Petter Selasky 	char usage_args[] = "[<dest dr_path|lid|guid> [<startlid> [<endlid>]]]";
437d6b92ffaSHans Petter Selasky 	const char *usage_examples[] = {
438d6b92ffaSHans Petter Selasky 		" -- Unicast examples:",
439d6b92ffaSHans Petter Selasky 		"4\t# dump all lids with valid out ports of switch with lid 4",
440d6b92ffaSHans Petter Selasky 		"-a 4\t# same, but dump all lids, even with invalid out ports",
441d6b92ffaSHans Petter Selasky 		"-n 4\t# simple dump format - no destination resolving",
442d6b92ffaSHans Petter Selasky 		"4 10\t# dump lids starting from 10",
443d6b92ffaSHans Petter Selasky 		"4 0x10 0x20\t# dump lid range",
444d6b92ffaSHans Petter Selasky 		"-G 0x08f1040023\t# resolve switch by GUID",
445d6b92ffaSHans Petter Selasky 		"-D 0,1\t# resolve switch by direct path",
446d6b92ffaSHans Petter Selasky 		" -- Multicast examples:",
447d6b92ffaSHans Petter Selasky 		"-M 4\t# dump all non empty mlids of switch with lid 4",
448d6b92ffaSHans Petter Selasky 		"-M 4 0xc010 0xc020\t# same, but with range",
449d6b92ffaSHans Petter Selasky 		"-M -n 4\t# simple dump format",
450d6b92ffaSHans Petter Selasky 		NULL,
451d6b92ffaSHans Petter Selasky 	};
452d6b92ffaSHans Petter Selasky 
453d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, NULL, "K", opts, process_opt,
454d6b92ffaSHans Petter Selasky 			    usage_args, usage_examples);
455d6b92ffaSHans Petter Selasky 
456d6b92ffaSHans Petter Selasky 	argc -= optind;
457d6b92ffaSHans Petter Selasky 	argv += optind;
458d6b92ffaSHans Petter Selasky 
459d6b92ffaSHans Petter Selasky 	if (!argc)
460d6b92ffaSHans Petter Selasky 		ibdiag_show_usage();
461d6b92ffaSHans Petter Selasky 
462d6b92ffaSHans Petter Selasky 	if (argc > 1)
463d6b92ffaSHans Petter Selasky 		startlid = strtoul(argv[1], 0, 0);
464d6b92ffaSHans Petter Selasky 	if (argc > 2)
465d6b92ffaSHans Petter Selasky 		endlid = strtoul(argv[2], 0, 0);
466d6b92ffaSHans Petter Selasky 
467d6b92ffaSHans Petter Selasky 	node_name_map = open_node_name_map(node_name_map_file);
468d6b92ffaSHans Petter Selasky 
469d6b92ffaSHans Petter Selasky 	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
470d6b92ffaSHans Petter Selasky 	if (!srcport)
471d6b92ffaSHans Petter Selasky 		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
472d6b92ffaSHans Petter Selasky 
473d6b92ffaSHans Petter Selasky 	smp_mkey_set(srcport, ibd_mkey);
474d6b92ffaSHans Petter Selasky 
475d6b92ffaSHans Petter Selasky 	if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
476d6b92ffaSHans Petter Selasky 			       ibd_dest_type, ibd_sm_id, srcport) < 0)
477d6b92ffaSHans Petter Selasky 		IBEXIT("can't resolve destination port %s", argv[0]);
478d6b92ffaSHans Petter Selasky 
479d6b92ffaSHans Petter Selasky 	if (multicast)
480d6b92ffaSHans Petter Selasky 		err = dump_multicast_tables(&portid, startlid, endlid);
481d6b92ffaSHans Petter Selasky 	else
482d6b92ffaSHans Petter Selasky 		err = dump_unicast_tables(&portid, startlid, endlid);
483d6b92ffaSHans Petter Selasky 
484d6b92ffaSHans Petter Selasky 	if (err)
485d6b92ffaSHans Petter Selasky 		IBEXIT("dump tables: %s", err);
486d6b92ffaSHans Petter Selasky 
487d6b92ffaSHans Petter Selasky 	mad_rpc_close_port(srcport);
488d6b92ffaSHans Petter Selasky 	close_node_name_map(node_name_map);
489d6b92ffaSHans Petter Selasky 	exit(0);
490d6b92ffaSHans Petter Selasky }
491