1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3d6b92ffaSHans Petter Selasky  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4d6b92ffaSHans Petter Selasky  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
5d6b92ffaSHans Petter Selasky  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
6d6b92ffaSHans Petter Selasky  * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
7d6b92ffaSHans Petter Selasky  *
8d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
9d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
10d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
11d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
12d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
13d6b92ffaSHans Petter Selasky  *
14d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
15d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
16d6b92ffaSHans Petter Selasky  *     conditions are met:
17d6b92ffaSHans Petter Selasky  *
18d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
19d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20d6b92ffaSHans Petter Selasky  *        disclaimer.
21d6b92ffaSHans Petter Selasky  *
22d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
23d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
24d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
25d6b92ffaSHans Petter Selasky  *        provided with the distribution.
26d6b92ffaSHans Petter Selasky  *
27d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34d6b92ffaSHans Petter Selasky  * SOFTWARE.
35d6b92ffaSHans Petter Selasky  *
36d6b92ffaSHans Petter Selasky  */
37d6b92ffaSHans Petter Selasky 
38d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H
39d6b92ffaSHans Petter Selasky #  include <config.h>
40d6b92ffaSHans Petter Selasky #endif				/* HAVE_CONFIG_H */
41d6b92ffaSHans Petter Selasky 
42d6b92ffaSHans Petter Selasky #define _GNU_SOURCE
43d6b92ffaSHans Petter Selasky #include <stdio.h>
44d6b92ffaSHans Petter Selasky #include <stdlib.h>
45d6b92ffaSHans Petter Selasky #include <unistd.h>
46d6b92ffaSHans Petter Selasky #include <stdarg.h>
47d6b92ffaSHans Petter Selasky #include <time.h>
48d6b92ffaSHans Petter Selasky #include <string.h>
49d6b92ffaSHans Petter Selasky #include <getopt.h>
50d6b92ffaSHans Petter Selasky #include <errno.h>
51d6b92ffaSHans Petter Selasky #include <inttypes.h>
52d6b92ffaSHans Petter Selasky 
53d6b92ffaSHans Petter Selasky #include <complib/cl_nodenamemap.h>
54d6b92ffaSHans Petter Selasky #include <infiniband/ibnetdisc.h>
55d6b92ffaSHans Petter Selasky #include <infiniband/mad.h>
56d6b92ffaSHans Petter Selasky 
57d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
58d6b92ffaSHans Petter Selasky #include "ibdiag_sa.h"
59d6b92ffaSHans Petter Selasky 
60d6b92ffaSHans Petter Selasky struct ibmad_port *ibmad_port;
61d6b92ffaSHans Petter Selasky static char *node_name_map_file = NULL;
62d6b92ffaSHans Petter Selasky static nn_map_t *node_name_map = NULL;
63d6b92ffaSHans Petter Selasky static char *load_cache_file = NULL;
64d6b92ffaSHans Petter Selasky static uint16_t lid2sl_table[sizeof(uint8_t) * 1024 * 48] = { 0 };
65d6b92ffaSHans Petter Selasky static int obtain_sl = 1;
66d6b92ffaSHans Petter Selasky 
67d6b92ffaSHans Petter Selasky int data_counters = 0;
68d6b92ffaSHans Petter Selasky int data_counters_only = 0;
69d6b92ffaSHans Petter Selasky int port_config = 0;
70d6b92ffaSHans Petter Selasky uint64_t port_guid = 0;
71d6b92ffaSHans Petter Selasky char *port_guid_str = NULL;
72d6b92ffaSHans Petter Selasky #define SUP_MAX 64
73d6b92ffaSHans Petter Selasky int sup_total = 0;
74d6b92ffaSHans Petter Selasky enum MAD_FIELDS suppressed_fields[SUP_MAX];
75d6b92ffaSHans Petter Selasky char *dr_path = NULL;
76d6b92ffaSHans Petter Selasky uint8_t node_type_to_print = 0;
77d6b92ffaSHans Petter Selasky unsigned clear_errors = 0, clear_counts = 0, details = 0;
78d6b92ffaSHans Petter Selasky 
79d6b92ffaSHans Petter Selasky #define PRINT_SWITCH 0x1
80d6b92ffaSHans Petter Selasky #define PRINT_CA     0x2
81d6b92ffaSHans Petter Selasky #define PRINT_ROUTER 0x4
82d6b92ffaSHans Petter Selasky #define PRINT_ALL 0xFF		/* all nodes default flag */
83d6b92ffaSHans Petter Selasky 
84d6b92ffaSHans Petter Selasky #define DEFAULT_HALF_WORLD_PR_TIMEOUT (3000)
85d6b92ffaSHans Petter Selasky 
86d6b92ffaSHans Petter Selasky struct {
87d6b92ffaSHans Petter Selasky 	int nodes_checked;
88d6b92ffaSHans Petter Selasky 	int bad_nodes;
89d6b92ffaSHans Petter Selasky 	int ports_checked;
90d6b92ffaSHans Petter Selasky 	int bad_ports;
91d6b92ffaSHans Petter Selasky 	int pma_query_failures;
92d6b92ffaSHans Petter Selasky } summary = { 0 };
93d6b92ffaSHans Petter Selasky 
94d6b92ffaSHans Petter Selasky #define DEF_THRES_FILE IBDIAG_CONFIG_PATH"/error_thresholds"
95d6b92ffaSHans Petter Selasky static char *threshold_file = DEF_THRES_FILE;
96d6b92ffaSHans Petter Selasky 
97d6b92ffaSHans Petter Selasky /* define a "packet" with threshold values in it */
98d6b92ffaSHans Petter Selasky uint8_t thresholds[1204] = { 0 };
99d6b92ffaSHans Petter Selasky char * threshold_str = "";
100d6b92ffaSHans Petter Selasky 
valid_gid(ib_gid_t * gid)101d6b92ffaSHans Petter Selasky static unsigned valid_gid(ib_gid_t * gid)
102d6b92ffaSHans Petter Selasky {
103d6b92ffaSHans Petter Selasky 	ib_gid_t zero_gid;
104d6b92ffaSHans Petter Selasky 	memset(&zero_gid, 0, sizeof zero_gid);
105d6b92ffaSHans Petter Selasky 	return memcmp(&zero_gid, gid, sizeof(*gid));
106d6b92ffaSHans Petter Selasky }
107d6b92ffaSHans Petter Selasky 
set_thres(char * name,uint32_t val)108d6b92ffaSHans Petter Selasky static void set_thres(char *name, uint32_t val)
109d6b92ffaSHans Petter Selasky {
110d6b92ffaSHans Petter Selasky 	int f;
111d6b92ffaSHans Petter Selasky 	int n;
112d6b92ffaSHans Petter Selasky 	char tmp[256];
113d6b92ffaSHans Petter Selasky 	for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) {
114d6b92ffaSHans Petter Selasky 		if (strcmp(name, mad_field_name(f)) == 0) {
115d6b92ffaSHans Petter Selasky 			mad_encode_field(thresholds, f, &val);
116d6b92ffaSHans Petter Selasky 			snprintf(tmp, 255, "[%s = %u]", name, val);
117d6b92ffaSHans Petter Selasky 			threshold_str = realloc(threshold_str,
118d6b92ffaSHans Petter Selasky 					strlen(threshold_str)+strlen(tmp)+1);
119d6b92ffaSHans Petter Selasky 			if (!threshold_str) {
120d6b92ffaSHans Petter Selasky 				fprintf(stderr, "Failed to allocate memory: "
121d6b92ffaSHans Petter Selasky 					"%s\n", strerror(errno));
122d6b92ffaSHans Petter Selasky 				exit(1);
123d6b92ffaSHans Petter Selasky 			}
124d6b92ffaSHans Petter Selasky 			n = strlen(threshold_str);
125d6b92ffaSHans Petter Selasky 			strcpy(threshold_str+n, tmp);
126d6b92ffaSHans Petter Selasky 		}
127d6b92ffaSHans Petter Selasky 	}
128d6b92ffaSHans Petter Selasky }
129d6b92ffaSHans Petter Selasky 
set_thresholds(char * threshold_file)130d6b92ffaSHans Petter Selasky static void set_thresholds(char *threshold_file)
131d6b92ffaSHans Petter Selasky {
132d6b92ffaSHans Petter Selasky 	char buf[1024];
133d13def78SEric van Gyzen 	char orig_buf[1024];
134d6b92ffaSHans Petter Selasky 	int val = 0;
135d6b92ffaSHans Petter Selasky 	FILE *thresf = fopen(threshold_file, "r");
136d6b92ffaSHans Petter Selasky 	char *p_prefix, *p_last;
137d6b92ffaSHans Petter Selasky 	char *name;
138d6b92ffaSHans Petter Selasky 	char *val_str;
139d6b92ffaSHans Petter Selasky 	char str[64];
140d6b92ffaSHans Petter Selasky 
141d6b92ffaSHans Petter Selasky 	if (!thresf)
142d6b92ffaSHans Petter Selasky 		return;
143d6b92ffaSHans Petter Selasky 
144d6b92ffaSHans Petter Selasky 	snprintf(str, 63, "Thresholds: ");
145d6b92ffaSHans Petter Selasky 	threshold_str = malloc(strlen(str)+1);
146d6b92ffaSHans Petter Selasky 	if (!threshold_str) {
147d6b92ffaSHans Petter Selasky 		fprintf(stderr, "Failed to allocate memory: %s\n",
148d6b92ffaSHans Petter Selasky 			strerror(errno));
149d6b92ffaSHans Petter Selasky 		exit(1);
150d6b92ffaSHans Petter Selasky 	}
151d6b92ffaSHans Petter Selasky 	strcpy(threshold_str, str);
152d6b92ffaSHans Petter Selasky 	while (fgets(buf, sizeof buf, thresf) != NULL) {
153d6b92ffaSHans Petter Selasky 		p_prefix = strtok_r(buf, "\n", &p_last);
154d6b92ffaSHans Petter Selasky 		if (!p_prefix)
155d6b92ffaSHans Petter Selasky 			continue; /* ignore blank lines */
156d6b92ffaSHans Petter Selasky 
157d6b92ffaSHans Petter Selasky 		if (*p_prefix == '#')
158d6b92ffaSHans Petter Selasky 			continue; /* ignore comment lines */
159d6b92ffaSHans Petter Selasky 
160d13def78SEric van Gyzen 		strlcpy(orig_buf, buf, sizeof(orig_buf));
161d6b92ffaSHans Petter Selasky 		name = strtok_r(p_prefix, "=", &p_last);
162d6b92ffaSHans Petter Selasky 		val_str = strtok_r(NULL, "\n", &p_last);
163d13def78SEric van Gyzen 		if (!name || !val_str) {
164d13def78SEric van Gyzen 			fprintf(stderr, "malformed line in \"%s\":\n%s\n",
165d13def78SEric van Gyzen 			    threshold_file, orig_buf);
166d13def78SEric van Gyzen 			continue;
167d13def78SEric van Gyzen 		}
168d6b92ffaSHans Petter Selasky 
169d6b92ffaSHans Petter Selasky 		val = strtoul(val_str, NULL, 0);
170d6b92ffaSHans Petter Selasky 		set_thres(name, val);
171d6b92ffaSHans Petter Selasky 	}
172d6b92ffaSHans Petter Selasky 
173d6b92ffaSHans Petter Selasky 	fclose(thresf);
174d6b92ffaSHans Petter Selasky }
175d6b92ffaSHans Petter Selasky 
exceeds_threshold(int field,unsigned val)176d6b92ffaSHans Petter Selasky static int exceeds_threshold(int field, unsigned val)
177d6b92ffaSHans Petter Selasky {
178d6b92ffaSHans Petter Selasky 	uint32_t thres = 0;
179d6b92ffaSHans Petter Selasky 	mad_decode_field(thresholds, field, &thres);
180d6b92ffaSHans Petter Selasky 	return (val > thres);
181d6b92ffaSHans Petter Selasky }
182d6b92ffaSHans Petter Selasky 
print_port_config(ibnd_node_t * node,int portnum)183d6b92ffaSHans Petter Selasky static void print_port_config(ibnd_node_t * node, int portnum)
184d6b92ffaSHans Petter Selasky {
185d6b92ffaSHans Petter Selasky 	char width[64], speed[64], state[64], physstate[64];
186d6b92ffaSHans Petter Selasky 	char remote_str[256];
187d6b92ffaSHans Petter Selasky 	char link_str[256];
188d6b92ffaSHans Petter Selasky 	char width_msg[256];
189d6b92ffaSHans Petter Selasky 	char speed_msg[256];
190d6b92ffaSHans Petter Selasky 	char ext_port_str[256];
191d6b92ffaSHans Petter Selasky 	int iwidth, ispeed, fdr10, espeed, istate, iphystate, cap_mask;
192d6b92ffaSHans Petter Selasky 	uint8_t *info;
193d6b92ffaSHans Petter Selasky 
194d6b92ffaSHans Petter Selasky 	ibnd_port_t *port = node->ports[portnum];
195d6b92ffaSHans Petter Selasky 
196d6b92ffaSHans Petter Selasky 	if (!port)
197d6b92ffaSHans Petter Selasky 		return;
198d6b92ffaSHans Petter Selasky 
199d6b92ffaSHans Petter Selasky 	iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
200d6b92ffaSHans Petter Selasky 	ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
201d6b92ffaSHans Petter Selasky 	fdr10 = mad_get_field(port->ext_info, 0,
202d6b92ffaSHans Petter Selasky 			      IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10;
203d6b92ffaSHans Petter Selasky 
204d6b92ffaSHans Petter Selasky 	if (port->node->type == IB_NODE_SWITCH)
205d6b92ffaSHans Petter Selasky 		info = (uint8_t *)&port->node->ports[0]->info;
206d6b92ffaSHans Petter Selasky 	else
207d6b92ffaSHans Petter Selasky 		info = (uint8_t *)&port->info;
208d6b92ffaSHans Petter Selasky 	cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
209d6b92ffaSHans Petter Selasky 	if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
210d6b92ffaSHans Petter Selasky 		espeed = mad_get_field(port->info, 0,
211d6b92ffaSHans Petter Selasky 				       IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
212d6b92ffaSHans Petter Selasky 	else
213d6b92ffaSHans Petter Selasky 		espeed = 0;
214d6b92ffaSHans Petter Selasky 	istate = mad_get_field(port->info, 0, IB_PORT_STATE_F);
215d6b92ffaSHans Petter Selasky 	iphystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F);
216d6b92ffaSHans Petter Selasky 
217d6b92ffaSHans Petter Selasky 	remote_str[0] = '\0';
218d6b92ffaSHans Petter Selasky 	link_str[0] = '\0';
219d6b92ffaSHans Petter Selasky 	width_msg[0] = '\0';
220d6b92ffaSHans Petter Selasky 	speed_msg[0] = '\0';
221d6b92ffaSHans Petter Selasky 
222d6b92ffaSHans Petter Selasky 	/* C14-24.2.1 states that a down port allows for invalid data to be
223d6b92ffaSHans Petter Selasky 	 * returned for all PortInfo components except PortState and
224d6b92ffaSHans Petter Selasky 	 * PortPhysicalState */
225d6b92ffaSHans Petter Selasky 	if (istate != IB_LINK_DOWN) {
226d6b92ffaSHans Petter Selasky 		if (!espeed) {
227d6b92ffaSHans Petter Selasky 			if (fdr10)
228d6b92ffaSHans Petter Selasky 				sprintf(speed, "10.0 Gbps (FDR10)");
229d6b92ffaSHans Petter Selasky 			else
230d6b92ffaSHans Petter Selasky 				mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed,
231d6b92ffaSHans Petter Selasky 					     64, &ispeed);
232d6b92ffaSHans Petter Selasky 		} else
233d6b92ffaSHans Petter Selasky 			mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed,
234d6b92ffaSHans Petter Selasky 			     64, &espeed);
235d6b92ffaSHans Petter Selasky 
236d6b92ffaSHans Petter Selasky 		snprintf(link_str, 256, "(%3s %18s %6s/%8s)",
237d6b92ffaSHans Petter Selasky 			 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
238d6b92ffaSHans Petter Selasky 			 speed,
239d6b92ffaSHans Petter Selasky 			 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
240d6b92ffaSHans Petter Selasky 			 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
241d6b92ffaSHans Petter Selasky 	} else {
242d6b92ffaSHans Petter Selasky 		snprintf(link_str, 256, "(              %6s/%8s)",
243d6b92ffaSHans Petter Selasky 			 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
244d6b92ffaSHans Petter Selasky 			 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
245d6b92ffaSHans Petter Selasky 	}
246d6b92ffaSHans Petter Selasky 
247d6b92ffaSHans Petter Selasky 	if (port->remoteport) {
248d6b92ffaSHans Petter Selasky 		char *rem_node_name = NULL;
249d6b92ffaSHans Petter Selasky 
250d6b92ffaSHans Petter Selasky 		if (port->remoteport->ext_portnum)
251d6b92ffaSHans Petter Selasky 			snprintf(ext_port_str, 256, "%d",
252d6b92ffaSHans Petter Selasky 				 port->remoteport->ext_portnum);
253d6b92ffaSHans Petter Selasky 		else
254d6b92ffaSHans Petter Selasky 			ext_port_str[0] = '\0';
255d6b92ffaSHans Petter Selasky 
256d6b92ffaSHans Petter Selasky 		get_max_msg(width_msg, speed_msg, 256, port);
257d6b92ffaSHans Petter Selasky 
258d6b92ffaSHans Petter Selasky 		rem_node_name = remap_node_name(node_name_map,
259d6b92ffaSHans Petter Selasky 						port->remoteport->node->guid,
260d6b92ffaSHans Petter Selasky 						port->remoteport->node->
261d6b92ffaSHans Petter Selasky 						nodedesc);
262d6b92ffaSHans Petter Selasky 
263d6b92ffaSHans Petter Selasky 		snprintf(remote_str, 256,
264d6b92ffaSHans Petter Selasky 			 "0x%016" PRIx64 " %6d %4d[%2s] \"%s\" (%s %s)\n",
265d6b92ffaSHans Petter Selasky 			 port->remoteport->guid,
266d6b92ffaSHans Petter Selasky 			 port->remoteport->base_lid ? port->remoteport->
267d6b92ffaSHans Petter Selasky 			 base_lid : port->remoteport->node->smalid,
268d6b92ffaSHans Petter Selasky 			 port->remoteport->portnum, ext_port_str, rem_node_name,
269d6b92ffaSHans Petter Selasky 			 width_msg, speed_msg);
270d6b92ffaSHans Petter Selasky 
271d6b92ffaSHans Petter Selasky 		free(rem_node_name);
272d6b92ffaSHans Petter Selasky 	} else
273d6b92ffaSHans Petter Selasky 		snprintf(remote_str, 256, "           [  ] \"\" ( )\n");
274d6b92ffaSHans Petter Selasky 
275d6b92ffaSHans Petter Selasky 	if (port->ext_portnum)
276d6b92ffaSHans Petter Selasky 		snprintf(ext_port_str, 256, "%d", port->ext_portnum);
277d6b92ffaSHans Petter Selasky 	else
278d6b92ffaSHans Petter Selasky 		ext_port_str[0] = '\0';
279d6b92ffaSHans Petter Selasky 
280d6b92ffaSHans Petter Selasky 	if (node->type == IB_NODE_SWITCH)
281d6b92ffaSHans Petter Selasky 		printf("       Link info: %6d", node->smalid);
282d6b92ffaSHans Petter Selasky 	else
283d6b92ffaSHans Petter Selasky 		printf("       Link info: %6d", port->base_lid);
284d6b92ffaSHans Petter Selasky 
285d6b92ffaSHans Petter Selasky 	printf("%4d[%2s] ==%s==>  %s",
286d6b92ffaSHans Petter Selasky 	       port->portnum, ext_port_str, link_str, remote_str);
287d6b92ffaSHans Petter Selasky }
288d6b92ffaSHans Petter Selasky 
suppress(enum MAD_FIELDS field)289d6b92ffaSHans Petter Selasky static int suppress(enum MAD_FIELDS field)
290d6b92ffaSHans Petter Selasky {
291d6b92ffaSHans Petter Selasky 	int i = 0;
292d6b92ffaSHans Petter Selasky 	for (i = 0; i < sup_total; i++)
293d6b92ffaSHans Petter Selasky 		if (field == suppressed_fields[i])
294d6b92ffaSHans Petter Selasky 			return 1;
295d6b92ffaSHans Petter Selasky 	return 0;
296d6b92ffaSHans Petter Selasky }
297d6b92ffaSHans Petter Selasky 
report_suppressed(void)298d6b92ffaSHans Petter Selasky static void report_suppressed(void)
299d6b92ffaSHans Petter Selasky {
300d6b92ffaSHans Petter Selasky 	int i = 0;
301d6b92ffaSHans Petter Selasky 	printf("## Suppressed:");
302d6b92ffaSHans Petter Selasky 	for (i = 0; i < sup_total; i++)
303d6b92ffaSHans Petter Selasky 		printf(" %s", mad_field_name(suppressed_fields[i]));
304d6b92ffaSHans Petter Selasky 	printf("\n");
305d6b92ffaSHans Petter Selasky }
306d6b92ffaSHans Petter Selasky 
print_summary(void)307d6b92ffaSHans Petter Selasky static int print_summary(void)
308d6b92ffaSHans Petter Selasky {
309d6b92ffaSHans Petter Selasky 	printf("\n## Summary: %d nodes checked, %d bad nodes found\n",
310d6b92ffaSHans Petter Selasky 		summary.nodes_checked, summary.bad_nodes);
311d6b92ffaSHans Petter Selasky 	printf("##          %d ports checked, %d ports have errors beyond threshold\n",
312d6b92ffaSHans Petter Selasky 		summary.ports_checked, summary.bad_ports);
313d6b92ffaSHans Petter Selasky 	printf("## %s\n", threshold_str);
314d6b92ffaSHans Petter Selasky 	if (summary.pma_query_failures)
315d6b92ffaSHans Petter Selasky 		printf("##          %d PMA query failures\n", summary.pma_query_failures);
316d6b92ffaSHans Petter Selasky 	report_suppressed();
317d6b92ffaSHans Petter Selasky 	return (summary.bad_ports);
318d6b92ffaSHans Petter Selasky }
319d6b92ffaSHans Petter Selasky 
insert_lid2sl_table(struct sa_query_result * r)320d6b92ffaSHans Petter Selasky static void insert_lid2sl_table(struct sa_query_result *r)
321d6b92ffaSHans Petter Selasky {
322d6b92ffaSHans Petter Selasky     unsigned int i;
323d6b92ffaSHans Petter Selasky     for (i = 0; i < r->result_cnt; i++) {
324d6b92ffaSHans Petter Selasky 	    ib_path_rec_t *p_pr = (ib_path_rec_t *)sa_get_query_rec(r->p_result_madw, i);
325d6b92ffaSHans Petter Selasky 	    lid2sl_table[cl_ntoh16(p_pr->dlid)] = ib_path_rec_sl(p_pr);
326d6b92ffaSHans Petter Selasky     }
327d6b92ffaSHans Petter Selasky }
328d6b92ffaSHans Petter Selasky 
path_record_query(ib_gid_t sgid,uint64_t dguid)329d6b92ffaSHans Petter Selasky static int path_record_query(ib_gid_t sgid,uint64_t dguid)
330d6b92ffaSHans Petter Selasky {
331d6b92ffaSHans Petter Selasky      ib_path_rec_t pr;
332d6b92ffaSHans Petter Selasky      ib_net64_t comp_mask = 0;
333d6b92ffaSHans Petter Selasky      uint8_t reversible = 0;
334d6b92ffaSHans Petter Selasky      struct sa_handle * h;
335d6b92ffaSHans Petter Selasky 
336d6b92ffaSHans Petter Selasky      if (!(h = sa_get_handle()))
337d6b92ffaSHans Petter Selasky 	return -1;
338d6b92ffaSHans Petter Selasky 
339d6b92ffaSHans Petter Selasky      ibd_timeout = DEFAULT_HALF_WORLD_PR_TIMEOUT;
340d6b92ffaSHans Petter Selasky      memset(&pr, 0, sizeof(pr));
341d6b92ffaSHans Petter Selasky 
342d6b92ffaSHans Petter Selasky      CHECK_AND_SET_GID(sgid, pr.sgid, PR, SGID);
343d6b92ffaSHans Petter Selasky      if(dguid) {
344d6b92ffaSHans Petter Selasky 	     mad_encode_field(sgid.raw, IB_GID_GUID_F, &dguid);
345d6b92ffaSHans Petter Selasky 	     CHECK_AND_SET_GID(sgid, pr.dgid, PR, DGID);
346d6b92ffaSHans Petter Selasky      }
347d6b92ffaSHans Petter Selasky 
348d6b92ffaSHans Petter Selasky      CHECK_AND_SET_VAL(1, 8, -1, pr.num_path, PR, NUMBPATH);/*to get only one PathRecord for each source and destination pair*/
349d6b92ffaSHans Petter Selasky      CHECK_AND_SET_VAL(1, 8, -1, reversible, PR, REVERSIBLE);/*for a reversible path*/
350d6b92ffaSHans Petter Selasky      pr.num_path |= reversible << 7;
351d6b92ffaSHans Petter Selasky      struct sa_query_result result;
352d6b92ffaSHans Petter Selasky      int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE,
353d6b92ffaSHans Petter Selasky                         (uint16_t)IB_SA_ATTR_PATHRECORD,0,cl_ntoh64(comp_mask),ibd_sakey,
354d6b92ffaSHans Petter Selasky                         &pr, sizeof(pr), &result);
355d6b92ffaSHans Petter Selasky      if (ret) {
356d6b92ffaSHans Petter Selasky              sa_free_handle(h);
357d6b92ffaSHans Petter Selasky              fprintf(stderr, "Query SA failed: %s; sa call path_query failed\n", strerror(ret));
358d6b92ffaSHans Petter Selasky              return ret;
359d6b92ffaSHans Petter Selasky      }
360d6b92ffaSHans Petter Selasky      if (result.status != IB_SA_MAD_STATUS_SUCCESS) {
361d6b92ffaSHans Petter Selasky              sa_report_err(result.status);
362d6b92ffaSHans Petter Selasky              ret = EIO;
363d6b92ffaSHans Petter Selasky              goto Exit;
364d6b92ffaSHans Petter Selasky      }
365d6b92ffaSHans Petter Selasky 
366d6b92ffaSHans Petter Selasky      insert_lid2sl_table(&result);
367d6b92ffaSHans Petter Selasky Exit:
368d6b92ffaSHans Petter Selasky      sa_free_handle(h);
369d6b92ffaSHans Petter Selasky      sa_free_result_mad(&result);
370d6b92ffaSHans Petter Selasky      return ret;
371d6b92ffaSHans Petter Selasky }
372d6b92ffaSHans Petter Selasky 
query_and_dump(char * buf,size_t size,ib_portid_t * portid,char * node_name,int portnum,const char * attr_name,uint16_t attr_id,int start_field,int end_field)373d6b92ffaSHans Petter Selasky static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
374d6b92ffaSHans Petter Selasky 			  char *node_name, int portnum,
375d6b92ffaSHans Petter Selasky 			  const char *attr_name, uint16_t attr_id,
376d6b92ffaSHans Petter Selasky 			  int start_field, int end_field)
377d6b92ffaSHans Petter Selasky {
378d6b92ffaSHans Petter Selasky 	uint8_t pc[1024];
379d6b92ffaSHans Petter Selasky 	uint32_t val = 0;
380d6b92ffaSHans Petter Selasky 	int i, n;
381d6b92ffaSHans Petter Selasky 
382d6b92ffaSHans Petter Selasky 	memset(pc, 0, sizeof(pc));
383d6b92ffaSHans Petter Selasky 
384d6b92ffaSHans Petter Selasky 	if (!pma_query_via(pc, portid, portnum, ibd_timeout, attr_id,
385d6b92ffaSHans Petter Selasky 			   ibmad_port)) {
386d6b92ffaSHans Petter Selasky 		IBWARN("%s query failed on %s, %s port %d", attr_name,
387d6b92ffaSHans Petter Selasky 		       node_name, portid2str(portid), portnum);
388d6b92ffaSHans Petter Selasky 		summary.pma_query_failures++;
389d6b92ffaSHans Petter Selasky 		return 0;
390d6b92ffaSHans Petter Selasky 	}
391d6b92ffaSHans Petter Selasky 
392d6b92ffaSHans Petter Selasky 	for (n = 0, i = start_field; i < end_field; i++) {
393d6b92ffaSHans Petter Selasky 		mad_decode_field(pc, i, (void *)&val);
394d6b92ffaSHans Petter Selasky 		if (val)
395d6b92ffaSHans Petter Selasky 			n += snprintf(buf + n, size - n, " [%s == %u]",
396d6b92ffaSHans Petter Selasky 				      mad_field_name(i), val);
397d6b92ffaSHans Petter Selasky 	}
398d6b92ffaSHans Petter Selasky 
399d6b92ffaSHans Petter Selasky 	return n;
400d6b92ffaSHans Petter Selasky }
401d6b92ffaSHans Petter Selasky 
402d6b92ffaSHans Petter Selasky 
print_results(ib_portid_t * portid,char * node_name,ibnd_node_t * node,uint8_t * pc,int portnum,int * header_printed,uint8_t * pce,uint16_t cap_mask)403d6b92ffaSHans Petter Selasky static int print_results(ib_portid_t * portid, char *node_name,
404d6b92ffaSHans Petter Selasky 			 ibnd_node_t * node, uint8_t * pc, int portnum,
405d6b92ffaSHans Petter Selasky 			 int *header_printed, uint8_t *pce, uint16_t cap_mask)
406d6b92ffaSHans Petter Selasky {
407d6b92ffaSHans Petter Selasky 	char buf[1024];
408d6b92ffaSHans Petter Selasky 	char *str = buf;
409d6b92ffaSHans Petter Selasky 	uint32_t val = 0;
410d6b92ffaSHans Petter Selasky 	int i, n;
411d6b92ffaSHans Petter Selasky 
412d6b92ffaSHans Petter Selasky 	for (n = 0, i = IB_PC_ERR_SYM_F; i <= IB_PC_VL15_DROPPED_F; i++) {
413d6b92ffaSHans Petter Selasky 		if (suppress(i))
414d6b92ffaSHans Petter Selasky 			continue;
415d6b92ffaSHans Petter Selasky 
416d6b92ffaSHans Petter Selasky 		/* this is not a counter, skip it */
417d6b92ffaSHans Petter Selasky 		if (i == IB_PC_COUNTER_SELECT2_F)
418d6b92ffaSHans Petter Selasky 			continue;
419d6b92ffaSHans Petter Selasky 
420d6b92ffaSHans Petter Selasky 		mad_decode_field(pc, i, (void *)&val);
421d6b92ffaSHans Petter Selasky 		if (exceeds_threshold(i, val)) {
422d6b92ffaSHans Petter Selasky 			n += snprintf(str + n, 1024 - n, " [%s == %u]",
423d6b92ffaSHans Petter Selasky 				      mad_field_name(i), val);
424d6b92ffaSHans Petter Selasky 
425d6b92ffaSHans Petter Selasky 			/* If there are PortXmitDiscards, get details (if supported) */
426d6b92ffaSHans Petter Selasky 			if (i == IB_PC_XMT_DISCARDS_F && details) {
427d6b92ffaSHans Petter Selasky 				n += query_and_dump(str + n, sizeof(buf) - n, portid,
428d6b92ffaSHans Petter Selasky 						    node_name, portnum,
429d6b92ffaSHans Petter Selasky 						    "PortXmitDiscardDetails",
430d6b92ffaSHans Petter Selasky 						    IB_GSI_PORT_XMIT_DISCARD_DETAILS,
431d6b92ffaSHans Petter Selasky 						    IB_PC_RCV_LOCAL_PHY_ERR_F,
432d6b92ffaSHans Petter Selasky 						    IB_PC_RCV_ERR_LAST_F);
433d6b92ffaSHans Petter Selasky 				/* If there are PortRcvErrors, get details (if supported) */
434d6b92ffaSHans Petter Selasky 			} else if (i == IB_PC_ERR_RCV_F && details) {
435d6b92ffaSHans Petter Selasky 				n += query_and_dump(str + n, sizeof(buf) - n, portid,
436d6b92ffaSHans Petter Selasky 						    node_name, portnum,
437d6b92ffaSHans Petter Selasky 						    "PortRcvErrorDetails",
438d6b92ffaSHans Petter Selasky 						    IB_GSI_PORT_RCV_ERROR_DETAILS,
439d6b92ffaSHans Petter Selasky 						    IB_PC_XMT_INACT_DISC_F,
440d6b92ffaSHans Petter Selasky 						    IB_PC_XMT_DISC_LAST_F);
441d6b92ffaSHans Petter Selasky 			}
442d6b92ffaSHans Petter Selasky 		}
443d6b92ffaSHans Petter Selasky 	}
444d6b92ffaSHans Petter Selasky 
445d6b92ffaSHans Petter Selasky 	if (!suppress(IB_PC_XMT_WAIT_F)) {
446d6b92ffaSHans Petter Selasky 		mad_decode_field(pc, IB_PC_XMT_WAIT_F, (void *)&val);
447d6b92ffaSHans Petter Selasky 		if (exceeds_threshold(IB_PC_XMT_WAIT_F, val))
448d6b92ffaSHans Petter Selasky 			n += snprintf(str + n, 1024 - n, " [%s == %u]",
449d6b92ffaSHans Petter Selasky 				      mad_field_name(IB_PC_XMT_WAIT_F), val);
450d6b92ffaSHans Petter Selasky 	}
451d6b92ffaSHans Petter Selasky 
452d6b92ffaSHans Petter Selasky 	/* if we found errors. */
453d6b92ffaSHans Petter Selasky 	if (n != 0) {
454d6b92ffaSHans Petter Selasky 		if (data_counters) {
455d6b92ffaSHans Petter Selasky 			uint8_t *pkt = pc;
456d6b92ffaSHans Petter Selasky 			int start_field = IB_PC_XMT_BYTES_F;
457d6b92ffaSHans Petter Selasky 			int end_field = IB_PC_RCV_PKTS_F;
458d6b92ffaSHans Petter Selasky 
459d6b92ffaSHans Petter Selasky 			if (pce) {
460d6b92ffaSHans Petter Selasky 				pkt = pce;
461d6b92ffaSHans Petter Selasky 				start_field = IB_PC_EXT_XMT_BYTES_F;
462d6b92ffaSHans Petter Selasky 				if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
463d6b92ffaSHans Petter Selasky 					end_field = IB_PC_EXT_RCV_MPKTS_F;
464d6b92ffaSHans Petter Selasky 				else
465d6b92ffaSHans Petter Selasky 					end_field = IB_PC_EXT_RCV_PKTS_F;
466d6b92ffaSHans Petter Selasky 			}
467d6b92ffaSHans Petter Selasky 
468d6b92ffaSHans Petter Selasky 			for (i = start_field; i <= end_field; i++) {
469d6b92ffaSHans Petter Selasky 				uint64_t val64 = 0;
470d6b92ffaSHans Petter Selasky 				float val = 0;
471d6b92ffaSHans Petter Selasky 				char *unit = "";
472d6b92ffaSHans Petter Selasky 				mad_decode_field(pkt, i, (void *)&val64);
473d6b92ffaSHans Petter Selasky 				if (val64) {
474d6b92ffaSHans Petter Selasky 					int data = 0;
475d6b92ffaSHans Petter Selasky 					if (i == IB_PC_EXT_XMT_BYTES_F ||
476d6b92ffaSHans Petter Selasky 					    i == IB_PC_EXT_RCV_BYTES_F ||
477d6b92ffaSHans Petter Selasky 					    i == IB_PC_XMT_BYTES_F ||
478d6b92ffaSHans Petter Selasky 					    i == IB_PC_RCV_BYTES_F)
479d6b92ffaSHans Petter Selasky 						data = 1;
480d6b92ffaSHans Petter Selasky 					unit = conv_cnt_human_readable(val64,
481d6b92ffaSHans Petter Selasky 								&val, data);
482d6b92ffaSHans Petter Selasky 					n += snprintf(str + n, 1024 - n,
483d6b92ffaSHans Petter Selasky 						" [%s == %" PRIu64
484d6b92ffaSHans Petter Selasky 						" (%5.3f%s)]",
485d6b92ffaSHans Petter Selasky 						mad_field_name(i), val64, val,
486d6b92ffaSHans Petter Selasky 						unit);
487d6b92ffaSHans Petter Selasky 				}
488d6b92ffaSHans Petter Selasky 			}
489d6b92ffaSHans Petter Selasky 		}
490d6b92ffaSHans Petter Selasky 
491d6b92ffaSHans Petter Selasky 		if (!*header_printed) {
492d6b92ffaSHans Petter Selasky 			if (node->type == IB_NODE_SWITCH)
493d6b92ffaSHans Petter Selasky 				printf("Errors for 0x%" PRIx64 " \"%s\"\n",
494d6b92ffaSHans Petter Selasky 					node->ports[0]->guid, node_name);
495d6b92ffaSHans Petter Selasky 			else
496d6b92ffaSHans Petter Selasky 				printf("Errors for \"%s\"\n", node_name);
497d6b92ffaSHans Petter Selasky 			*header_printed = 1;
498d6b92ffaSHans Petter Selasky 			summary.bad_nodes++;
499d6b92ffaSHans Petter Selasky 		}
500d6b92ffaSHans Petter Selasky 
501d6b92ffaSHans Petter Selasky 		if (portnum == 0xFF) {
502d6b92ffaSHans Petter Selasky 			if (node->type == IB_NODE_SWITCH)
503d6b92ffaSHans Petter Selasky 				printf("   GUID 0x%" PRIx64 " port ALL:%s\n",
504d6b92ffaSHans Petter Selasky 				       node->ports[0]->guid, str);
505d6b92ffaSHans Petter Selasky 		} else {
506d6b92ffaSHans Petter Selasky 			printf("   GUID 0x%" PRIx64 " port %d:%s\n",
507d6b92ffaSHans Petter Selasky 			       node->ports[portnum]->guid, portnum, str);
508d6b92ffaSHans Petter Selasky 			if (port_config)
509d6b92ffaSHans Petter Selasky 				print_port_config(node, portnum);
510d6b92ffaSHans Petter Selasky 			summary.bad_ports++;
511d6b92ffaSHans Petter Selasky 		}
512d6b92ffaSHans Petter Selasky 	}
513d6b92ffaSHans Petter Selasky 	return (n);
514d6b92ffaSHans Petter Selasky }
515d6b92ffaSHans Petter Selasky 
query_cap_mask(ib_portid_t * portid,char * node_name,int portnum,uint16_t * cap_mask)516d6b92ffaSHans Petter Selasky static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
517d6b92ffaSHans Petter Selasky 			  uint16_t * cap_mask)
518d6b92ffaSHans Petter Selasky {
519d6b92ffaSHans Petter Selasky 	uint8_t pc[1024] = { 0 };
520d6b92ffaSHans Petter Selasky 	uint16_t rc_cap_mask;
521d6b92ffaSHans Petter Selasky 
522d6b92ffaSHans Petter Selasky 	portid->sl = lid2sl_table[portid->lid];
523d6b92ffaSHans Petter Selasky 
524d6b92ffaSHans Petter Selasky 	/* PerfMgt ClassPortInfo is a required attribute */
525d6b92ffaSHans Petter Selasky 	if (!pma_query_via(pc, portid, portnum, ibd_timeout, CLASS_PORT_INFO,
526d6b92ffaSHans Petter Selasky 			   ibmad_port)) {
527d6b92ffaSHans Petter Selasky 		IBWARN("classportinfo query failed on %s, %s port %d",
528d6b92ffaSHans Petter Selasky 		       node_name, portid2str(portid), portnum);
529d6b92ffaSHans Petter Selasky 		summary.pma_query_failures++;
530d6b92ffaSHans Petter Selasky 		return -1;
531d6b92ffaSHans Petter Selasky 	}
532d6b92ffaSHans Petter Selasky 
533d6b92ffaSHans Petter Selasky 	/* ClassPortInfo should be supported as part of libibmad */
534d6b92ffaSHans Petter Selasky 	memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask));	/* CapabilityMask */
535d6b92ffaSHans Petter Selasky 
536d6b92ffaSHans Petter Selasky 	*cap_mask = rc_cap_mask;
537d6b92ffaSHans Petter Selasky 	return 0;
538d6b92ffaSHans Petter Selasky }
539d6b92ffaSHans Petter Selasky 
print_data_cnts(ib_portid_t * portid,uint16_t cap_mask,char * node_name,ibnd_node_t * node,int portnum,int * header_printed)540d6b92ffaSHans Petter Selasky static int print_data_cnts(ib_portid_t * portid, uint16_t cap_mask,
541d6b92ffaSHans Petter Selasky 			   char *node_name, ibnd_node_t * node, int portnum,
542d6b92ffaSHans Petter Selasky 			   int *header_printed)
543d6b92ffaSHans Petter Selasky {
544d6b92ffaSHans Petter Selasky 	uint8_t pc[1024];
545d6b92ffaSHans Petter Selasky 	int i;
546d6b92ffaSHans Petter Selasky 	int start_field = IB_PC_XMT_BYTES_F;
547d6b92ffaSHans Petter Selasky 	int end_field = IB_PC_RCV_PKTS_F;
548d6b92ffaSHans Petter Selasky 
549d6b92ffaSHans Petter Selasky 	memset(pc, 0, 1024);
550d6b92ffaSHans Petter Selasky 
551d6b92ffaSHans Petter Selasky 	portid->sl = lid2sl_table[portid->lid];
552d6b92ffaSHans Petter Selasky 
553d6b92ffaSHans Petter Selasky 	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
554d6b92ffaSHans Petter Selasky 		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
555d6b92ffaSHans Petter Selasky 				   IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
556d6b92ffaSHans Petter Selasky 			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
557d6b92ffaSHans Petter Selasky 			       node_name, portid2str(portid), portnum);
558d6b92ffaSHans Petter Selasky 			summary.pma_query_failures++;
559d6b92ffaSHans Petter Selasky 			return (1);
560d6b92ffaSHans Petter Selasky 		}
561d6b92ffaSHans Petter Selasky 		start_field = IB_PC_EXT_XMT_BYTES_F;
562d6b92ffaSHans Petter Selasky 		if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
563d6b92ffaSHans Petter Selasky 			end_field = IB_PC_EXT_RCV_MPKTS_F;
564d6b92ffaSHans Petter Selasky 		else
565d6b92ffaSHans Petter Selasky 			end_field = IB_PC_EXT_RCV_PKTS_F;
566d6b92ffaSHans Petter Selasky 	} else {
567d6b92ffaSHans Petter Selasky 		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
568d6b92ffaSHans Petter Selasky 				   IB_GSI_PORT_COUNTERS, ibmad_port)) {
569d6b92ffaSHans Petter Selasky 			IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
570d6b92ffaSHans Petter Selasky 			       node_name, portid2str(portid), portnum);
571d6b92ffaSHans Petter Selasky 			summary.pma_query_failures++;
572d6b92ffaSHans Petter Selasky 			return (1);
573d6b92ffaSHans Petter Selasky 		}
574d6b92ffaSHans Petter Selasky 		start_field = IB_PC_XMT_BYTES_F;
575d6b92ffaSHans Petter Selasky 		end_field = IB_PC_RCV_PKTS_F;
576d6b92ffaSHans Petter Selasky 	}
577d6b92ffaSHans Petter Selasky 
578d6b92ffaSHans Petter Selasky 	if (!*header_printed) {
579d6b92ffaSHans Petter Selasky 		printf("Data Counters for 0x%" PRIx64 " \"%s\"\n", node->guid,
580d6b92ffaSHans Petter Selasky 		       node_name);
581d6b92ffaSHans Petter Selasky 		*header_printed = 1;
582d6b92ffaSHans Petter Selasky 	}
583d6b92ffaSHans Petter Selasky 
584d6b92ffaSHans Petter Selasky 	if (portnum == 0xFF)
585d6b92ffaSHans Petter Selasky 		printf("   GUID 0x%" PRIx64 " port ALL:", node->guid);
586d6b92ffaSHans Petter Selasky 	else
587d6b92ffaSHans Petter Selasky 		printf("   GUID 0x%" PRIx64 " port %d:",
588d6b92ffaSHans Petter Selasky 		       node->guid, portnum);
589d6b92ffaSHans Petter Selasky 
590d6b92ffaSHans Petter Selasky 	for (i = start_field; i <= end_field; i++) {
591d6b92ffaSHans Petter Selasky 		uint64_t val64 = 0;
592d6b92ffaSHans Petter Selasky 		float val = 0;
593d6b92ffaSHans Petter Selasky 		char *unit = "";
594d6b92ffaSHans Petter Selasky 		int data = 0;
595d6b92ffaSHans Petter Selasky 		mad_decode_field(pc, i, (void *)&val64);
596d6b92ffaSHans Petter Selasky 		if (i == IB_PC_EXT_XMT_BYTES_F || i == IB_PC_EXT_RCV_BYTES_F ||
597d6b92ffaSHans Petter Selasky 		    i == IB_PC_XMT_BYTES_F || i == IB_PC_RCV_BYTES_F)
598d6b92ffaSHans Petter Selasky 			data = 1;
599d6b92ffaSHans Petter Selasky 		unit = conv_cnt_human_readable(val64, &val, data);
600d6b92ffaSHans Petter Selasky 		printf(" [%s == %" PRIu64 " (%5.3f%s)]", mad_field_name(i),
601d6b92ffaSHans Petter Selasky 			val64, val, unit);
602d6b92ffaSHans Petter Selasky 	}
603d6b92ffaSHans Petter Selasky 	printf("\n");
604d6b92ffaSHans Petter Selasky 
605d6b92ffaSHans Petter Selasky 	if (portnum != 0xFF && port_config)
606d6b92ffaSHans Petter Selasky 		print_port_config(node, portnum);
607d6b92ffaSHans Petter Selasky 
608d6b92ffaSHans Petter Selasky 	return (0);
609d6b92ffaSHans Petter Selasky }
610d6b92ffaSHans Petter Selasky 
print_errors(ib_portid_t * portid,uint16_t cap_mask,char * node_name,ibnd_node_t * node,int portnum,int * header_printed)611d6b92ffaSHans Petter Selasky static int print_errors(ib_portid_t * portid, uint16_t cap_mask,
612d6b92ffaSHans Petter Selasky 			char *node_name, ibnd_node_t * node, int portnum,
613d6b92ffaSHans Petter Selasky 			int *header_printed)
614d6b92ffaSHans Petter Selasky {
615d6b92ffaSHans Petter Selasky 	uint8_t pc[1024];
616d6b92ffaSHans Petter Selasky 	uint8_t pce[1024];
617d6b92ffaSHans Petter Selasky 	uint8_t *pc_ext = NULL;
618d6b92ffaSHans Petter Selasky 
619d6b92ffaSHans Petter Selasky 	memset(pc, 0, 1024);
620d6b92ffaSHans Petter Selasky 	memset(pce, 0, 1024);
621d6b92ffaSHans Petter Selasky 
622d6b92ffaSHans Petter Selasky 	portid->sl = lid2sl_table[portid->lid];
623d6b92ffaSHans Petter Selasky 
624d6b92ffaSHans Petter Selasky 	if (!pma_query_via(pc, portid, portnum, ibd_timeout,
625d6b92ffaSHans Petter Selasky 			   IB_GSI_PORT_COUNTERS, ibmad_port)) {
626d6b92ffaSHans Petter Selasky 		IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
627d6b92ffaSHans Petter Selasky 		       node_name, portid2str(portid), portnum);
628d6b92ffaSHans Petter Selasky 		summary.pma_query_failures++;
629d6b92ffaSHans Petter Selasky 		return (0);
630d6b92ffaSHans Petter Selasky 	}
631d6b92ffaSHans Petter Selasky 
632d6b92ffaSHans Petter Selasky 	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
633d6b92ffaSHans Petter Selasky 		if (!pma_query_via(pce, portid, portnum, ibd_timeout,
634d6b92ffaSHans Petter Selasky 		    IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
635d6b92ffaSHans Petter Selasky 			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
636d6b92ffaSHans Petter Selasky 			       node_name, portid2str(portid), portnum);
637d6b92ffaSHans Petter Selasky 			summary.pma_query_failures++;
638d6b92ffaSHans Petter Selasky 			return (0);
639d6b92ffaSHans Petter Selasky 		}
640d6b92ffaSHans Petter Selasky 		pc_ext = pce;
641d6b92ffaSHans Petter Selasky 	}
642d6b92ffaSHans Petter Selasky 
643d6b92ffaSHans Petter Selasky 	if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
644d6b92ffaSHans Petter Selasky 		/* if PortCounters:PortXmitWait not supported clear this counter */
645d6b92ffaSHans Petter Selasky 		uint32_t foo = 0;
646d6b92ffaSHans Petter Selasky 		mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo);
647d6b92ffaSHans Petter Selasky 	}
648d6b92ffaSHans Petter Selasky 	return (print_results(portid, node_name, node, pc, portnum,
649d6b92ffaSHans Petter Selasky 			      header_printed, pc_ext, cap_mask));
650d6b92ffaSHans Petter Selasky }
651d6b92ffaSHans Petter Selasky 
reset_pc_ext(void * rcvbuf,ib_portid_t * dest,int port,unsigned mask,unsigned timeout,const struct ibmad_port * srcport)652d6b92ffaSHans Petter Selasky uint8_t *reset_pc_ext(void *rcvbuf, ib_portid_t * dest,
653d6b92ffaSHans Petter Selasky 		      int port, unsigned mask, unsigned timeout,
654d6b92ffaSHans Petter Selasky 		      const struct ibmad_port * srcport)
655d6b92ffaSHans Petter Selasky {
656d6b92ffaSHans Petter Selasky 	ib_rpc_t rpc = { 0 };
657d6b92ffaSHans Petter Selasky 	int lid = dest->lid;
658d6b92ffaSHans Petter Selasky 
659d6b92ffaSHans Petter Selasky 	DEBUG("lid %u port %d mask 0x%x", lid, port, mask);
660d6b92ffaSHans Petter Selasky 
661d6b92ffaSHans Petter Selasky 	if (lid == -1) {
662d6b92ffaSHans Petter Selasky 		IBWARN("only lid routed is supported");
663d6b92ffaSHans Petter Selasky 		return NULL;
664d6b92ffaSHans Petter Selasky 	}
665d6b92ffaSHans Petter Selasky 
666d6b92ffaSHans Petter Selasky 	if (!mask)
667d6b92ffaSHans Petter Selasky 		mask = ~0;
668d6b92ffaSHans Petter Selasky 
669d6b92ffaSHans Petter Selasky 	rpc.mgtclass = IB_PERFORMANCE_CLASS;
670d6b92ffaSHans Petter Selasky 	rpc.method = IB_MAD_METHOD_SET;
671d6b92ffaSHans Petter Selasky 	rpc.attr.id = IB_GSI_PORT_COUNTERS_EXT;
672d6b92ffaSHans Petter Selasky 
673d6b92ffaSHans Petter Selasky 	memset(rcvbuf, 0, IB_MAD_SIZE);
674d6b92ffaSHans Petter Selasky 
675d6b92ffaSHans Petter Selasky 	/* Same for attribute IDs */
676d6b92ffaSHans Petter Selasky 	mad_set_field(rcvbuf, 0, IB_PC_EXT_PORT_SELECT_F, port);
677d6b92ffaSHans Petter Selasky 	mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT_F, mask);
678d6b92ffaSHans Petter Selasky 	rpc.attr.mod = 0;
679d6b92ffaSHans Petter Selasky 	rpc.timeout = timeout;
680d6b92ffaSHans Petter Selasky 	rpc.datasz = IB_PC_DATA_SZ;
681d6b92ffaSHans Petter Selasky 	rpc.dataoffs = IB_PC_DATA_OFFS;
682d6b92ffaSHans Petter Selasky 	if (!dest->qp)
683d6b92ffaSHans Petter Selasky 		dest->qp = 1;
684d6b92ffaSHans Petter Selasky 	if (!dest->qkey)
685d6b92ffaSHans Petter Selasky 		dest->qkey = IB_DEFAULT_QP1_QKEY;
686d6b92ffaSHans Petter Selasky 
687d6b92ffaSHans Petter Selasky 	return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
688d6b92ffaSHans Petter Selasky }
689d6b92ffaSHans Petter Selasky 
clear_port(ib_portid_t * portid,uint16_t cap_mask,char * node_name,int port)690d6b92ffaSHans Petter Selasky static void clear_port(ib_portid_t * portid, uint16_t cap_mask,
691d6b92ffaSHans Petter Selasky 		       char *node_name, int port)
692d6b92ffaSHans Petter Selasky {
693d6b92ffaSHans Petter Selasky 	uint8_t pc[1024] = { 0 };
694d6b92ffaSHans Petter Selasky 	/* bits defined in Table 228 PortCounters CounterSelect and
695d6b92ffaSHans Petter Selasky 	 * CounterSelect2
696d6b92ffaSHans Petter Selasky 	 */
697d6b92ffaSHans Petter Selasky 	uint32_t mask = 0;
698d6b92ffaSHans Petter Selasky 
699d6b92ffaSHans Petter Selasky 	if (clear_errors) {
700d6b92ffaSHans Petter Selasky 		mask |= 0xFFF;
701d6b92ffaSHans Petter Selasky 		if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
702d6b92ffaSHans Petter Selasky 			mask |= 0x10000;
703d6b92ffaSHans Petter Selasky 	}
704d6b92ffaSHans Petter Selasky 	if (clear_counts)
705d6b92ffaSHans Petter Selasky 		mask |= 0xF000;
706d6b92ffaSHans Petter Selasky 
707d6b92ffaSHans Petter Selasky 	if (mask)
708d6b92ffaSHans Petter Selasky 		if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
709d6b92ffaSHans Petter Selasky 					   IB_GSI_PORT_COUNTERS, ibmad_port))
710d6b92ffaSHans Petter Selasky 			fprintf(stderr, "Failed to reset errors %s port %d\n", node_name,
711d6b92ffaSHans Petter Selasky 				port);
712d6b92ffaSHans Petter Selasky 
713d6b92ffaSHans Petter Selasky 	if (clear_errors && details) {
714d6b92ffaSHans Petter Selasky 		memset(pc, 0, 1024);
715d6b92ffaSHans Petter Selasky 		performance_reset_via(pc, portid, port, 0xf, ibd_timeout,
716d6b92ffaSHans Petter Selasky 				      IB_GSI_PORT_XMIT_DISCARD_DETAILS,
717d6b92ffaSHans Petter Selasky 				      ibmad_port);
718d6b92ffaSHans Petter Selasky 		memset(pc, 0, 1024);
719d6b92ffaSHans Petter Selasky 		performance_reset_via(pc, portid, port, 0x3f, ibd_timeout,
720d6b92ffaSHans Petter Selasky 				      IB_GSI_PORT_RCV_ERROR_DETAILS,
721d6b92ffaSHans Petter Selasky 				      ibmad_port);
722d6b92ffaSHans Petter Selasky 	}
723d6b92ffaSHans Petter Selasky 
724d6b92ffaSHans Petter Selasky 	if (clear_counts &&
725d6b92ffaSHans Petter Selasky 	    (cap_mask &
726d6b92ffaSHans Petter Selasky 	     (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP))) {
727d6b92ffaSHans Petter Selasky 		if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
728d6b92ffaSHans Petter Selasky 			mask = 0xFF;
729d6b92ffaSHans Petter Selasky 		else
730d6b92ffaSHans Petter Selasky 			mask = 0x0F;
731d6b92ffaSHans Petter Selasky 
732d6b92ffaSHans Petter Selasky 		if (!reset_pc_ext(pc, portid, port, mask, ibd_timeout,
733d6b92ffaSHans Petter Selasky 		    ibmad_port))
734d6b92ffaSHans Petter Selasky 			fprintf(stderr, "Failed to reset extended data counters %s, "
735d6b92ffaSHans Petter Selasky 				"%s port %d\n", node_name, portid2str(portid),
736d6b92ffaSHans Petter Selasky 				port);
737d6b92ffaSHans Petter Selasky 	}
738d6b92ffaSHans Petter Selasky }
739d6b92ffaSHans Petter Selasky 
print_node(ibnd_node_t * node,void * user_data)740d6b92ffaSHans Petter Selasky void print_node(ibnd_node_t * node, void *user_data)
741d6b92ffaSHans Petter Selasky {
742d6b92ffaSHans Petter Selasky 	int header_printed = 0;
743d6b92ffaSHans Petter Selasky 	int p = 0;
744d6b92ffaSHans Petter Selasky 	int startport = 1;
745d6b92ffaSHans Petter Selasky 	int type = 0;
746d6b92ffaSHans Petter Selasky 	int all_port_sup = 0;
747d6b92ffaSHans Petter Selasky 	ib_portid_t portid = { 0 };
748d6b92ffaSHans Petter Selasky 	uint16_t cap_mask = 0;
749d6b92ffaSHans Petter Selasky 	char *node_name = NULL;
750d6b92ffaSHans Petter Selasky 
751d6b92ffaSHans Petter Selasky 	switch (node->type) {
752d6b92ffaSHans Petter Selasky 	case IB_NODE_SWITCH:
753d6b92ffaSHans Petter Selasky 		type = PRINT_SWITCH;
754d6b92ffaSHans Petter Selasky 		break;
755d6b92ffaSHans Petter Selasky 	case IB_NODE_CA:
756d6b92ffaSHans Petter Selasky 		type = PRINT_CA;
757d6b92ffaSHans Petter Selasky 		break;
758d6b92ffaSHans Petter Selasky 	case IB_NODE_ROUTER:
759d6b92ffaSHans Petter Selasky 		type = PRINT_ROUTER;
760d6b92ffaSHans Petter Selasky 		break;
761d6b92ffaSHans Petter Selasky 	}
762d6b92ffaSHans Petter Selasky 
763d6b92ffaSHans Petter Selasky 	if ((type & node_type_to_print) == 0)
764d6b92ffaSHans Petter Selasky 		return;
765d6b92ffaSHans Petter Selasky 
766d6b92ffaSHans Petter Selasky 	if (node->type == IB_NODE_SWITCH && node->smaenhsp0)
767d6b92ffaSHans Petter Selasky 		startport = 0;
768d6b92ffaSHans Petter Selasky 
769d6b92ffaSHans Petter Selasky 	node_name = remap_node_name(node_name_map, node->guid, node->nodedesc);
770d6b92ffaSHans Petter Selasky 
771d6b92ffaSHans Petter Selasky 	if (node->type == IB_NODE_SWITCH) {
772d6b92ffaSHans Petter Selasky 		ib_portid_set(&portid, node->smalid, 0, 0);
773d6b92ffaSHans Petter Selasky 		p = 0;
774d6b92ffaSHans Petter Selasky 	} else {
775d6b92ffaSHans Petter Selasky 		for (p = 1; p <= node->numports; p++) {
776d6b92ffaSHans Petter Selasky 			if (node->ports[p]) {
777d6b92ffaSHans Petter Selasky 				ib_portid_set(&portid,
778d6b92ffaSHans Petter Selasky 					      node->ports[p]->base_lid,
779d6b92ffaSHans Petter Selasky 					      0, 0);
780d6b92ffaSHans Petter Selasky 				break;
781d6b92ffaSHans Petter Selasky 			}
782d6b92ffaSHans Petter Selasky 		}
783d6b92ffaSHans Petter Selasky 	}
784d6b92ffaSHans Petter Selasky 
785d6b92ffaSHans Petter Selasky 	if ((query_cap_mask(&portid, node_name, p, &cap_mask) == 0) &&
786d6b92ffaSHans Petter Selasky 	    (cap_mask & IB_PM_ALL_PORT_SELECT))
787d6b92ffaSHans Petter Selasky 		all_port_sup = 1;
788d6b92ffaSHans Petter Selasky 
789d6b92ffaSHans Petter Selasky 	if (data_counters_only) {
790d6b92ffaSHans Petter Selasky 		for (p = startport; p <= node->numports; p++) {
791d6b92ffaSHans Petter Selasky 			if (node->ports[p]) {
792d6b92ffaSHans Petter Selasky 				if (node->type == IB_NODE_SWITCH)
793d6b92ffaSHans Petter Selasky 					ib_portid_set(&portid, node->smalid, 0, 0);
794d6b92ffaSHans Petter Selasky 				else
795d6b92ffaSHans Petter Selasky 					ib_portid_set(&portid, node->ports[p]->base_lid,
796d6b92ffaSHans Petter Selasky 						      0, 0);
797d6b92ffaSHans Petter Selasky 
798d6b92ffaSHans Petter Selasky 				print_data_cnts(&portid, cap_mask, node_name, node, p,
799d6b92ffaSHans Petter Selasky 						&header_printed);
800d6b92ffaSHans Petter Selasky 				summary.ports_checked++;
801d6b92ffaSHans Petter Selasky 				if (!all_port_sup)
802d6b92ffaSHans Petter Selasky 					clear_port(&portid, cap_mask, node_name, p);
803d6b92ffaSHans Petter Selasky 			}
804d6b92ffaSHans Petter Selasky 		}
805d6b92ffaSHans Petter Selasky 	} else {
806d6b92ffaSHans Petter Selasky 		if (all_port_sup)
807d6b92ffaSHans Petter Selasky 			if (!print_errors(&portid, cap_mask, node_name, node,
808d6b92ffaSHans Petter Selasky 					  0xFF, &header_printed)) {
809d6b92ffaSHans Petter Selasky 				summary.ports_checked += node->numports;
810d6b92ffaSHans Petter Selasky 				goto clear;
811d6b92ffaSHans Petter Selasky 			}
812d6b92ffaSHans Petter Selasky 
813d6b92ffaSHans Petter Selasky 		for (p = startport; p <= node->numports; p++) {
814d6b92ffaSHans Petter Selasky 			if (node->ports[p]) {
815d6b92ffaSHans Petter Selasky 				if (node->type == IB_NODE_SWITCH)
816d6b92ffaSHans Petter Selasky 					ib_portid_set(&portid, node->smalid, 0, 0);
817d6b92ffaSHans Petter Selasky 				else
818d6b92ffaSHans Petter Selasky 					ib_portid_set(&portid, node->ports[p]->base_lid,
819d6b92ffaSHans Petter Selasky 						      0, 0);
820d6b92ffaSHans Petter Selasky 
821d6b92ffaSHans Petter Selasky 				print_errors(&portid, cap_mask, node_name, node, p,
822d6b92ffaSHans Petter Selasky 					     &header_printed);
823d6b92ffaSHans Petter Selasky 				summary.ports_checked++;
824d6b92ffaSHans Petter Selasky 				if (!all_port_sup)
825d6b92ffaSHans Petter Selasky 					clear_port(&portid, cap_mask, node_name, p);
826d6b92ffaSHans Petter Selasky 			}
827d6b92ffaSHans Petter Selasky 		}
828d6b92ffaSHans Petter Selasky 	}
829d6b92ffaSHans Petter Selasky 
830d6b92ffaSHans Petter Selasky clear:
831d6b92ffaSHans Petter Selasky 	summary.nodes_checked++;
832d6b92ffaSHans Petter Selasky 	if (all_port_sup)
833d6b92ffaSHans Petter Selasky 		clear_port(&portid, cap_mask, node_name, 0xFF);
834d6b92ffaSHans Petter Selasky 
835d6b92ffaSHans Petter Selasky 	free(node_name);
836d6b92ffaSHans Petter Selasky }
837d6b92ffaSHans Petter Selasky 
add_suppressed(enum MAD_FIELDS field)838d6b92ffaSHans Petter Selasky static void add_suppressed(enum MAD_FIELDS field)
839d6b92ffaSHans Petter Selasky {
840d6b92ffaSHans Petter Selasky 	if (sup_total >= SUP_MAX) {
841d6b92ffaSHans Petter Selasky 		IBWARN("Maximum (%d) fields have been suppressed; skipping %s",
842d6b92ffaSHans Petter Selasky 		       sup_total, mad_field_name(field));
843d6b92ffaSHans Petter Selasky 		return;
844d6b92ffaSHans Petter Selasky 	}
845d6b92ffaSHans Petter Selasky 	suppressed_fields[sup_total++] = field;
846d6b92ffaSHans Petter Selasky }
847d6b92ffaSHans Petter Selasky 
calculate_suppressed_fields(char * str)848d6b92ffaSHans Petter Selasky static void calculate_suppressed_fields(char *str)
849d6b92ffaSHans Petter Selasky {
850d6b92ffaSHans Petter Selasky 	enum MAD_FIELDS f;
851d6b92ffaSHans Petter Selasky 	char *val, *lasts = NULL;
852d6b92ffaSHans Petter Selasky 	char *tmp = strdup(str);
853d6b92ffaSHans Petter Selasky 
854d6b92ffaSHans Petter Selasky 	val = strtok_r(tmp, ",", &lasts);
855d6b92ffaSHans Petter Selasky 	while (val) {
856d6b92ffaSHans Petter Selasky 		for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++)
857d6b92ffaSHans Petter Selasky 			if (strcmp(val, mad_field_name(f)) == 0)
858d6b92ffaSHans Petter Selasky 				add_suppressed(f);
859d6b92ffaSHans Petter Selasky 		val = strtok_r(NULL, ",", &lasts);
860d6b92ffaSHans Petter Selasky 	}
861d6b92ffaSHans Petter Selasky 
862d6b92ffaSHans Petter Selasky 	free(tmp);
863d6b92ffaSHans Petter Selasky }
864d6b92ffaSHans Petter Selasky 
process_opt(void * context,int ch,char * optarg)865d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg)
866d6b92ffaSHans Petter Selasky {
867d6b92ffaSHans Petter Selasky 	struct ibnd_config *cfg = context;
868d6b92ffaSHans Petter Selasky 	switch (ch) {
869d6b92ffaSHans Petter Selasky 	case 's':
870d6b92ffaSHans Petter Selasky 		calculate_suppressed_fields(optarg);
871d6b92ffaSHans Petter Selasky 		break;
872d6b92ffaSHans Petter Selasky 	case 'c':
873d6b92ffaSHans Petter Selasky 		/* Right now this is the only "common" error */
874d6b92ffaSHans Petter Selasky 		add_suppressed(IB_PC_ERR_SWITCH_REL_F);
875d6b92ffaSHans Petter Selasky 		break;
876d6b92ffaSHans Petter Selasky 	case 1:
877d6b92ffaSHans Petter Selasky 		node_name_map_file = strdup(optarg);
878d6b92ffaSHans Petter Selasky 		break;
879d6b92ffaSHans Petter Selasky 	case 2:
880d6b92ffaSHans Petter Selasky 		data_counters++;
881d6b92ffaSHans Petter Selasky 		break;
882d6b92ffaSHans Petter Selasky 	case 3:
883d6b92ffaSHans Petter Selasky 		node_type_to_print |= PRINT_SWITCH;
884d6b92ffaSHans Petter Selasky 		break;
885d6b92ffaSHans Petter Selasky 	case 4:
886d6b92ffaSHans Petter Selasky 		node_type_to_print |= PRINT_CA;
887d6b92ffaSHans Petter Selasky 		break;
888d6b92ffaSHans Petter Selasky 	case 5:
889d6b92ffaSHans Petter Selasky 		node_type_to_print |= PRINT_ROUTER;
890d6b92ffaSHans Petter Selasky 		break;
891d6b92ffaSHans Petter Selasky 	case 6:
892d6b92ffaSHans Petter Selasky 		details = 1;
893d6b92ffaSHans Petter Selasky 		break;
894d6b92ffaSHans Petter Selasky 	case 7:
895d6b92ffaSHans Petter Selasky 		load_cache_file = strdup(optarg);
896d6b92ffaSHans Petter Selasky 		break;
897d6b92ffaSHans Petter Selasky 	case 8:
898d6b92ffaSHans Petter Selasky 		threshold_file = strdup(optarg);
899d6b92ffaSHans Petter Selasky 		break;
900d6b92ffaSHans Petter Selasky 	case 9:
901d6b92ffaSHans Petter Selasky 		data_counters_only = 1;
902d6b92ffaSHans Petter Selasky 		break;
903d6b92ffaSHans Petter Selasky 	case 10:
904d6b92ffaSHans Petter Selasky 		obtain_sl = 0;
905d6b92ffaSHans Petter Selasky 		break;
906d6b92ffaSHans Petter Selasky 	case 'G':
907d6b92ffaSHans Petter Selasky 	case 'S':
908d6b92ffaSHans Petter Selasky 		port_guid_str = optarg;
909d6b92ffaSHans Petter Selasky 		port_guid = strtoull(optarg, 0, 0);
910d6b92ffaSHans Petter Selasky 		break;
911d6b92ffaSHans Petter Selasky 	case 'D':
912d6b92ffaSHans Petter Selasky 		dr_path = strdup(optarg);
913d6b92ffaSHans Petter Selasky 		break;
914d6b92ffaSHans Petter Selasky 	case 'r':
915d6b92ffaSHans Petter Selasky 		port_config++;
916d6b92ffaSHans Petter Selasky 		break;
917d6b92ffaSHans Petter Selasky 	case 'R':		/* nop */
918d6b92ffaSHans Petter Selasky 		break;
919d6b92ffaSHans Petter Selasky 	case 'k':
920d6b92ffaSHans Petter Selasky 		clear_errors = 1;
921d6b92ffaSHans Petter Selasky 		break;
922d6b92ffaSHans Petter Selasky 	case 'K':
923d6b92ffaSHans Petter Selasky 		clear_counts = 1;
924d6b92ffaSHans Petter Selasky 		break;
925d6b92ffaSHans Petter Selasky 	case 'o':
926d6b92ffaSHans Petter Selasky 		cfg->max_smps = strtoul(optarg, NULL, 0);
927d6b92ffaSHans Petter Selasky 		break;
928d6b92ffaSHans Petter Selasky 	default:
929d6b92ffaSHans Petter Selasky 		return -1;
930d6b92ffaSHans Petter Selasky 	}
931d6b92ffaSHans Petter Selasky 
932d6b92ffaSHans Petter Selasky 	return 0;
933d6b92ffaSHans Petter Selasky }
934d6b92ffaSHans Petter Selasky 
main(int argc,char ** argv)935d6b92ffaSHans Petter Selasky int main(int argc, char **argv)
936d6b92ffaSHans Petter Selasky {
937d6b92ffaSHans Petter Selasky 	struct ibnd_config config = { 0 };
938d6b92ffaSHans Petter Selasky 	int resolved = -1;
939d6b92ffaSHans Petter Selasky 	ib_portid_t portid = { 0 };
940d6b92ffaSHans Petter Selasky 	ib_portid_t self_portid = { 0 };
941d6b92ffaSHans Petter Selasky 	int rc = 0;
942d6b92ffaSHans Petter Selasky 	ibnd_fabric_t *fabric = NULL;
943d6b92ffaSHans Petter Selasky 	ib_gid_t self_gid;
944d6b92ffaSHans Petter Selasky 	int port = 0;
945d6b92ffaSHans Petter Selasky 
946d6b92ffaSHans Petter Selasky 	int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS,
947d6b92ffaSHans Petter Selasky 		IB_PERFORMANCE_CLASS
948d6b92ffaSHans Petter Selasky 	};
949d6b92ffaSHans Petter Selasky 
950d6b92ffaSHans Petter Selasky 	const struct ibdiag_opt opts[] = {
951d6b92ffaSHans Petter Selasky 		{"suppress", 's', 1, "<err1,err2,...>",
952d6b92ffaSHans Petter Selasky 		 "suppress errors listed"},
953d6b92ffaSHans Petter Selasky 		{"suppress-common", 'c', 0, NULL,
954d6b92ffaSHans Petter Selasky 		 "suppress some of the common counters"},
955d6b92ffaSHans Petter Selasky 		{"node-name-map", 1, 1, "<file>", "node name map file"},
956d6b92ffaSHans Petter Selasky 		{"port-guid", 'G', 1, "<port_guid>",
957d6b92ffaSHans Petter Selasky 		 "report the node containing the port specified by <port_guid>"},
958d6b92ffaSHans Petter Selasky 		{"", 'S', 1, "<port_guid>",
959d6b92ffaSHans Petter Selasky 		 "Same as \"-G\" for backward compatibility"},
960d6b92ffaSHans Petter Selasky 		{"Direct", 'D', 1, "<dr_path>",
961d6b92ffaSHans Petter Selasky 		 "report the node containing the port specified by <dr_path>"},
962d6b92ffaSHans Petter Selasky 		{"skip-sl", 10, 0, NULL,"don't obtain SL to all destinations"},
963d6b92ffaSHans Petter Selasky 		{"report-port", 'r', 0, NULL,
964d6b92ffaSHans Petter Selasky 		 "report port link information"},
965d6b92ffaSHans Petter Selasky 		{"threshold-file", 8, 1, NULL,
966d6b92ffaSHans Petter Selasky 		 "specify an alternate threshold file, default: " DEF_THRES_FILE},
967d6b92ffaSHans Petter Selasky 		{"GNDN", 'R', 0, NULL,
968d6b92ffaSHans Petter Selasky 		 "(This option is obsolete and does nothing)"},
969d6b92ffaSHans Petter Selasky 		{"data", 2, 0, NULL, "include data counters for ports with errors"},
970d6b92ffaSHans Petter Selasky 		{"switch", 3, 0, NULL, "print data for switches only"},
971d6b92ffaSHans Petter Selasky 		{"ca", 4, 0, NULL, "print data for CA's only"},
972d6b92ffaSHans Petter Selasky 		{"router", 5, 0, NULL, "print data for routers only"},
973d6b92ffaSHans Petter Selasky 		{"details", 6, 0, NULL, "include transmit discard details"},
974d6b92ffaSHans Petter Selasky 		{"counters", 9, 0, NULL, "print data counters only"},
975d6b92ffaSHans Petter Selasky 		{"clear-errors", 'k', 0, NULL,
976d6b92ffaSHans Petter Selasky 		 "Clear error counters after read"},
977d6b92ffaSHans Petter Selasky 		{"clear-counts", 'K', 0, NULL,
978d6b92ffaSHans Petter Selasky 		 "Clear data counters after read"},
979d6b92ffaSHans Petter Selasky 		{"load-cache", 7, 1, "<file>",
980d6b92ffaSHans Petter Selasky 		 "filename of ibnetdiscover cache to load"},
981d6b92ffaSHans Petter Selasky 		{"outstanding_smps", 'o', 1, NULL,
982d6b92ffaSHans Petter Selasky 		 "specify the number of outstanding SMP's which should be "
983d6b92ffaSHans Petter Selasky 		 "issued during the scan"},
984d6b92ffaSHans Petter Selasky 		{0}
985d6b92ffaSHans Petter Selasky 	};
986d6b92ffaSHans Petter Selasky 	char usage_args[] = "";
987d6b92ffaSHans Petter Selasky 
988d6b92ffaSHans Petter Selasky 	memset(suppressed_fields, 0, sizeof suppressed_fields);
989d6b92ffaSHans Petter Selasky 	ibdiag_process_opts(argc, argv, &config, "cDGKLnRrSs", opts, process_opt,
990d6b92ffaSHans Petter Selasky 			    usage_args, NULL);
991d6b92ffaSHans Petter Selasky 
992d6b92ffaSHans Petter Selasky 	argc -= optind;
993d6b92ffaSHans Petter Selasky 	argv += optind;
994d6b92ffaSHans Petter Selasky 
995d6b92ffaSHans Petter Selasky 	if (!node_type_to_print)
996d6b92ffaSHans Petter Selasky 		node_type_to_print = PRINT_ALL;
997d6b92ffaSHans Petter Selasky 
998d6b92ffaSHans Petter Selasky 	ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4);
999d6b92ffaSHans Petter Selasky 	if (!ibmad_port)
1000d6b92ffaSHans Petter Selasky 		IBEXIT("Failed to open port; %s:%d\n", ibd_ca, ibd_ca_port);
1001d6b92ffaSHans Petter Selasky 
1002d6b92ffaSHans Petter Selasky 	smp_mkey_set(ibmad_port, ibd_mkey);
1003d6b92ffaSHans Petter Selasky 
1004d6b92ffaSHans Petter Selasky 	if (ibd_timeout) {
1005d6b92ffaSHans Petter Selasky 		mad_rpc_set_timeout(ibmad_port, ibd_timeout);
1006d6b92ffaSHans Petter Selasky 		config.timeout_ms = ibd_timeout;
1007d6b92ffaSHans Petter Selasky 	}
1008d6b92ffaSHans Petter Selasky 
1009d6b92ffaSHans Petter Selasky 	config.flags = ibd_ibnetdisc_flags;
1010d6b92ffaSHans Petter Selasky 	config.mkey = ibd_mkey;
1011d6b92ffaSHans Petter Selasky 
1012d6b92ffaSHans Petter Selasky 	if (dr_path && load_cache_file) {
1013d6b92ffaSHans Petter Selasky 		mad_rpc_close_port(ibmad_port);
1014d6b92ffaSHans Petter Selasky 		fprintf(stderr, "Cannot specify cache and direct route path\n");
1015d6b92ffaSHans Petter Selasky 		exit(-1);
1016d6b92ffaSHans Petter Selasky 	}
1017d6b92ffaSHans Petter Selasky 
1018d6b92ffaSHans Petter Selasky 	if (resolve_self(ibd_ca, ibd_ca_port, &self_portid, &port, &self_gid.raw) < 0) {
1019d6b92ffaSHans Petter Selasky 		mad_rpc_close_port(ibmad_port);
1020d6b92ffaSHans Petter Selasky 		IBEXIT("can't resolve self port %s", argv[0]);
1021d6b92ffaSHans Petter Selasky 	}
1022d6b92ffaSHans Petter Selasky 
1023d6b92ffaSHans Petter Selasky 	node_name_map = open_node_name_map(node_name_map_file);
1024d6b92ffaSHans Petter Selasky 
1025d6b92ffaSHans Petter Selasky 	/* limit the scan the fabric around the target */
1026d6b92ffaSHans Petter Selasky 	if (dr_path) {
1027d6b92ffaSHans Petter Selasky 		if ((resolved =
1028d6b92ffaSHans Petter Selasky 		     resolve_portid_str(ibd_ca, ibd_ca_port, &portid, dr_path,
1029d6b92ffaSHans Petter Selasky 					IB_DEST_DRPATH, NULL, ibmad_port)) < 0)
1030d6b92ffaSHans Petter Selasky 			IBWARN("Failed to resolve %s; attempting full scan",
1031d6b92ffaSHans Petter Selasky 			       dr_path);
1032d6b92ffaSHans Petter Selasky 	} else if (port_guid_str) {
1033d6b92ffaSHans Petter Selasky 		if ((resolved =
1034d6b92ffaSHans Petter Selasky 		     resolve_portid_str(ibd_ca, ibd_ca_port, &portid,
1035d6b92ffaSHans Petter Selasky 					port_guid_str, IB_DEST_GUID, ibd_sm_id,
1036d6b92ffaSHans Petter Selasky 					       ibmad_port)) < 0)
1037d6b92ffaSHans Petter Selasky 			IBWARN("Failed to resolve %s; attempting full scan",
1038d6b92ffaSHans Petter Selasky 			       port_guid_str);
1039d6b92ffaSHans Petter Selasky 		if(obtain_sl)
1040d6b92ffaSHans Petter Selasky 			lid2sl_table[portid.lid] = portid.sl;
1041d6b92ffaSHans Petter Selasky 	}
1042d6b92ffaSHans Petter Selasky 
1043d6b92ffaSHans Petter Selasky 	mad_rpc_close_port(ibmad_port);
1044d6b92ffaSHans Petter Selasky 
1045d6b92ffaSHans Petter Selasky 	if (load_cache_file) {
1046d6b92ffaSHans Petter Selasky 		if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
1047d6b92ffaSHans Petter Selasky 			fprintf(stderr, "loading cached fabric failed\n");
1048d6b92ffaSHans Petter Selasky 			rc = -1;
1049d6b92ffaSHans Petter Selasky 			goto close_port;
1050d6b92ffaSHans Petter Selasky 		}
1051d6b92ffaSHans Petter Selasky 	} else {
1052d6b92ffaSHans Petter Selasky 		if (resolved >= 0) {
1053d6b92ffaSHans Petter Selasky 			if (!config.max_hops)
1054d6b92ffaSHans Petter Selasky 				config.max_hops = 1;
1055d6b92ffaSHans Petter Selasky 			if (!(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
1056d6b92ffaSHans Petter Selasky 						    &portid, &config)))
1057d6b92ffaSHans Petter Selasky 				IBWARN("Single node discover failed;"
1058d6b92ffaSHans Petter Selasky 				       " attempting full scan");
1059d6b92ffaSHans Petter Selasky 		}
1060d6b92ffaSHans Petter Selasky 
1061d6b92ffaSHans Petter Selasky 		if (!fabric && !(fabric = ibnd_discover_fabric(ibd_ca,
1062d6b92ffaSHans Petter Selasky 							       ibd_ca_port,
1063d6b92ffaSHans Petter Selasky 							       NULL,
1064d6b92ffaSHans Petter Selasky 							       &config))) {
1065d6b92ffaSHans Petter Selasky 			fprintf(stderr, "discover failed\n");
1066d6b92ffaSHans Petter Selasky 			rc = -1;
1067d6b92ffaSHans Petter Selasky 			goto close_port;
1068d6b92ffaSHans Petter Selasky 		}
1069d6b92ffaSHans Petter Selasky 	}
1070d6b92ffaSHans Petter Selasky 
1071d6b92ffaSHans Petter Selasky 	set_thresholds(threshold_file);
1072d6b92ffaSHans Petter Selasky 
1073d6b92ffaSHans Petter Selasky 	/* reopen the global ibmad_port */
1074d6b92ffaSHans Petter Selasky 	ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port,
1075d6b92ffaSHans Petter Selasky 				       mgmt_classes, 4);
1076d6b92ffaSHans Petter Selasky 	if (!ibmad_port) {
1077d6b92ffaSHans Petter Selasky 		ibnd_destroy_fabric(fabric);
1078d6b92ffaSHans Petter Selasky 		close_node_name_map(node_name_map);
1079d6b92ffaSHans Petter Selasky 		IBEXIT("Failed to reopen port: %s:%d\n",
1080d6b92ffaSHans Petter Selasky 			ibd_ca, ibd_ca_port);
1081d6b92ffaSHans Petter Selasky 	}
1082d6b92ffaSHans Petter Selasky 
1083d6b92ffaSHans Petter Selasky 	smp_mkey_set(ibmad_port, ibd_mkey);
1084d6b92ffaSHans Petter Selasky 
1085d6b92ffaSHans Petter Selasky 	if (ibd_timeout)
1086d6b92ffaSHans Petter Selasky 		mad_rpc_set_timeout(ibmad_port, ibd_timeout);
1087d6b92ffaSHans Petter Selasky 
1088d6b92ffaSHans Petter Selasky 	if (port_guid_str) {
1089d6b92ffaSHans Petter Selasky 		ibnd_port_t *port = ibnd_find_port_guid(fabric, port_guid);
1090d6b92ffaSHans Petter Selasky 		if (port)
1091d6b92ffaSHans Petter Selasky 			print_node(port->node, NULL);
1092d6b92ffaSHans Petter Selasky 		else
1093d6b92ffaSHans Petter Selasky 			fprintf(stderr, "Failed to find node: %s\n",
1094d6b92ffaSHans Petter Selasky 				port_guid_str);
1095d6b92ffaSHans Petter Selasky 	} else if (dr_path) {
1096d6b92ffaSHans Petter Selasky 		ibnd_port_t *port;
1097d6b92ffaSHans Petter Selasky 		uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
1098d6b92ffaSHans Petter Selasky 		if (!smp_query_via(ni, &portid, IB_ATTR_NODE_INFO, 0,
1099d6b92ffaSHans Petter Selasky 			   ibd_timeout, ibmad_port)) {
1100d6b92ffaSHans Petter Selasky 				fprintf(stderr, "Failed to query local Node Info\n");
1101d6b92ffaSHans Petter Selasky 				goto destroy_fabric;
1102d6b92ffaSHans Petter Selasky 		}
1103d6b92ffaSHans Petter Selasky 
1104d6b92ffaSHans Petter Selasky 		mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(port_guid));
1105d6b92ffaSHans Petter Selasky 
1106d6b92ffaSHans Petter Selasky 		port = ibnd_find_port_guid(fabric, port_guid);
1107d6b92ffaSHans Petter Selasky 		if (port) {
1108d6b92ffaSHans Petter Selasky 			if(obtain_sl)
1109d6b92ffaSHans Petter Selasky 				if(path_record_query(self_gid,port->guid))
1110d6b92ffaSHans Petter Selasky 					goto destroy_fabric;
1111d6b92ffaSHans Petter Selasky 			print_node(port->node, NULL);
1112d6b92ffaSHans Petter Selasky 		} else
1113d6b92ffaSHans Petter Selasky 			fprintf(stderr, "Failed to find node: %s\n", dr_path);
1114d6b92ffaSHans Petter Selasky 	} else {
1115d6b92ffaSHans Petter Selasky 		if(obtain_sl)
1116d6b92ffaSHans Petter Selasky 			if(path_record_query(self_gid,0))
1117d6b92ffaSHans Petter Selasky 				goto destroy_fabric;
1118d6b92ffaSHans Petter Selasky 
1119d6b92ffaSHans Petter Selasky 		ibnd_iter_nodes(fabric, print_node, NULL);
1120d6b92ffaSHans Petter Selasky 	}
1121d6b92ffaSHans Petter Selasky 
1122d6b92ffaSHans Petter Selasky 	rc = print_summary();
1123d6b92ffaSHans Petter Selasky 	if (rc)
1124d6b92ffaSHans Petter Selasky 		rc = 1;
1125d6b92ffaSHans Petter Selasky 
1126d6b92ffaSHans Petter Selasky destroy_fabric:
1127d6b92ffaSHans Petter Selasky 	mad_rpc_close_port(ibmad_port);
1128d6b92ffaSHans Petter Selasky 	ibnd_destroy_fabric(fabric);
1129d6b92ffaSHans Petter Selasky 
1130d6b92ffaSHans Petter Selasky close_port:
1131d6b92ffaSHans Petter Selasky 	close_node_name_map(node_name_map);
1132d6b92ffaSHans Petter Selasky 	exit(rc);
1133d6b92ffaSHans Petter Selasky }
1134