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