1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 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 <getopt.h>
44d6b92ffaSHans Petter Selasky #include <netinet/in.h>
45d6b92ffaSHans Petter Selasky 
46d6b92ffaSHans Petter Selasky #define __STDC_FORMAT_MACROS
47d6b92ffaSHans Petter Selasky #include <inttypes.h>
48d6b92ffaSHans Petter Selasky 
49d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
50d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
51d6b92ffaSHans Petter Selasky #include <complib/cl_nodenamemap.h>
52d6b92ffaSHans Petter Selasky 
53d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
54d6b92ffaSHans Petter Selasky 
55d6b92ffaSHans Petter Selasky struct ibmad_port *srcport;
56d6b92ffaSHans Petter Selasky 
57d6b92ffaSHans Petter Selasky static op_fn_t node_desc, node_info, port_info, switch_info, pkey_table,
58d6b92ffaSHans Petter Selasky     sl2vl_table, vlarb_table, guid_info, mlnx_ext_port_info, port_info_extended;
59d6b92ffaSHans Petter Selasky 
60d6b92ffaSHans Petter Selasky static const match_rec_t match_tbl[] = {
61d6b92ffaSHans Petter Selasky 	{"NodeInfo", "NI", node_info, 0, ""},
62d6b92ffaSHans Petter Selasky 	{"NodeDesc", "ND", node_desc, 0, ""},
63d6b92ffaSHans Petter Selasky 	{"PortInfo", "PI", port_info, 1, ""},
64d6b92ffaSHans Petter Selasky 	{"PortInfoExtended", "PIE", port_info_extended, 1, ""},
65d6b92ffaSHans Petter Selasky 	{"SwitchInfo", "SI", switch_info, 0, ""},
66d6b92ffaSHans Petter Selasky 	{"PKeyTable", "PKeys", pkey_table, 1, ""},
67d6b92ffaSHans Petter Selasky 	{"SL2VLTable", "SL2VL", sl2vl_table, 1, ""},
68d6b92ffaSHans Petter Selasky 	{"VLArbitration", "VLArb", vlarb_table, 1, ""},
69d6b92ffaSHans Petter Selasky 	{"GUIDInfo", "GI", guid_info, 0, ""},
70d6b92ffaSHans Petter Selasky 	{"MlnxExtPortInfo", "MEPI", mlnx_ext_port_info, 1, ""},
71d6b92ffaSHans Petter Selasky 	{0}
72d6b92ffaSHans Petter Selasky };
73d6b92ffaSHans Petter Selasky 
74d6b92ffaSHans Petter Selasky static char *node_name_map_file = NULL;
75d6b92ffaSHans Petter Selasky static nn_map_t *node_name_map = NULL;
76d6b92ffaSHans Petter Selasky static int extended_speeds = 0;
77d6b92ffaSHans Petter Selasky 
78d6b92ffaSHans Petter Selasky /*******************************************/
node_desc(ib_portid_t * dest,char ** argv,int argc)79d6b92ffaSHans Petter Selasky static char *node_desc(ib_portid_t * dest, char **argv, int argc)
80d6b92ffaSHans Petter Selasky {
81d6b92ffaSHans Petter Selasky 	int node_type, l;
82d6b92ffaSHans Petter Selasky 	uint64_t node_guid;
83d6b92ffaSHans Petter Selasky 	char nd[IB_SMP_DATA_SIZE] = { 0 };
84d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
85d6b92ffaSHans Petter Selasky 	char dots[128];
86d6b92ffaSHans Petter Selasky 	char *nodename = NULL;
87d6b92ffaSHans Petter Selasky 
88d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
89d6b92ffaSHans Petter Selasky 		return "node info query failed";
90d6b92ffaSHans Petter Selasky 
91d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_TYPE_F, &node_type);
92d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_GUID_F, &node_guid);
93d6b92ffaSHans Petter Selasky 
94d6b92ffaSHans Petter Selasky 	if (!smp_query_via(nd, dest, IB_ATTR_NODE_DESC, 0, 0, srcport))
95d6b92ffaSHans Petter Selasky 		return "node desc query failed";
96d6b92ffaSHans Petter Selasky 
97d6b92ffaSHans Petter Selasky 	nodename = remap_node_name(node_name_map, node_guid, nd);
98d6b92ffaSHans Petter Selasky 
99d6b92ffaSHans Petter Selasky 	l = strlen(nodename);
100d6b92ffaSHans Petter Selasky 	if (l < 32) {
101d6b92ffaSHans Petter Selasky 		memset(dots, '.', 32 - l);
102d6b92ffaSHans Petter Selasky 		dots[32 - l] = '\0';
103d6b92ffaSHans Petter Selasky 	} else {
104d6b92ffaSHans Petter Selasky 		dots[0] = '.';
105d6b92ffaSHans Petter Selasky 		dots[1] = '\0';
106d6b92ffaSHans Petter Selasky 	}
107d6b92ffaSHans Petter Selasky 
108d6b92ffaSHans Petter Selasky 	printf("Node Description:%s%s\n", dots, nodename);
109d6b92ffaSHans Petter Selasky 	free(nodename);
110d6b92ffaSHans Petter Selasky 	return 0;
111d6b92ffaSHans Petter Selasky }
112d6b92ffaSHans Petter Selasky 
node_info(ib_portid_t * dest,char ** argv,int argc)113d6b92ffaSHans Petter Selasky static char *node_info(ib_portid_t * dest, char **argv, int argc)
114d6b92ffaSHans Petter Selasky {
115d6b92ffaSHans Petter Selasky 	char buf[2048];
116d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE] = { 0 };
117d6b92ffaSHans Petter Selasky 
118d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
119d6b92ffaSHans Petter Selasky 		return "node info query failed";
120d6b92ffaSHans Petter Selasky 
121d6b92ffaSHans Petter Selasky 	mad_dump_nodeinfo(buf, sizeof buf, data, sizeof data);
122d6b92ffaSHans Petter Selasky 
123d6b92ffaSHans Petter Selasky 	printf("# Node info: %s\n%s", portid2str(dest), buf);
124d6b92ffaSHans Petter Selasky 	return 0;
125d6b92ffaSHans Petter Selasky }
126d6b92ffaSHans Petter Selasky 
port_info_extended(ib_portid_t * dest,char ** argv,int argc)127d6b92ffaSHans Petter Selasky static char *port_info_extended(ib_portid_t * dest, char **argv, int argc)
128d6b92ffaSHans Petter Selasky {
129d6b92ffaSHans Petter Selasky 	char buf[2048];
130d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
131d6b92ffaSHans Petter Selasky 	int portnum = 0;
132d6b92ffaSHans Petter Selasky 
133d6b92ffaSHans Petter Selasky 	if (argc > 0)
134d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
135d6b92ffaSHans Petter Selasky 
136d6b92ffaSHans Petter Selasky 	if (!is_port_info_extended_supported(dest, portnum, srcport))
137d6b92ffaSHans Petter Selasky 		return "port info extended not supported";
138d6b92ffaSHans Petter Selasky 
139d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO_EXT, portnum, 0,
140d6b92ffaSHans Petter Selasky 			   srcport))
141d6b92ffaSHans Petter Selasky 		return "port info extended query failed";
142d6b92ffaSHans Petter Selasky 
143d6b92ffaSHans Petter Selasky 	mad_dump_portinfo_ext(buf, sizeof buf, data, sizeof data);
144d6b92ffaSHans Petter Selasky 	printf("# Port info Extended: %s port %d\n%s", portid2str(dest),
145d6b92ffaSHans Petter Selasky 	       portnum, buf);
146d6b92ffaSHans Petter Selasky 	return 0;
147d6b92ffaSHans Petter Selasky }
148d6b92ffaSHans Petter Selasky 
port_info(ib_portid_t * dest,char ** argv,int argc)149d6b92ffaSHans Petter Selasky static char *port_info(ib_portid_t * dest, char **argv, int argc)
150d6b92ffaSHans Petter Selasky {
151d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE] = { 0 };
152d6b92ffaSHans Petter Selasky 	int portnum = 0, orig_portnum;
153d6b92ffaSHans Petter Selasky 
154d6b92ffaSHans Petter Selasky 	if (argc > 0)
155d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
156d6b92ffaSHans Petter Selasky 	orig_portnum = portnum;
157d6b92ffaSHans Petter Selasky 	if (extended_speeds)
158d6b92ffaSHans Petter Selasky 		portnum |= 1 << 31;
159d6b92ffaSHans Petter Selasky 
160d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
161d6b92ffaSHans Petter Selasky 		return "port info query failed";
162d6b92ffaSHans Petter Selasky 
163d6b92ffaSHans Petter Selasky 	printf("# Port info: %s port %d\n", portid2str(dest), orig_portnum);
164d6b92ffaSHans Petter Selasky 	dump_portinfo(data, 0);
165d6b92ffaSHans Petter Selasky 	return 0;
166d6b92ffaSHans Petter Selasky }
167d6b92ffaSHans Petter Selasky 
mlnx_ext_port_info(ib_portid_t * dest,char ** argv,int argc)168d6b92ffaSHans Petter Selasky static char *mlnx_ext_port_info(ib_portid_t * dest, char **argv, int argc)
169d6b92ffaSHans Petter Selasky {
170d6b92ffaSHans Petter Selasky 	char buf[2300];
171d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE];
172d6b92ffaSHans Petter Selasky 	int portnum = 0;
173d6b92ffaSHans Petter Selasky 
174d6b92ffaSHans Petter Selasky 	if (argc > 0)
175d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
176d6b92ffaSHans Petter Selasky 
177d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO, portnum, 0, srcport))
178d6b92ffaSHans Petter Selasky 		return "Mellanox ext port info query failed";
179d6b92ffaSHans Petter Selasky 
180d6b92ffaSHans Petter Selasky 	mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, sizeof data);
181d6b92ffaSHans Petter Selasky 
182d6b92ffaSHans Petter Selasky 	printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
183d6b92ffaSHans Petter Selasky 	return 0;
184d6b92ffaSHans Petter Selasky }
185d6b92ffaSHans Petter Selasky 
switch_info(ib_portid_t * dest,char ** argv,int argc)186d6b92ffaSHans Petter Selasky static char *switch_info(ib_portid_t * dest, char **argv, int argc)
187d6b92ffaSHans Petter Selasky {
188d6b92ffaSHans Petter Selasky 	char buf[2048];
189d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE] = { 0 };
190d6b92ffaSHans Petter Selasky 
191d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
192d6b92ffaSHans Petter Selasky 		return "switch info query failed";
193d6b92ffaSHans Petter Selasky 
194d6b92ffaSHans Petter Selasky 	mad_dump_switchinfo(buf, sizeof buf, data, sizeof data);
195d6b92ffaSHans Petter Selasky 
196d6b92ffaSHans Petter Selasky 	printf("# Switch info: %s\n%s", portid2str(dest), buf);
197d6b92ffaSHans Petter Selasky 	return 0;
198d6b92ffaSHans Petter Selasky }
199d6b92ffaSHans Petter Selasky 
pkey_table(ib_portid_t * dest,char ** argv,int argc)200d6b92ffaSHans Petter Selasky static char *pkey_table(ib_portid_t * dest, char **argv, int argc)
201d6b92ffaSHans Petter Selasky {
202d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
203d6b92ffaSHans Petter Selasky 	int i, j, k;
204d6b92ffaSHans Petter Selasky 	uint16_t *p;
205d6b92ffaSHans Petter Selasky 	unsigned mod;
206d6b92ffaSHans Petter Selasky 	int n, t, phy_ports;
207d6b92ffaSHans Petter Selasky 	int portnum = 0;
208d6b92ffaSHans Petter Selasky 
209d6b92ffaSHans Petter Selasky 	if (argc > 0)
210d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
211d6b92ffaSHans Petter Selasky 
212d6b92ffaSHans Petter Selasky 	/* Get the partition capacity */
213d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
214d6b92ffaSHans Petter Selasky 		return "node info query failed";
215d6b92ffaSHans Petter Selasky 
216d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_TYPE_F, &t);
217d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_NPORTS_F, &phy_ports);
218d6b92ffaSHans Petter Selasky 	if (portnum > phy_ports)
219d6b92ffaSHans Petter Selasky 		return "invalid port number";
220d6b92ffaSHans Petter Selasky 
221d6b92ffaSHans Petter Selasky 	if ((t == IB_NODE_SWITCH) && (portnum != 0)) {
222d6b92ffaSHans Petter Selasky 		if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0, 0,
223d6b92ffaSHans Petter Selasky 				   srcport))
224d6b92ffaSHans Petter Selasky 			return "switch info failed";
225d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_SW_PARTITION_ENFORCE_CAP_F, &n);
226d6b92ffaSHans Petter Selasky 	} else
227d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_NODE_PARTITION_CAP_F, &n);
228d6b92ffaSHans Petter Selasky 
229d6b92ffaSHans Petter Selasky 	for (i = 0; i < (n + 31) / 32; i++) {
230d6b92ffaSHans Petter Selasky 		mod = i | (portnum << 16);
231d6b92ffaSHans Petter Selasky 		if (!smp_query_via(data, dest, IB_ATTR_PKEY_TBL, mod, 0,
232d6b92ffaSHans Petter Selasky 				   srcport))
233d6b92ffaSHans Petter Selasky 			return "pkey table query failed";
234d6b92ffaSHans Petter Selasky 		if (i + 1 == (n + 31) / 32)
235d6b92ffaSHans Petter Selasky 			k = ((n + 7 - i * 32) / 8) * 8;
236d6b92ffaSHans Petter Selasky 		else
237d6b92ffaSHans Petter Selasky 			k = 32;
238d6b92ffaSHans Petter Selasky 		p = (uint16_t *) data;
239d6b92ffaSHans Petter Selasky 		for (j = 0; j < k; j += 8, p += 8) {
240d6b92ffaSHans Petter Selasky 			printf
241d6b92ffaSHans Petter Selasky 			    ("%4u: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
242d6b92ffaSHans Petter Selasky 			     (i * 32) + j, ntohs(p[0]), ntohs(p[1]),
243d6b92ffaSHans Petter Selasky 			     ntohs(p[2]), ntohs(p[3]), ntohs(p[4]), ntohs(p[5]),
244d6b92ffaSHans Petter Selasky 			     ntohs(p[6]), ntohs(p[7]));
245d6b92ffaSHans Petter Selasky 		}
246d6b92ffaSHans Petter Selasky 	}
247d6b92ffaSHans Petter Selasky 	printf("%d pkeys capacity for this port\n", n);
248d6b92ffaSHans Petter Selasky 
249d6b92ffaSHans Petter Selasky 	return 0;
250d6b92ffaSHans Petter Selasky }
251d6b92ffaSHans Petter Selasky 
sl2vl_dump_table_entry(ib_portid_t * dest,int in,int out)252d6b92ffaSHans Petter Selasky static char *sl2vl_dump_table_entry(ib_portid_t * dest, int in, int out)
253d6b92ffaSHans Petter Selasky {
254d6b92ffaSHans Petter Selasky 	char buf[2048];
255d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE] = { 0 };
256d6b92ffaSHans Petter Selasky 	int portnum = (in << 8) | out;
257d6b92ffaSHans Petter Selasky 
258d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_SLVL_TABLE, portnum, 0, srcport))
259d6b92ffaSHans Petter Selasky 		return "slvl query failed";
260d6b92ffaSHans Petter Selasky 
261d6b92ffaSHans Petter Selasky 	mad_dump_sltovl(buf, sizeof buf, data, sizeof data);
262d6b92ffaSHans Petter Selasky 	printf("ports: in %2d, out %2d: ", in, out);
263d6b92ffaSHans Petter Selasky 	printf("%s", buf);
264d6b92ffaSHans Petter Selasky 	return 0;
265d6b92ffaSHans Petter Selasky }
266d6b92ffaSHans Petter Selasky 
sl2vl_table(ib_portid_t * dest,char ** argv,int argc)267d6b92ffaSHans Petter Selasky static char *sl2vl_table(ib_portid_t * dest, char **argv, int argc)
268d6b92ffaSHans Petter Selasky {
269d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
270d6b92ffaSHans Petter Selasky 	int type, num_ports, portnum = 0;
271d6b92ffaSHans Petter Selasky 	int i;
272d6b92ffaSHans Petter Selasky 	char *ret;
273d6b92ffaSHans Petter Selasky 
274d6b92ffaSHans Petter Selasky 	if (argc > 0)
275d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
276d6b92ffaSHans Petter Selasky 
277d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
278d6b92ffaSHans Petter Selasky 		return "node info query failed";
279d6b92ffaSHans Petter Selasky 
280d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_TYPE_F, &type);
281d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
282d6b92ffaSHans Petter Selasky 	if (portnum > num_ports)
283d6b92ffaSHans Petter Selasky 		return "invalid port number";
284d6b92ffaSHans Petter Selasky 
285d6b92ffaSHans Petter Selasky 	printf("# SL2VL table: %s\n", portid2str(dest));
286d6b92ffaSHans Petter Selasky 	printf("#                 SL: |");
287d6b92ffaSHans Petter Selasky 	for (i = 0; i < 16; i++)
288d6b92ffaSHans Petter Selasky 		printf("%2d|", i);
289d6b92ffaSHans Petter Selasky 	printf("\n");
290d6b92ffaSHans Petter Selasky 
291d6b92ffaSHans Petter Selasky 	if (type != IB_NODE_SWITCH)
292d6b92ffaSHans Petter Selasky 		return sl2vl_dump_table_entry(dest, 0, 0);
293d6b92ffaSHans Petter Selasky 
294d6b92ffaSHans Petter Selasky 	for (i = 0; i <= num_ports; i++) {
295d6b92ffaSHans Petter Selasky 		ret = sl2vl_dump_table_entry(dest, i, portnum);
296d6b92ffaSHans Petter Selasky 		if (ret)
297d6b92ffaSHans Petter Selasky 			return ret;
298d6b92ffaSHans Petter Selasky 	}
299d6b92ffaSHans Petter Selasky 	return 0;
300d6b92ffaSHans Petter Selasky }
301d6b92ffaSHans Petter Selasky 
vlarb_dump_table_entry(ib_portid_t * dest,int portnum,int offset,unsigned cap)302d6b92ffaSHans Petter Selasky static char *vlarb_dump_table_entry(ib_portid_t * dest, int portnum, int offset,
303d6b92ffaSHans Petter Selasky 				    unsigned cap)
304d6b92ffaSHans Petter Selasky {
305d6b92ffaSHans Petter Selasky 	char buf[2048];
306d6b92ffaSHans Petter Selasky 	char data[IB_SMP_DATA_SIZE] = { 0 };
307d6b92ffaSHans Petter Selasky 
308d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_VL_ARBITRATION,
309d6b92ffaSHans Petter Selasky 			   (offset << 16) | portnum, 0, srcport))
310d6b92ffaSHans Petter Selasky 		return "vl arb query failed";
311d6b92ffaSHans Petter Selasky 	mad_dump_vlarbitration(buf, sizeof(buf), data, cap * 2);
312d6b92ffaSHans Petter Selasky 	printf("%s", buf);
313d6b92ffaSHans Petter Selasky 	return 0;
314d6b92ffaSHans Petter Selasky }
315d6b92ffaSHans Petter Selasky 
vlarb_dump_table(ib_portid_t * dest,int portnum,char * name,int offset,int cap)316d6b92ffaSHans Petter Selasky static char *vlarb_dump_table(ib_portid_t * dest, int portnum,
317d6b92ffaSHans Petter Selasky 			      char *name, int offset, int cap)
318d6b92ffaSHans Petter Selasky {
319d6b92ffaSHans Petter Selasky 	char *ret;
320d6b92ffaSHans Petter Selasky 
321d6b92ffaSHans Petter Selasky 	printf("# %s priority VL Arbitration Table:", name);
322d6b92ffaSHans Petter Selasky 	ret = vlarb_dump_table_entry(dest, portnum, offset,
323d6b92ffaSHans Petter Selasky 				     cap < 32 ? cap : 32);
324d6b92ffaSHans Petter Selasky 	if (!ret && cap > 32)
325d6b92ffaSHans Petter Selasky 		ret = vlarb_dump_table_entry(dest, portnum, offset + 1,
326d6b92ffaSHans Petter Selasky 					     cap - 32);
327d6b92ffaSHans Petter Selasky 	return ret;
328d6b92ffaSHans Petter Selasky }
329d6b92ffaSHans Petter Selasky 
vlarb_table(ib_portid_t * dest,char ** argv,int argc)330d6b92ffaSHans Petter Selasky static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
331d6b92ffaSHans Petter Selasky {
332d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
333d6b92ffaSHans Petter Selasky 	int portnum = 0;
334d6b92ffaSHans Petter Selasky 	int type, enhsp0, lowcap, highcap;
335d6b92ffaSHans Petter Selasky 	char *ret = 0;
336d6b92ffaSHans Petter Selasky 
337d6b92ffaSHans Petter Selasky 	if (argc > 0)
338d6b92ffaSHans Petter Selasky 		portnum = strtol(argv[0], 0, 0);
339d6b92ffaSHans Petter Selasky 
340d6b92ffaSHans Petter Selasky 	/* port number of 0 could mean SP0 or port MAD arrives on */
341d6b92ffaSHans Petter Selasky 	if (portnum == 0) {
342d6b92ffaSHans Petter Selasky 		if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0,
343d6b92ffaSHans Petter Selasky 				   srcport))
344d6b92ffaSHans Petter Selasky 			return "node info query failed";
345d6b92ffaSHans Petter Selasky 
346d6b92ffaSHans Petter Selasky 		mad_decode_field(data, IB_NODE_TYPE_F, &type);
347d6b92ffaSHans Petter Selasky 		if (type == IB_NODE_SWITCH) {
348d6b92ffaSHans Petter Selasky 			memset(data, 0, sizeof(data));
349d6b92ffaSHans Petter Selasky 			if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0,
350d6b92ffaSHans Petter Selasky 					   0, srcport))
351d6b92ffaSHans Petter Selasky 				return "switch info query failed";
352d6b92ffaSHans Petter Selasky 			mad_decode_field(data, IB_SW_ENHANCED_PORT0_F, &enhsp0);
353d6b92ffaSHans Petter Selasky 			if (!enhsp0) {
354d6b92ffaSHans Petter Selasky 				printf
355d6b92ffaSHans Petter Selasky 				    ("# No VLArbitration tables (BSP0): %s port %d\n",
356d6b92ffaSHans Petter Selasky 				     portid2str(dest), 0);
357d6b92ffaSHans Petter Selasky 				return 0;
358d6b92ffaSHans Petter Selasky 			}
359d6b92ffaSHans Petter Selasky 			memset(data, 0, sizeof(data));
360d6b92ffaSHans Petter Selasky 		}
361d6b92ffaSHans Petter Selasky 	}
362d6b92ffaSHans Petter Selasky 
363d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
364d6b92ffaSHans Petter Selasky 		return "port info query failed";
365d6b92ffaSHans Petter Selasky 
366d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_VL_ARBITRATION_LOW_CAP_F, &lowcap);
367d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_VL_ARBITRATION_HIGH_CAP_F, &highcap);
368d6b92ffaSHans Petter Selasky 
369d6b92ffaSHans Petter Selasky 	printf("# VLArbitration tables: %s port %d LowCap %d HighCap %d\n",
370d6b92ffaSHans Petter Selasky 	       portid2str(dest), portnum, lowcap, highcap);
371d6b92ffaSHans Petter Selasky 
372d6b92ffaSHans Petter Selasky 	if (lowcap > 0)
373d6b92ffaSHans Petter Selasky 		ret = vlarb_dump_table(dest, portnum, "Low", 1, lowcap);
374d6b92ffaSHans Petter Selasky 
375d6b92ffaSHans Petter Selasky 	if (!ret && highcap > 0)
376d6b92ffaSHans Petter Selasky 		ret = vlarb_dump_table(dest, portnum, "High", 3, highcap);
377d6b92ffaSHans Petter Selasky 
378d6b92ffaSHans Petter Selasky 	return ret;
379d6b92ffaSHans Petter Selasky }
380d6b92ffaSHans Petter Selasky 
guid_info(ib_portid_t * dest,char ** argv,int argc)381d6b92ffaSHans Petter Selasky static char *guid_info(ib_portid_t * dest, char **argv, int argc)
382d6b92ffaSHans Petter Selasky {
383d6b92ffaSHans Petter Selasky 	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
384d6b92ffaSHans Petter Selasky 	int i, j, k;
385d6b92ffaSHans Petter Selasky 	uint64_t *p;
386d6b92ffaSHans Petter Selasky 	unsigned mod;
387d6b92ffaSHans Petter Selasky 	int n;
388d6b92ffaSHans Petter Selasky 
389d6b92ffaSHans Petter Selasky 	/* Get the guid capacity */
390d6b92ffaSHans Petter Selasky 	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
391d6b92ffaSHans Petter Selasky 		return "port info failed";
392d6b92ffaSHans Petter Selasky 	mad_decode_field(data, IB_PORT_GUID_CAP_F, &n);
393d6b92ffaSHans Petter Selasky 
394d6b92ffaSHans Petter Selasky 	for (i = 0; i < (n + 7) / 8; i++) {
395d6b92ffaSHans Petter Selasky 		mod = i;
396d6b92ffaSHans Petter Selasky 		if (!smp_query_via(data, dest, IB_ATTR_GUID_INFO, mod, 0,
397d6b92ffaSHans Petter Selasky 				   srcport))
398d6b92ffaSHans Petter Selasky 			return "guid info query failed";
399d6b92ffaSHans Petter Selasky 		if (i + 1 == (n + 7) / 8)
400d6b92ffaSHans Petter Selasky 			k = ((n + 1 - i * 8) / 2) * 2;
401d6b92ffaSHans Petter Selasky 		else
402d6b92ffaSHans Petter Selasky 			k = 8;
403d6b92ffaSHans Petter Selasky 		p = (uint64_t *) data;
404d6b92ffaSHans Petter Selasky 		for (j = 0; j < k; j += 2, p += 2) {
405d6b92ffaSHans Petter Selasky 			printf("%4u: 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
406d6b92ffaSHans Petter Selasky 			       (i * 8) + j, ntohll(p[0]), ntohll(p[1]));
407d6b92ffaSHans Petter Selasky 		}
408d6b92ffaSHans Petter Selasky 	}
409d6b92ffaSHans Petter Selasky 	printf("%d guids capacity for this port\n", n);
410d6b92ffaSHans Petter Selasky 
411d6b92ffaSHans Petter Selasky 	return 0;
412d6b92ffaSHans Petter Selasky }
413d6b92ffaSHans Petter Selasky 
process_opt(void * context,int ch,char * optarg)414d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
415d6b92ffaSHans Petter Selasky {
416d6b92ffaSHans Petter Selasky 	switch (ch) {
417d6b92ffaSHans Petter Selasky 	case 1:
418d6b92ffaSHans Petter Selasky 		node_name_map_file = strdup(optarg);
419d6b92ffaSHans Petter Selasky 		break;
420d6b92ffaSHans Petter Selasky 	case 'c':
421d6b92ffaSHans Petter Selasky 		ibd_dest_type = IB_DEST_DRSLID;
422d6b92ffaSHans Petter Selasky 		break;
423d6b92ffaSHans Petter Selasky 	case 'x':
424d6b92ffaSHans Petter Selasky 		extended_speeds = 1;
425d6b92ffaSHans Petter Selasky 		break;
426d6b92ffaSHans Petter Selasky 	default:
427d6b92ffaSHans Petter Selasky 		return -1;
428d6b92ffaSHans Petter Selasky 	}
429d6b92ffaSHans Petter Selasky 	return 0;
430d6b92ffaSHans Petter Selasky }
431d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)432d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
433d6b92ffaSHans Petter Selasky {
434d6b92ffaSHans Petter Selasky 	char usage_args[1024];
435d6b92ffaSHans Petter Selasky 	int mgmt_classes[3] =
436d6b92ffaSHans Petter Selasky 	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
437d6b92ffaSHans Petter Selasky 	ib_portid_t portid = { 0 };
438d6b92ffaSHans Petter Selasky 	char *err;
439d6b92ffaSHans Petter Selasky 	op_fn_t *fn;
440d6b92ffaSHans Petter Selasky 	const match_rec_t *r;
441d6b92ffaSHans Petter Selasky 	int n;
442d6b92ffaSHans Petter Selasky 
443d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
444d6b92ffaSHans Petter Selasky 		{"combined", 'c', 0, NULL,
445d6b92ffaSHans Petter Selasky 		 "use Combined route address argument"},
446d6b92ffaSHans Petter Selasky 		{"node-name-map", 1, 1, "<file>", "node name map file"},
447d6b92ffaSHans Petter Selasky 		{"extended", 'x', 0, NULL, "use extended speeds"},
448d6b92ffaSHans Petter Selasky 		{0}
449d6b92ffaSHans Petter Selasky 	};
450d6b92ffaSHans Petter Selasky 	const char *usage_examples[] = {
451d6b92ffaSHans Petter Selasky 		"portinfo 3 1\t\t\t\t# portinfo by lid, with port modifier",
452d6b92ffaSHans Petter Selasky 		"-G switchinfo 0x2C9000100D051 1\t# switchinfo by guid",
453d6b92ffaSHans Petter Selasky 		"-D nodeinfo 0\t\t\t\t# nodeinfo by direct route",
454d6b92ffaSHans Petter Selasky 		"-c nodeinfo 6 0,12\t\t\t# nodeinfo by combined route",
455d6b92ffaSHans Petter Selasky 		NULL
456d6b92ffaSHans Petter Selasky 	};
457d6b92ffaSHans Petter Selasky 
458d6b92ffaSHans Petter Selasky 	n = sprintf(usage_args, "<op> <dest dr_path|lid|guid> [op params]\n"
459d6b92ffaSHans Petter Selasky 		    "\nSupported ops (and aliases, case insensitive):\n");
460d6b92ffaSHans Petter Selasky 	for (r = match_tbl; r->name; r++) {
461d6b92ffaSHans Petter Selasky 		n += snprintf(usage_args + n, sizeof(usage_args) - n,
462d6b92ffaSHans Petter Selasky 			      "  %s (%s) <addr>%s\n", r->name,
463d6b92ffaSHans Petter Selasky 			      r->alias ? r->alias : "",
464d6b92ffaSHans Petter Selasky 			      r->opt_portnum ? " [<portnum>]" : "");
465d6b92ffaSHans Petter Selasky 		if (n >= sizeof(usage_args))
466d6b92ffaSHans Petter Selasky 			exit(-1);
467d6b92ffaSHans Petter Selasky 	}
468d6b92ffaSHans Petter Selasky 
469d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, NULL, NULL, opts, process_opt,
470d6b92ffaSHans Petter Selasky 			    usage_args, usage_examples);
471d6b92ffaSHans Petter Selasky 
472d6b92ffaSHans Petter Selasky 	argc -= optind;
473d6b92ffaSHans Petter Selasky 	argv += optind;
474d6b92ffaSHans Petter Selasky 
475d6b92ffaSHans Petter Selasky 	if (argc < 2)
476d6b92ffaSHans Petter Selasky 		ibdiag_show_usage();
477d6b92ffaSHans Petter Selasky 
478d6b92ffaSHans Petter Selasky 	if (!(fn = match_op(match_tbl, argv[0])))
479d6b92ffaSHans Petter Selasky 		IBEXIT("operation '%s' not supported", argv[0]);
480d6b92ffaSHans Petter Selasky 
481d6b92ffaSHans Petter Selasky 	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
482d6b92ffaSHans Petter Selasky 	if (!srcport)
483d6b92ffaSHans Petter Selasky 		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
484d6b92ffaSHans Petter Selasky 
485d6b92ffaSHans Petter Selasky 	smp_mkey_set(srcport, ibd_mkey);
486d6b92ffaSHans Petter Selasky 
487d6b92ffaSHans Petter Selasky 	node_name_map = open_node_name_map(node_name_map_file);
488d6b92ffaSHans Petter Selasky 
489d6b92ffaSHans Petter Selasky 	if (ibd_dest_type != IB_DEST_DRSLID) {
490d6b92ffaSHans Petter Selasky 		if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[1],
491d6b92ffaSHans Petter Selasky 				       ibd_dest_type, ibd_sm_id, srcport) < 0)
492d6b92ffaSHans Petter Selasky 			IBEXIT("can't resolve destination port %s", argv[1]);
493d6b92ffaSHans Petter Selasky 		if ((err = fn(&portid, argv + 2, argc - 2)))
494d6b92ffaSHans Petter Selasky 			IBEXIT("operation %s: %s", argv[0], err);
495d6b92ffaSHans Petter Selasky 	} else {
496d6b92ffaSHans Petter Selasky 		char concat[64];
497d6b92ffaSHans Petter Selasky 
498d6b92ffaSHans Petter Selasky 		memset(concat, 0, 64);
499d6b92ffaSHans Petter Selasky 		snprintf(concat, sizeof(concat), "%s %s", argv[1], argv[2]);
500d6b92ffaSHans Petter Selasky 		if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, concat,
501d6b92ffaSHans Petter Selasky 				       ibd_dest_type, ibd_sm_id, srcport) < 0)
502d6b92ffaSHans Petter Selasky 			IBEXIT("can't resolve destination port %s", concat);
503d6b92ffaSHans Petter Selasky 		if ((err = fn(&portid, argv + 3, argc - 3)))
504d6b92ffaSHans Petter Selasky 			IBEXIT("operation %s: %s", argv[0], err);
505d6b92ffaSHans Petter Selasky 	}
506d6b92ffaSHans Petter Selasky 	close_node_name_map(node_name_map);
507d6b92ffaSHans Petter Selasky 	mad_rpc_close_port(srcport);
508d6b92ffaSHans Petter Selasky 	exit(0);
509d6b92ffaSHans Petter Selasky }
510