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