2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2009-2011 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 2013 Lawrence Livermore National Security. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #endif /* HAVE_CONFIG_H */
46 #include <netinet/in.h>
49 #include <infiniband/umad.h>
50 #include <infiniband/mad.h>
51 #include <complib/cl_nodenamemap.h>
53 #include <infiniband/ibnetdisc.h>
55 #include "ibdiag_common.h"
57 struct ibmad_port *srcport;
59 unsigned startlid = 0, endlid = 0;
61 static int brief, dump_all, multicast;
63 static char *node_name_map_file = NULL;
64 static nn_map_t *node_name_map = NULL;
66 #define IB_MLIDS_IN_BLOCK (IB_SMP_DATA_SIZE/2)
68 int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
69 uint16_t mft[16][IB_MLIDS_IN_BLOCK])
72 unsigned i, chunk, bit, nonzero = 0;
76 unsigned chunks = ALIGN(nports + 1, 16) / 16;
77 for (i = 0; i < chunks; i++) {
78 mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
81 n += snprintf(str + n, strlen - n, "%04hx", mask);
87 if (!nonzero && !dump_all) {
93 for (i = 0; i <= nports; i++) {
97 mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
100 str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
101 str[i * 2 + 1] = ' ';
103 if (!nonzero && !dump_all) {
111 uint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
113 void dump_multicast_tables(ibnd_node_t * node, unsigned startlid,
114 unsigned endlid, struct ibmad_port * mad_port)
116 ib_portid_t *portid = &node->path_portid;
117 char nd[IB_SMP_DATA_SIZE] = { 0 };
122 unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
127 memcpy(nd, node->nodedesc, strlen(node->nodedesc));
128 nports = node->numports;
129 nodeguid = node->guid;
131 mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_CAP_F, &cap);
132 mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_TOP_F, &top);
134 if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)
135 endlid = IB_MIN_MCAST_LID + cap - 1;
136 if (!dump_all && top && top < endlid) {
137 if (top < IB_MIN_MCAST_LID - 1)
138 IBWARN("illegal top mlid %x", top);
144 startlid = IB_MIN_MCAST_LID;
145 else if (startlid < IB_MIN_MCAST_LID) {
146 IBWARN("illegal start mlid %x, set to %x", startlid,
148 startlid = IB_MIN_MCAST_LID;
151 if (endlid > IB_MAX_MCAST_LID) {
152 IBWARN("illegal end mlid %x, truncate to %x", endlid,
154 endlid = IB_MAX_MCAST_LID;
157 mapnd = remap_node_name(node_name_map, nodeguid, nd);
159 printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
160 " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
164 printf(" MLid Port Mask\n");
167 for (i = 0, s = str; i <= nports; i++) {
168 *s++ = (i % 10) ? ' ' : '0' + i / 10;
172 printf(" %s\n", str);
174 for (i = 0, s = str; i <= nports; i++)
175 s += sprintf(s, "%d ", i % 10);
176 printf(" Ports: %s\n", str);
180 printf("Switch multicast mlid capability is %d top is 0x%x\n",
183 chunks = ALIGN(nports + 1, 16) / 16;
185 startblock = startlid / IB_MLIDS_IN_BLOCK;
186 lastblock = endlid / IB_MLIDS_IN_BLOCK;
187 for (block = startblock; block <= lastblock; block++) {
188 for (j = 0; j < chunks; j++) {
190 mod = (block - IB_MIN_MCAST_LID / IB_MLIDS_IN_BLOCK)
193 DEBUG("reading block %x chunk %d mod %x", block, j,
195 if (!smp_query_status_via
196 (mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0,
197 &status, mad_port)) {
198 fprintf(stderr, "SubnGet(MFT) failed on switch "
199 "'%s' %s Node GUID 0x%"PRIx64
200 " SMA LID %d; MAD status 0x%x "
202 mapnd, portid2str(portid),
203 node->guid, node->smalid,
208 i = block * IB_MLIDS_IN_BLOCK;
209 e = i + IB_MLIDS_IN_BLOCK;
216 if (dump_mlid(str, sizeof str, i, nports, mft) == 0)
218 printf("0x%04x %s\n", i, str);
223 printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
228 int dump_lid(char *str, int str_len, int lid, int valid,
229 ibnd_fabric_t *fabric,
230 int * last_port_lid, int * base_port_lid,
233 char nd[IB_SMP_DATA_SIZE] = { 0 };
235 ibnd_port_t *port = NULL;
237 char ntype[50], sguid[30];
239 int baselid, lmc, type;
248 if (lid <= *last_port_lid) {
250 return snprintf(str, str_len,
251 ": (path #%d - illegal port)",
252 lid - *base_port_lid);
254 return snprintf(str, str_len,
255 ": (path #%d out of %d)",
256 lid - *base_port_lid + 1,
257 *last_port_lid - *base_port_lid + 1);
259 return snprintf(str, str_len,
260 ": (path #%d out of %d: portguid %s)",
261 lid - *base_port_lid + 1,
262 *last_port_lid - *base_port_lid + 1,
263 mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
264 sizeof sguid, portguid));
269 return snprintf(str, str_len, ": (illegal port)");
273 port = ibnd_find_port_lid(fabric, lid);
275 return snprintf(str, str_len, ": (node info not available fabric scan)");
278 nodeguid = port->node->guid;
279 *portguid = port->guid;
280 type = port->node->type;
282 baselid = port->base_lid;
285 memcpy(nd, port->node->nodedesc, strlen(port->node->nodedesc));
288 *base_port_lid = baselid;
289 *last_port_lid = baselid + (1 << lmc) - 1;
292 mapnd = remap_node_name(node_name_map, nodeguid, nd);
294 rc = snprintf(str, str_len, ": (%s portguid %s: '%s')",
295 mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype,
296 &type), mad_dump_val(IB_NODE_PORT_GUID_F,
305 void dump_unicast_tables(ibnd_node_t * node, int startlid, int endlid,
306 struct ibmad_port *mad_port, ibnd_fabric_t *fabric)
308 ib_portid_t * portid = &node->path_portid;
309 char lft[IB_SMP_DATA_SIZE] = { 0 };
310 char nd[IB_SMP_DATA_SIZE] = { 0 };
313 int block, i, e, top;
315 int n = 0, startblock, endblock;
317 int last_port_lid = 0, base_port_lid = 0;
318 uint64_t portguid = 0;
320 mad_decode_field(node->switchinfo, IB_SW_LINEAR_FDB_TOP_F, &top);
321 nodeguid = node->guid;
322 nports = node->numports;
323 memcpy(nd, node->nodedesc, strlen(node->nodedesc));
325 if (!endlid || endlid > top)
328 if (endlid > IB_MAX_UCAST_LID) {
329 IBWARN("illegal lft top %d, truncate to %d", endlid,
331 endlid = IB_MAX_UCAST_LID;
334 mapnd = remap_node_name(node_name_map, nodeguid, nd);
336 printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
337 " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
340 DEBUG("Switch top is 0x%x\n", top);
342 printf(" Lid Out Destination\n");
343 printf(" Port Info \n");
344 startblock = startlid / IB_SMP_DATA_SIZE;
345 endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;
346 for (block = startblock; block < endblock; block++) {
348 DEBUG("reading block %d", block);
349 if (!smp_query_status_via(lft, portid, IB_ATTR_LINEARFORWTBL, block,
350 0, &status, mad_port)) {
351 fprintf(stderr, "SubnGet(LFT) failed on switch "
352 "'%s' %s Node GUID 0x%"PRIx64
353 " SMA LID %d; MAD status 0x%x AM 0x%x\n",
354 mapnd, portid2str(portid),
355 node->guid, node->smalid,
358 i = block * IB_SMP_DATA_SIZE;
359 e = i + IB_SMP_DATA_SIZE;
366 unsigned outport = lft[i % IB_SMP_DATA_SIZE];
367 unsigned valid = (outport <= nports);
369 if (!valid && !dump_all)
371 dump_lid(str, sizeof str, i, valid, fabric,
372 &last_port_lid, &base_port_lid, &portguid);
373 printf("0x%04x %03u %s\n", i, outport & 0xff, str);
378 printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
382 void dump_node(ibnd_node_t *node, struct ibmad_port *mad_port,
383 ibnd_fabric_t *fabric)
386 dump_multicast_tables(node, startlid, endlid, mad_port);
388 dump_unicast_tables(node, startlid, endlid,
392 void process_switch(ibnd_node_t * node, void *fabric)
394 dump_node(node, srcport, (ibnd_fabric_t *)fabric);
397 static int process_opt(void *context, int ch, char *optarg)
410 node_name_map_file = strdup(optarg);
418 int main(int argc, char **argv)
421 int mgmt_classes[3] =
422 { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
424 struct ibnd_config config = { 0 };
425 ibnd_fabric_t *fabric = NULL;
427 const struct ibdiag_opt opts[] = {
428 {"all", 'a', 0, NULL, "show all lids, even invalid entries"},
429 {"no_dests", 'n', 0, NULL,
430 "do not try to resolve destinations"},
431 {"Multicast", 'M', 0, NULL, "show multicast forwarding tables"},
432 {"node-name-map", 1, 1, "<file>", "node name map file"},
435 char usage_args[] = "[<dest dr_path|lid|guid> [<startlid> [<endlid>]]]";
436 const char *usage_examples[] = {
437 " -- Unicast examples:",
438 "-a\t# same, but dump all lids, even with invalid out ports",
439 "-n\t# simple dump format - no destination resolving",
440 "10\t# dump lids starting from 10",
441 "0x10 0x20\t# dump lid range",
442 " -- Multicast examples:",
443 "-M\t# dump all non empty mlids of switch with lid 4",
444 "-M 0xc010 0xc020\t# same, but with range",
445 "-M -n\t# simple dump format",
449 ibdiag_process_opts(argc, argv, &config, "KGDLs", opts, process_opt,
450 usage_args, usage_examples);
456 startlid = strtoul(argv[0], 0, 0);
458 endlid = strtoul(argv[1], 0, 0);
460 node_name_map = open_node_name_map(node_name_map_file);
463 config.timeout_ms = ibd_timeout;
465 config.flags = ibd_ibnetdisc_flags;
466 config.mkey = ibd_mkey;
468 if ((fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL,
471 srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
474 "Failed to open '%s' port '%d'\n", ibd_ca, ibd_ca_port);
478 smp_mkey_set(srcport, ibd_mkey);
481 mad_rpc_set_timeout(srcport, ibd_timeout);
484 ibnd_iter_nodes_type(fabric, process_switch, IB_NODE_SWITCH, fabric);
486 mad_rpc_close_port(srcport);
489 fprintf(stderr, "Failed to discover fabric\n");
493 ibnd_destroy_fabric(fabric);
495 close_node_name_map(node_name_map);