Blame src/ibqueryerrors.c

Packit db064d
/*
Packit db064d
 * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
Packit db064d
 * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
Packit db064d
 * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
Packit db064d
 * Copyright (c) 2009 HNR Consulting.  All rights reserved.
Packit db064d
 * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
Packit db064d
 *
Packit db064d
 * This software is available to you under a choice of one of two
Packit db064d
 * licenses.  You may choose to be licensed under the terms of the GNU
Packit db064d
 * General Public License (GPL) Version 2, available from the file
Packit db064d
 * COPYING in the main directory of this source tree, or the
Packit db064d
 * OpenIB.org BSD license below:
Packit db064d
 *
Packit db064d
 *     Redistribution and use in source and binary forms, with or
Packit db064d
 *     without modification, are permitted provided that the following
Packit db064d
 *     conditions are met:
Packit db064d
 *
Packit db064d
 *      - Redistributions of source code must retain the above
Packit db064d
 *        copyright notice, this list of conditions and the following
Packit db064d
 *        disclaimer.
Packit db064d
 *
Packit db064d
 *      - Redistributions in binary form must reproduce the above
Packit db064d
 *        copyright notice, this list of conditions and the following
Packit db064d
 *        disclaimer in the documentation and/or other materials
Packit db064d
 *        provided with the distribution.
Packit db064d
 *
Packit db064d
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
Packit db064d
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
Packit db064d
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
Packit db064d
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
Packit db064d
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
Packit db064d
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit db064d
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
Packit db064d
 * SOFTWARE.
Packit db064d
 *
Packit db064d
 */
Packit db064d
Packit db064d
#if HAVE_CONFIG_H
Packit db064d
#  include <config.h>
Packit db064d
#endif				/* HAVE_CONFIG_H */
Packit db064d
Packit db064d
#define _GNU_SOURCE
Packit db064d
#include <stdio.h>
Packit db064d
#include <stdlib.h>
Packit db064d
#include <unistd.h>
Packit db064d
#include <stdarg.h>
Packit db064d
#include <time.h>
Packit db064d
#include <string.h>
Packit db064d
#include <errno.h>
Packit db064d
#include <inttypes.h>
Packit db064d
Packit db064d
#include <complib/cl_nodenamemap.h>
Packit db064d
#include <infiniband/ibnetdisc.h>
Packit db064d
#include <infiniband/mad.h>
Packit db064d
Packit db064d
#include "ibdiag_common.h"
Packit db064d
#include "ibdiag_sa.h"
Packit db064d
Packit db064d
static struct ibmad_port *ibmad_port;
Packit db064d
static char *node_name_map_file = NULL;
Packit db064d
static nn_map_t *node_name_map = NULL;
Packit db064d
static char *load_cache_file = NULL;
Packit db064d
static uint16_t lid2sl_table[sizeof(uint8_t) * 1024 * 48] = { 0 };
Packit db064d
static int obtain_sl = 1;
Packit db064d
Packit db064d
static int data_counters;
Packit db064d
static int data_counters_only;
Packit db064d
static int port_config;
Packit db064d
static uint64_t port_guid;
Packit db064d
static char *port_guid_str;
Packit db064d
#define SUP_MAX 64
Packit db064d
static int sup_total;
Packit db064d
static enum MAD_FIELDS suppressed_fields[SUP_MAX];
Packit db064d
static char *dr_path;
Packit db064d
static uint8_t node_type_to_print;
Packit db064d
static unsigned clear_errors, clear_counts, details;
Packit db064d
Packit db064d
#define PRINT_SWITCH 0x1
Packit db064d
#define PRINT_CA     0x2
Packit db064d
#define PRINT_ROUTER 0x4
Packit db064d
#define PRINT_ALL 0xFF		/* all nodes default flag */
Packit db064d
Packit db064d
#define DEFAULT_HALF_WORLD_PR_TIMEOUT (3000)
Packit db064d
Packit db064d
static struct {
Packit db064d
	int nodes_checked;
Packit db064d
	int bad_nodes;
Packit db064d
	int ports_checked;
Packit db064d
	int bad_ports;
Packit db064d
	int pma_query_failures;
Packit db064d
} summary;
Packit db064d
Packit db064d
#define DEF_THRES_FILE IBDIAG_CONFIG_PATH"/error_thresholds"
Packit db064d
static const char *threshold_file = DEF_THRES_FILE;
Packit db064d
Packit db064d
/* define a "packet" with threshold values in it */
Packit db064d
static uint8_t thresholds[1204];
Packit db064d
static char *threshold_str;
Packit db064d
Packit db064d
static unsigned valid_gid(ib_gid_t * gid)
Packit db064d
{
Packit db064d
	ib_gid_t zero_gid;
Packit db064d
	memset(&zero_gid, 0, sizeof zero_gid);
Packit db064d
	return memcmp(&zero_gid, gid, sizeof(*gid));
Packit db064d
}
Packit db064d
Packit db064d
static void set_thres(char *name, uint64_t val)
Packit db064d
{
Packit db064d
	int f;
Packit db064d
	int n;
Packit db064d
	char tmp[256];
Packit db064d
	for (f = IB_PC_EXT_ERR_SYM_F; f <= IB_PC_EXT_XMT_WAIT_F; f++) {
Packit db064d
		if (strcmp(name, mad_field_name(f)) == 0) {
Packit db064d
			mad_encode_field(thresholds, f, &val;;
Packit db064d
			snprintf(tmp, 255, "[%s = %" PRIu64 "]", name, val);
Packit db064d
			threshold_str = realloc(threshold_str,
Packit db064d
					strlen(threshold_str)+strlen(tmp)+1);
Packit db064d
			if (!threshold_str) {
Packit db064d
				fprintf(stderr, "Failed to allocate memory: "
Packit db064d
					"%s\n", strerror(errno));
Packit db064d
				exit(1);
Packit db064d
			}
Packit db064d
			n = strlen(threshold_str);
Packit db064d
			strcpy(threshold_str+n, tmp);
Packit db064d
		}
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
static void set_thresholds(void)
Packit db064d
{
Packit db064d
	char buf[1024];
Packit db064d
	uint64_t val = 0;
Packit db064d
	FILE *thresf = fopen(threshold_file, "r");
Packit db064d
	char *p_prefix, *p_last;
Packit db064d
	char *name;
Packit db064d
	char *val_str;
Packit db064d
	char str[64];
Packit db064d
Packit db064d
	if (!thresf)
Packit db064d
		return;
Packit db064d
Packit db064d
	snprintf(str, 63, "Thresholds: ");
Packit db064d
	threshold_str = malloc(strlen(str)+1);
Packit db064d
	if (!threshold_str) {
Packit db064d
		fprintf(stderr, "Failed to allocate memory: %s\n",
Packit db064d
			strerror(errno));
Packit db064d
		exit(1);
Packit db064d
	}
Packit db064d
	strcpy(threshold_str, str);
Packit db064d
	while (fgets(buf, sizeof buf, thresf) != NULL) {
Packit db064d
		p_prefix = strtok_r(buf, "\n", &p_last);
Packit db064d
		if (!p_prefix)
Packit db064d
			continue; /* ignore blank lines */
Packit db064d
Packit db064d
		if (*p_prefix == '#')
Packit db064d
			continue; /* ignore comment lines */
Packit db064d
Packit db064d
		name = strtok_r(p_prefix, "=", &p_last);
Packit db064d
		val_str = strtok_r(NULL, "\n", &p_last);
Packit db064d
Packit db064d
		val = strtoul(val_str, NULL, 0);
Packit db064d
		set_thres(name, val);
Packit db064d
	}
Packit db064d
Packit db064d
	fclose(thresf);
Packit db064d
}
Packit db064d
Packit db064d
static int exceeds_threshold(int field, uint64_t val)
Packit db064d
{
Packit db064d
	uint64_t thres = 0;
Packit db064d
	mad_decode_field(thresholds, field, &thres);
Packit db064d
	return (val > thres);
Packit db064d
}
Packit db064d
Packit db064d
static void print_port_config(ibnd_node_t * node, int portnum)
Packit db064d
{
Packit db064d
	char width[64], speed[64], state[64], physstate[64];
Packit db064d
	char remote_str[256];
Packit db064d
	char link_str[256];
Packit db064d
	char width_msg[256];
Packit db064d
	char speed_msg[256];
Packit db064d
	char ext_port_str[256];
Packit db064d
	int iwidth, ispeed, fdr10, espeed, istate, iphystate, cap_mask;
Packit db064d
	uint8_t *info;
Packit db064d
	int rc;
Packit db064d
Packit db064d
	ibnd_port_t *port = node->ports[portnum];
Packit db064d
Packit db064d
	if (!port)
Packit db064d
		return;
Packit db064d
Packit db064d
	iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
Packit db064d
	ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
Packit db064d
	fdr10 = mad_get_field(port->ext_info, 0,
Packit db064d
			      IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10;
Packit db064d
Packit db064d
	if (port->node->type == IB_NODE_SWITCH)
Packit db064d
		info = (uint8_t *)&port->node->ports[0]->info;
Packit db064d
	else
Packit db064d
		info = (uint8_t *)&port->info;
Packit db064d
	cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
Packit db064d
	if (cap_mask & be32toh(IB_PORT_CAP_HAS_EXT_SPEEDS))
Packit db064d
		espeed = mad_get_field(port->info, 0,
Packit db064d
				       IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
Packit db064d
	else
Packit db064d
		espeed = 0;
Packit db064d
	istate = mad_get_field(port->info, 0, IB_PORT_STATE_F);
Packit db064d
	iphystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F);
Packit db064d
Packit db064d
	remote_str[0] = '\0';
Packit db064d
	link_str[0] = '\0';
Packit db064d
	width_msg[0] = '\0';
Packit db064d
	speed_msg[0] = '\0';
Packit db064d
Packit db064d
	/* C14-24.2.1 states that a down port allows for invalid data to be
Packit db064d
	 * returned for all PortInfo components except PortState and
Packit db064d
	 * PortPhysicalState */
Packit db064d
	if (istate != IB_LINK_DOWN) {
Packit db064d
		if (!espeed) {
Packit db064d
			if (fdr10)
Packit db064d
				sprintf(speed, "10.0 Gbps (FDR10)");
Packit db064d
			else
Packit db064d
				mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed,
Packit db064d
					     64, &ispeed);
Packit db064d
		} else
Packit db064d
			mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed,
Packit db064d
			     64, &espeed);
Packit db064d
Packit db064d
		snprintf(link_str, 256, "(%3s %18s %6s/%8s)",
Packit db064d
			 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
Packit db064d
			 speed,
Packit db064d
			 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
Packit db064d
			 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
Packit db064d
	} else {
Packit db064d
		snprintf(link_str, 256, "(              %6s/%8s)",
Packit db064d
			 mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
Packit db064d
			 mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
Packit db064d
	}
Packit db064d
Packit db064d
	if (port->remoteport) {
Packit db064d
		char *rem_node_name = NULL;
Packit db064d
Packit db064d
		if (port->remoteport->ext_portnum)
Packit db064d
			snprintf(ext_port_str, 256, "%d",
Packit db064d
				 port->remoteport->ext_portnum);
Packit db064d
		else
Packit db064d
			ext_port_str[0] = '\0';
Packit db064d
Packit db064d
		get_max_msg(width_msg, speed_msg, 256, port);
Packit db064d
Packit db064d
		rem_node_name = remap_node_name(node_name_map,
Packit db064d
						port->remoteport->node->guid,
Packit db064d
						port->remoteport->node->
Packit db064d
						nodedesc);
Packit db064d
Packit db064d
		rc = snprintf(remote_str, sizeof(remote_str),
Packit db064d
			 "0x%016" PRIx64 " %6d %4d[%2s] \"%s\" (%s %s)\n",
Packit db064d
			 port->remoteport->guid,
Packit db064d
			 port->remoteport->base_lid ? port->remoteport->
Packit db064d
			 base_lid : port->remoteport->node->smalid,
Packit db064d
			 port->remoteport->portnum, ext_port_str, rem_node_name,
Packit db064d
			 width_msg, speed_msg);
Packit db064d
		if (rc > sizeof(remote_str))
Packit db064d
			fprintf(stderr, "WARN: string buffer overflow\n");
Packit db064d
Packit db064d
		free(rem_node_name);
Packit db064d
	} else
Packit db064d
		snprintf(remote_str, 256, "           [  ] \"\" ( )\n");
Packit db064d
Packit db064d
	if (port->ext_portnum)
Packit db064d
		snprintf(ext_port_str, 256, "%d", port->ext_portnum);
Packit db064d
	else
Packit db064d
		ext_port_str[0] = '\0';
Packit db064d
Packit db064d
	if (node->type == IB_NODE_SWITCH)
Packit db064d
		printf("       Link info: %6d", node->smalid);
Packit db064d
	else
Packit db064d
		printf("       Link info: %6d", port->base_lid);
Packit db064d
Packit db064d
	printf("%4d[%2s] ==%s==>  %s",
Packit db064d
	       port->portnum, ext_port_str, link_str, remote_str);
Packit db064d
}
Packit db064d
Packit db064d
static int suppress(enum MAD_FIELDS field)
Packit db064d
{
Packit db064d
	int i = 0;
Packit db064d
	for (i = 0; i < sup_total; i++)
Packit db064d
		if (field == suppressed_fields[i])
Packit db064d
			return 1;
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static void report_suppressed(void)
Packit db064d
{
Packit db064d
	int i = 0;
Packit db064d
	printf("## Suppressed:");
Packit db064d
	for (i = 0; i < sup_total; i++)
Packit db064d
		printf(" %s", mad_field_name(suppressed_fields[i]));
Packit db064d
	printf("\n");
Packit db064d
}
Packit db064d
Packit db064d
static int print_summary(void)
Packit db064d
{
Packit db064d
	printf("\n## Summary: %d nodes checked, %d bad nodes found\n",
Packit db064d
		summary.nodes_checked, summary.bad_nodes);
Packit db064d
	printf("##          %d ports checked, %d ports have errors beyond threshold\n",
Packit db064d
		summary.ports_checked, summary.bad_ports);
Packit db064d
	printf("## %s\n", threshold_str);
Packit db064d
	if (summary.pma_query_failures)
Packit db064d
		printf("##          %d PMA query failures\n", summary.pma_query_failures);
Packit db064d
	report_suppressed();
Packit db064d
	return (summary.bad_ports);
Packit db064d
}
Packit db064d
Packit db064d
static void insert_lid2sl_table(struct sa_query_result *r)
Packit db064d
{
Packit db064d
    unsigned int i;
Packit db064d
    for (i = 0; i < r->result_cnt; i++) {
Packit db064d
	    ib_path_rec_t *p_pr = (ib_path_rec_t *)sa_get_query_rec(r->p_result_madw, i);
Packit db064d
	    lid2sl_table[be16toh(p_pr->dlid)] = ib_path_rec_sl(p_pr);
Packit db064d
    }
Packit db064d
}
Packit db064d
Packit db064d
static int path_record_query(ib_gid_t sgid,uint64_t dguid)
Packit db064d
{
Packit db064d
     ib_path_rec_t pr;
Packit db064d
     __be64 comp_mask = 0;
Packit db064d
     uint8_t reversible = 0;
Packit db064d
     struct sa_handle * h;
Packit db064d
Packit db064d
     if (!(h = sa_get_handle()))
Packit db064d
	return -1;
Packit db064d
Packit db064d
     ibd_timeout = DEFAULT_HALF_WORLD_PR_TIMEOUT;
Packit db064d
     memset(&pr, 0, sizeof(pr));
Packit db064d
Packit db064d
     CHECK_AND_SET_GID(sgid, pr.sgid, PR, SGID);
Packit db064d
     if(dguid) {
Packit db064d
	     mad_encode_field(sgid.raw, IB_GID_GUID_F, &dguid);
Packit db064d
	     CHECK_AND_SET_GID(sgid, pr.dgid, PR, DGID);
Packit db064d
     }
Packit db064d
Packit db064d
     CHECK_AND_SET_VAL(1, 8, -1, pr.num_path, PR, NUMBPATH);/*to get only one PathRecord for each source and destination pair*/
Packit db064d
     CHECK_AND_SET_VAL(1, 8, -1, reversible, PR, REVERSIBLE);/*for a reversible path*/
Packit db064d
     pr.num_path |= reversible << 7;
Packit db064d
     struct sa_query_result result;
Packit db064d
     int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE,
Packit db064d
                        (uint16_t)IB_SA_ATTR_PATHRECORD,0,be64toh(comp_mask),ibd_sakey,
Packit db064d
                        &pr, sizeof(pr), &result);
Packit db064d
     if (ret) {
Packit db064d
             sa_free_handle(h);
Packit db064d
             fprintf(stderr, "Query SA failed: %s; sa call path_query failed\n", strerror(ret));
Packit db064d
             return ret;
Packit db064d
     }
Packit db064d
     if (result.status != IB_SA_MAD_STATUS_SUCCESS) {
Packit db064d
             sa_report_err(result.status);
Packit db064d
             ret = EIO;
Packit db064d
             goto Exit;
Packit db064d
     }
Packit db064d
Packit db064d
     insert_lid2sl_table(&result);
Packit db064d
Exit:
Packit db064d
     sa_free_handle(h);
Packit db064d
     sa_free_result_mad(&result);
Packit db064d
     return ret;
Packit db064d
}
Packit db064d
Packit db064d
static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
Packit db064d
			  char *node_name, int portnum,
Packit db064d
			  const char *attr_name, uint16_t attr_id,
Packit db064d
			  int start_field, int end_field)
Packit db064d
{
Packit db064d
	uint8_t pc[1024];
Packit db064d
	uint32_t val = 0;
Packit db064d
	int i, n;
Packit db064d
Packit db064d
	memset(pc, 0, sizeof(pc));
Packit db064d
Packit db064d
	if (!pma_query_via(pc, portid, portnum, ibd_timeout, attr_id,
Packit db064d
			   ibmad_port)) {
Packit db064d
		IBWARN("%s query failed on %s, %s port %d", attr_name,
Packit db064d
		       node_name, portid2str(portid), portnum);
Packit db064d
		summary.pma_query_failures++;
Packit db064d
		return 0;
Packit db064d
	}
Packit db064d
Packit db064d
	for (n = 0, i = start_field; i < end_field; i++) {
Packit db064d
		mad_decode_field(pc, i, (void *)&val;;
Packit db064d
		if (val)
Packit db064d
			n += snprintf(buf + n, size - n, " [%s == %u]",
Packit db064d
				      mad_field_name(i), val);
Packit db064d
	}
Packit db064d
Packit db064d
	return n;
Packit db064d
}
Packit db064d
Packit db064d
static int check_threshold(uint8_t *pc, uint8_t *pce, uint32_t cap_mask2,
Packit db064d
			 int i, int ext_i, int *n, char *str, size_t size)
Packit db064d
{
Packit db064d
	uint32_t val32 = 0;
Packit db064d
	uint64_t val64 = 0;
Packit db064d
	int is_exceeds = 0;
Packit db064d
	float val = 0;
Packit db064d
	const char *unit = "";
Packit db064d
Packit db064d
	if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
Packit db064d
		mad_decode_field(pce, ext_i, (void *)&val64);
Packit db064d
		if (exceeds_threshold(ext_i, val64)) {
Packit db064d
			unit = conv_cnt_human_readable(val64, &val, 0);
Packit db064d
			*n += snprintf(str + *n, size - *n,
Packit db064d
				       " [%s == %" PRIu64 " (%5.3f%s)]",
Packit db064d
				       mad_field_name(ext_i), val64, val, unit);
Packit db064d
			is_exceeds = 1;
Packit db064d
		}
Packit db064d
Packit db064d
	} else {
Packit db064d
		mad_decode_field(pc, i, (void *)&val32);
Packit db064d
		if (exceeds_threshold(ext_i, val32)) {
Packit db064d
			*n += snprintf(str + *n, size - *n, " [%s == %u]",
Packit db064d
					  mad_field_name(i), val32);
Packit db064d
			is_exceeds = 1;
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	return is_exceeds;
Packit db064d
}
Packit db064d
Packit db064d
static int print_results(ib_portid_t * portid, char *node_name,
Packit db064d
			 ibnd_node_t * node, uint8_t * pc, int portnum,
Packit db064d
			 int *header_printed, uint8_t *pce, __be16 cap_mask,
Packit db064d
			 uint32_t cap_mask2)
Packit db064d
{
Packit db064d
	char buf[2048];
Packit db064d
	char *str = buf;
Packit db064d
	int i, ext_i, n;
Packit db064d
Packit db064d
	for (n = 0, i = IB_PC_ERR_SYM_F, ext_i = IB_PC_EXT_ERR_SYM_F;
Packit db064d
			i <= IB_PC_VL15_DROPPED_F; i++, ext_i++ ) {
Packit db064d
		if (suppress(i))
Packit db064d
			continue;
Packit db064d
Packit db064d
		/* this is not a counter, skip it */
Packit db064d
		if (i == IB_PC_COUNTER_SELECT2_F) {
Packit db064d
			ext_i--;
Packit db064d
			continue;
Packit db064d
		}
Packit db064d
Packit db064d
		if (check_threshold(pc, pce, cap_mask2, i, ext_i, &n, str, sizeof(buf))) {
Packit db064d
Packit db064d
			/* If there are PortXmitDiscards, get details (if supported) */
Packit db064d
			if (i == IB_PC_XMT_DISCARDS_F && details) {
Packit db064d
				n += query_and_dump(str + n, sizeof(buf) - n, portid,
Packit db064d
						    node_name, portnum,
Packit db064d
						    "PortXmitDiscardDetails",
Packit db064d
						    IB_GSI_PORT_XMIT_DISCARD_DETAILS,
Packit db064d
						    IB_PC_RCV_LOCAL_PHY_ERR_F,
Packit db064d
						    IB_PC_RCV_ERR_LAST_F);
Packit db064d
				/* If there are PortRcvErrors, get details (if supported) */
Packit db064d
			} else if (i == IB_PC_ERR_RCV_F && details) {
Packit db064d
				n += query_and_dump(str + n, sizeof(buf) - n, portid,
Packit db064d
						    node_name, portnum,
Packit db064d
						    "PortRcvErrorDetails",
Packit db064d
						    IB_GSI_PORT_RCV_ERROR_DETAILS,
Packit db064d
						    IB_PC_XMT_INACT_DISC_F,
Packit db064d
						    IB_PC_XMT_DISC_LAST_F);
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	if (!suppress(IB_PC_XMT_WAIT_F)) {
Packit db064d
		check_threshold(pc, pce, cap_mask2, IB_PC_XMT_WAIT_F,
Packit db064d
				IB_PC_EXT_XMT_WAIT_F, &n, str, sizeof(buf));
Packit db064d
	}
Packit db064d
Packit db064d
	/* if we found errors. */
Packit db064d
	if (n != 0) {
Packit db064d
		if (data_counters) {
Packit db064d
			uint8_t *pkt = pc;
Packit db064d
			int start_field = IB_PC_XMT_BYTES_F;
Packit db064d
			int end_field = IB_PC_RCV_PKTS_F;
Packit db064d
Packit db064d
			if (pce) {
Packit db064d
				pkt = pce;
Packit db064d
				start_field = IB_PC_EXT_XMT_BYTES_F;
Packit db064d
				if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
Packit db064d
					end_field = IB_PC_EXT_RCV_MPKTS_F;
Packit db064d
				else
Packit db064d
					end_field = IB_PC_EXT_RCV_PKTS_F;
Packit db064d
			}
Packit db064d
Packit db064d
			for (i = start_field; i <= end_field; i++) {
Packit db064d
				uint64_t val64 = 0;
Packit db064d
				float val = 0;
Packit db064d
				const char *unit = "";
Packit db064d
				mad_decode_field(pkt, i, (void *)&val64);
Packit db064d
				if (val64) {
Packit db064d
					int data = 0;
Packit db064d
					if (i == IB_PC_EXT_XMT_BYTES_F ||
Packit db064d
					    i == IB_PC_EXT_RCV_BYTES_F ||
Packit db064d
					    i == IB_PC_XMT_BYTES_F ||
Packit db064d
					    i == IB_PC_RCV_BYTES_F)
Packit db064d
						data = 1;
Packit db064d
					unit = conv_cnt_human_readable(val64,
Packit db064d
								&val, data);
Packit db064d
					n += snprintf(str + n, sizeof(buf) - n,
Packit db064d
						" [%s == %" PRIu64
Packit db064d
						" (%5.3f%s)]",
Packit db064d
						mad_field_name(i), val64, val,
Packit db064d
						unit);
Packit db064d
				}
Packit db064d
			}
Packit db064d
		}
Packit db064d
Packit db064d
		if (!*header_printed) {
Packit db064d
			if (node->type == IB_NODE_SWITCH)
Packit db064d
				printf("Errors for 0x%" PRIx64 " \"%s\"\n",
Packit db064d
					node->ports[0]->guid, node_name);
Packit db064d
			else
Packit db064d
				printf("Errors for \"%s\"\n", node_name);
Packit db064d
			*header_printed = 1;
Packit db064d
			summary.bad_nodes++;
Packit db064d
		}
Packit db064d
Packit db064d
		if (portnum == 0xFF) {
Packit db064d
			if (node->type == IB_NODE_SWITCH)
Packit db064d
				printf("   GUID 0x%" PRIx64 " port ALL:%s\n",
Packit db064d
				       node->ports[0]->guid, str);
Packit db064d
		} else {
Packit db064d
			printf("   GUID 0x%" PRIx64 " port %d:%s\n",
Packit db064d
			       node->ports[portnum]->guid, portnum, str);
Packit db064d
			if (port_config)
Packit db064d
				print_port_config(node, portnum);
Packit db064d
			summary.bad_ports++;
Packit db064d
		}
Packit db064d
	}
Packit db064d
	return (n);
Packit db064d
}
Packit db064d
Packit db064d
static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
Packit db064d
			  __be16 * cap_mask, uint32_t * cap_mask2)
Packit db064d
{
Packit db064d
	uint8_t pc[1024] = { 0 };
Packit db064d
	__be16 rc_cap_mask;
Packit db064d
	__be32 rc_cap_mask2;
Packit db064d
Packit db064d
	portid->sl = lid2sl_table[portid->lid];
Packit db064d
Packit db064d
	/* PerfMgt ClassPortInfo is a required attribute */
Packit db064d
	if (!pma_query_via(pc, portid, portnum, ibd_timeout, CLASS_PORT_INFO,
Packit db064d
			   ibmad_port)) {
Packit db064d
		IBWARN("classportinfo query failed on %s, %s port %d",
Packit db064d
		       node_name, portid2str(portid), portnum);
Packit db064d
		summary.pma_query_failures++;
Packit db064d
		return -1;
Packit db064d
	}
Packit db064d
Packit db064d
	/* ClassPortInfo should be supported as part of libibmad */
Packit db064d
	memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask));	/* CapabilityMask */
Packit db064d
	memcpy(&rc_cap_mask2, pc + 4, sizeof(rc_cap_mask2));	/* CapabilityMask2 */
Packit db064d
Packit db064d
	*cap_mask = rc_cap_mask;
Packit db064d
	*cap_mask2 = ntohl(rc_cap_mask2) >> 5;
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int print_data_cnts(ib_portid_t * portid, __be16 cap_mask,
Packit db064d
			   char *node_name, ibnd_node_t * node, int portnum,
Packit db064d
			   int *header_printed)
Packit db064d
{
Packit db064d
	uint8_t pc[1024];
Packit db064d
	int i;
Packit db064d
	int start_field = IB_PC_XMT_BYTES_F;
Packit db064d
	int end_field = IB_PC_RCV_PKTS_F;
Packit db064d
Packit db064d
	memset(pc, 0, 1024);
Packit db064d
Packit db064d
	portid->sl = lid2sl_table[portid->lid];
Packit db064d
Packit db064d
	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
Packit db064d
		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
Packit db064d
				   IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
Packit db064d
			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
Packit db064d
			       node_name, portid2str(portid), portnum);
Packit db064d
			summary.pma_query_failures++;
Packit db064d
			return (1);
Packit db064d
		}
Packit db064d
		start_field = IB_PC_EXT_XMT_BYTES_F;
Packit db064d
		if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
Packit db064d
			end_field = IB_PC_EXT_RCV_MPKTS_F;
Packit db064d
		else
Packit db064d
			end_field = IB_PC_EXT_RCV_PKTS_F;
Packit db064d
	} else {
Packit db064d
		if (!pma_query_via(pc, portid, portnum, ibd_timeout,
Packit db064d
				   IB_GSI_PORT_COUNTERS, ibmad_port)) {
Packit db064d
			IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
Packit db064d
			       node_name, portid2str(portid), portnum);
Packit db064d
			summary.pma_query_failures++;
Packit db064d
			return (1);
Packit db064d
		}
Packit db064d
		start_field = IB_PC_XMT_BYTES_F;
Packit db064d
		end_field = IB_PC_RCV_PKTS_F;
Packit db064d
	}
Packit db064d
Packit db064d
	if (!*header_printed) {
Packit db064d
		printf("Data Counters for 0x%" PRIx64 " \"%s\"\n", node->guid,
Packit db064d
		       node_name);
Packit db064d
		*header_printed = 1;
Packit db064d
	}
Packit db064d
Packit db064d
	if (portnum == 0xFF)
Packit db064d
		printf("   GUID 0x%" PRIx64 " port ALL:", node->guid);
Packit db064d
	else
Packit db064d
		printf("   GUID 0x%" PRIx64 " port %d:",
Packit db064d
		       node->guid, portnum);
Packit db064d
Packit db064d
	for (i = start_field; i <= end_field; i++) {
Packit db064d
		uint64_t val64 = 0;
Packit db064d
		float val = 0;
Packit db064d
		const char *unit = "";
Packit db064d
		int data = 0;
Packit db064d
		mad_decode_field(pc, i, (void *)&val64);
Packit db064d
		if (i == IB_PC_EXT_XMT_BYTES_F || i == IB_PC_EXT_RCV_BYTES_F ||
Packit db064d
		    i == IB_PC_XMT_BYTES_F || i == IB_PC_RCV_BYTES_F)
Packit db064d
			data = 1;
Packit db064d
		unit = conv_cnt_human_readable(val64, &val, data);
Packit db064d
		printf(" [%s == %" PRIu64 " (%5.3f%s)]", mad_field_name(i),
Packit db064d
			val64, val, unit);
Packit db064d
	}
Packit db064d
	printf("\n");
Packit db064d
Packit db064d
	if (portnum != 0xFF && port_config)
Packit db064d
		print_port_config(node, portnum);
Packit db064d
Packit db064d
	return (0);
Packit db064d
}
Packit db064d
Packit db064d
static int print_errors(ib_portid_t * portid, __be16 cap_mask, uint32_t cap_mask2,
Packit db064d
			char *node_name, ibnd_node_t * node, int portnum,
Packit db064d
			int *header_printed)
Packit db064d
{
Packit db064d
	uint8_t pc[1024];
Packit db064d
	uint8_t pce[1024];
Packit db064d
	uint8_t *pc_ext = NULL;
Packit db064d
Packit db064d
	memset(pc, 0, 1024);
Packit db064d
	memset(pce, 0, 1024);
Packit db064d
Packit db064d
	portid->sl = lid2sl_table[portid->lid];
Packit db064d
Packit db064d
	if (!pma_query_via(pc, portid, portnum, ibd_timeout,
Packit db064d
			   IB_GSI_PORT_COUNTERS, ibmad_port)) {
Packit db064d
		IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
Packit db064d
		       node_name, portid2str(portid), portnum);
Packit db064d
		summary.pma_query_failures++;
Packit db064d
		return (0);
Packit db064d
	}
Packit db064d
Packit db064d
	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
Packit db064d
		if (!pma_query_via(pce, portid, portnum, ibd_timeout,
Packit db064d
		    IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
Packit db064d
			IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
Packit db064d
			       node_name, portid2str(portid), portnum);
Packit db064d
			summary.pma_query_failures++;
Packit db064d
			return (0);
Packit db064d
		}
Packit db064d
		pc_ext = pce;
Packit db064d
	}
Packit db064d
Packit db064d
	if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
Packit db064d
		/* if PortCounters:PortXmitWait not supported clear this counter */
Packit db064d
		uint32_t foo = 0;
Packit db064d
		mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo;;
Packit db064d
	}
Packit db064d
	return (print_results(portid, node_name, node, pc, portnum,
Packit db064d
			      header_printed, pc_ext, cap_mask, cap_mask2));
Packit db064d
}
Packit db064d
Packit db064d
static uint8_t *reset_pc_ext(void *rcvbuf, ib_portid_t *dest, int port,
Packit db064d
			     unsigned mask, unsigned timeout,
Packit db064d
			     const struct ibmad_port *srcport)
Packit db064d
{
Packit db064d
	ib_rpc_t rpc = { 0 };
Packit db064d
	int lid = dest->lid;
Packit db064d
Packit db064d
	DEBUG("lid %u port %d mask 0x%x", lid, port, mask);
Packit db064d
Packit db064d
	if (lid == -1) {
Packit db064d
		IBWARN("only lid routed is supported");
Packit db064d
		return NULL;
Packit db064d
	}
Packit db064d
Packit db064d
	if (!mask)
Packit db064d
		mask = ~0;
Packit db064d
Packit db064d
	rpc.mgtclass = IB_PERFORMANCE_CLASS;
Packit db064d
	rpc.method = IB_MAD_METHOD_SET;
Packit db064d
	rpc.attr.id = IB_GSI_PORT_COUNTERS_EXT;
Packit db064d
Packit db064d
	memset(rcvbuf, 0, IB_MAD_SIZE);
Packit db064d
Packit db064d
	/* Same for attribute IDs */
Packit db064d
	mad_set_field(rcvbuf, 0, IB_PC_EXT_PORT_SELECT_F, port);
Packit db064d
	mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT_F, mask);
Packit db064d
	mask = mask >> 16;
Packit db064d
	mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT2_F, mask);
Packit db064d
	rpc.attr.mod = 0;
Packit db064d
	rpc.timeout = timeout;
Packit db064d
	rpc.datasz = IB_PC_DATA_SZ;
Packit db064d
	rpc.dataoffs = IB_PC_DATA_OFFS;
Packit db064d
	if (!dest->qp)
Packit db064d
		dest->qp = 1;
Packit db064d
	if (!dest->qkey)
Packit db064d
		dest->qkey = IB_DEFAULT_QP1_QKEY;
Packit db064d
Packit db064d
	return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
Packit db064d
}
Packit db064d
Packit db064d
static void clear_port(ib_portid_t * portid, __be16 cap_mask, uint32_t cap_mask2,
Packit db064d
		       char *node_name, int port)
Packit db064d
{
Packit db064d
	uint8_t pc[1024] = { 0 };
Packit db064d
	/* bits defined in Table 228 PortCounters CounterSelect and
Packit db064d
	 * CounterSelect2
Packit db064d
	 */
Packit db064d
	uint32_t mask = 0;
Packit db064d
Packit db064d
	if (clear_errors) {
Packit db064d
		mask |= 0xFFF;
Packit db064d
		if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
Packit db064d
			mask |= 0x10000;
Packit db064d
	}
Packit db064d
	if (clear_counts)
Packit db064d
		mask |= 0xF000;
Packit db064d
Packit db064d
	if (mask)
Packit db064d
		if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
Packit db064d
					   IB_GSI_PORT_COUNTERS, ibmad_port))
Packit db064d
			fprintf(stderr, "Failed to reset errors %s port %d\n", node_name,
Packit db064d
				port);
Packit db064d
Packit db064d
	if (clear_errors && details) {
Packit db064d
		memset(pc, 0, 1024);
Packit db064d
		performance_reset_via(pc, portid, port, 0xf, ibd_timeout,
Packit db064d
				      IB_GSI_PORT_XMIT_DISCARD_DETAILS,
Packit db064d
				      ibmad_port);
Packit db064d
		memset(pc, 0, 1024);
Packit db064d
		performance_reset_via(pc, portid, port, 0x3f, ibd_timeout,
Packit db064d
				      IB_GSI_PORT_RCV_ERROR_DETAILS,
Packit db064d
				      ibmad_port);
Packit db064d
	}
Packit db064d
Packit db064d
	if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
Packit db064d
		mask = 0;
Packit db064d
		if (clear_counts) {
Packit db064d
			if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
Packit db064d
				mask = 0xFF;
Packit db064d
			else
Packit db064d
				mask = 0x0F;
Packit db064d
		}
Packit db064d
Packit db064d
		if (clear_errors && (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP)) {
Packit db064d
			mask |= 0xfff0000;
Packit db064d
			if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
Packit db064d
				mask |= (1 << 28);
Packit db064d
		}
Packit db064d
Packit db064d
		if (mask && !reset_pc_ext(pc, portid, port, mask, ibd_timeout,
Packit db064d
		    ibmad_port))
Packit db064d
			fprintf(stderr, "Failed to reset extended data counters %s, "
Packit db064d
				"%s port %d\n", node_name, portid2str(portid),
Packit db064d
				port);
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
static void print_node(ibnd_node_t *node, void *user_data)
Packit db064d
{
Packit db064d
	int header_printed = 0;
Packit db064d
	int p = 0;
Packit db064d
	int startport = 1;
Packit db064d
	int type = 0;
Packit db064d
	int all_port_sup = 0;
Packit db064d
	ib_portid_t portid = { 0 };
Packit db064d
	__be16 cap_mask = 0;
Packit db064d
	uint32_t cap_mask2 = 0;
Packit db064d
	char *node_name = NULL;
Packit db064d
Packit db064d
	switch (node->type) {
Packit db064d
	case IB_NODE_SWITCH:
Packit db064d
		type = PRINT_SWITCH;
Packit db064d
		break;
Packit db064d
	case IB_NODE_CA:
Packit db064d
		type = PRINT_CA;
Packit db064d
		break;
Packit db064d
	case IB_NODE_ROUTER:
Packit db064d
		type = PRINT_ROUTER;
Packit db064d
		break;
Packit db064d
	}
Packit db064d
Packit db064d
	if ((type & node_type_to_print) == 0)
Packit db064d
		return;
Packit db064d
Packit db064d
	if (node->type == IB_NODE_SWITCH && node->smaenhsp0)
Packit db064d
		startport = 0;
Packit db064d
Packit db064d
	node_name = remap_node_name(node_name_map, node->guid, node->nodedesc);
Packit db064d
Packit db064d
	if (node->type == IB_NODE_SWITCH) {
Packit db064d
		ib_portid_set(&portid, node->smalid, 0, 0);
Packit db064d
		p = 0;
Packit db064d
	} else {
Packit db064d
		for (p = 1; p <= node->numports; p++) {
Packit db064d
			if (node->ports[p]) {
Packit db064d
				ib_portid_set(&portid,
Packit db064d
					      node->ports[p]->base_lid,
Packit db064d
					      0, 0);
Packit db064d
				break;
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	if ((query_cap_mask(&portid, node_name, p, &cap_mask, &cap_mask2) == 0) &&
Packit db064d
	    (cap_mask & IB_PM_ALL_PORT_SELECT))
Packit db064d
		all_port_sup = 1;
Packit db064d
Packit db064d
	if (data_counters_only) {
Packit db064d
		for (p = startport; p <= node->numports; p++) {
Packit db064d
			if (node->ports[p]) {
Packit db064d
				if (node->type == IB_NODE_SWITCH)
Packit db064d
					ib_portid_set(&portid, node->smalid, 0, 0);
Packit db064d
				else
Packit db064d
					ib_portid_set(&portid, node->ports[p]->base_lid,
Packit db064d
						      0, 0);
Packit db064d
Packit db064d
				print_data_cnts(&portid, cap_mask, node_name, node, p,
Packit db064d
						&header_printed);
Packit db064d
				summary.ports_checked++;
Packit db064d
				if (!all_port_sup)
Packit db064d
					clear_port(&portid, cap_mask, cap_mask2, node_name, p);
Packit db064d
			}
Packit db064d
		}
Packit db064d
	} else {
Packit db064d
		if (all_port_sup)
Packit db064d
			if (!print_errors(&portid, cap_mask, cap_mask2, node_name, node,
Packit db064d
					  0xFF, &header_printed)) {
Packit db064d
				summary.ports_checked += node->numports;
Packit db064d
				goto clear;
Packit db064d
			}
Packit db064d
Packit db064d
		for (p = startport; p <= node->numports; p++) {
Packit db064d
			if (node->ports[p]) {
Packit db064d
				if (node->type == IB_NODE_SWITCH)
Packit db064d
					ib_portid_set(&portid, node->smalid, 0, 0);
Packit db064d
				else
Packit db064d
					ib_portid_set(&portid, node->ports[p]->base_lid,
Packit db064d
						      0, 0);
Packit db064d
Packit db064d
				print_errors(&portid, cap_mask, cap_mask2, node_name, node, p,
Packit db064d
					     &header_printed);
Packit db064d
				summary.ports_checked++;
Packit db064d
				if (!all_port_sup)
Packit db064d
					clear_port(&portid, cap_mask, cap_mask2, node_name, p);
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
clear:
Packit db064d
	summary.nodes_checked++;
Packit db064d
	if (all_port_sup)
Packit db064d
		clear_port(&portid, cap_mask, cap_mask2, node_name, 0xFF);
Packit db064d
Packit db064d
	free(node_name);
Packit db064d
}
Packit db064d
Packit db064d
static void add_suppressed(enum MAD_FIELDS field)
Packit db064d
{
Packit db064d
	if (sup_total >= SUP_MAX) {
Packit db064d
		IBWARN("Maximum (%d) fields have been suppressed; skipping %s",
Packit db064d
		       sup_total, mad_field_name(field));
Packit db064d
		return;
Packit db064d
	}
Packit db064d
	suppressed_fields[sup_total++] = field;
Packit db064d
}
Packit db064d
Packit db064d
static void calculate_suppressed_fields(char *str)
Packit db064d
{
Packit db064d
	enum MAD_FIELDS f;
Packit db064d
	char *val, *lasts = NULL;
Packit db064d
	char *tmp = strdup(str);
Packit db064d
Packit db064d
	val = strtok_r(tmp, ",", &lasts);
Packit db064d
	while (val) {
Packit db064d
		for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++)
Packit db064d
			if (strcmp(val, mad_field_name(f)) == 0)
Packit db064d
				add_suppressed(f);
Packit db064d
		val = strtok_r(NULL, ",", &lasts);
Packit db064d
	}
Packit db064d
Packit db064d
	free(tmp);
Packit db064d
}
Packit db064d
Packit db064d
static int process_opt(void *context, int ch)
Packit db064d
{
Packit db064d
	struct ibnd_config *cfg = context;
Packit db064d
	switch (ch) {
Packit db064d
	case 's':
Packit db064d
		calculate_suppressed_fields(optarg);
Packit db064d
		break;
Packit db064d
	case 'c':
Packit db064d
		/* Right now this is the only "common" error */
Packit db064d
		add_suppressed(IB_PC_ERR_SWITCH_REL_F);
Packit db064d
		break;
Packit db064d
	case 1:
Packit db064d
		node_name_map_file = strdup(optarg);
Packit db064d
		if (node_name_map_file == NULL)
Packit db064d
			IBEXIT("out of memory, strdup for node_name_map_file name failed");
Packit db064d
		break;
Packit db064d
	case 2:
Packit db064d
		data_counters++;
Packit db064d
		break;
Packit db064d
	case 3:
Packit db064d
		node_type_to_print |= PRINT_SWITCH;
Packit db064d
		break;
Packit db064d
	case 4:
Packit db064d
		node_type_to_print |= PRINT_CA;
Packit db064d
		break;
Packit db064d
	case 5:
Packit db064d
		node_type_to_print |= PRINT_ROUTER;
Packit db064d
		break;
Packit db064d
	case 6:
Packit db064d
		details = 1;
Packit db064d
		break;
Packit db064d
	case 7:
Packit db064d
		load_cache_file = strdup(optarg);
Packit db064d
		break;
Packit db064d
	case 8:
Packit db064d
		threshold_file = strdup(optarg);
Packit db064d
		break;
Packit db064d
	case 9:
Packit db064d
		data_counters_only = 1;
Packit db064d
		break;
Packit db064d
	case 10:
Packit db064d
		obtain_sl = 0;
Packit db064d
		break;
Packit db064d
	case 'G':
Packit db064d
	case 'S':
Packit db064d
		port_guid_str = optarg;
Packit db064d
		port_guid = strtoull(optarg, NULL, 0);
Packit db064d
		break;
Packit db064d
	case 'D':
Packit db064d
		dr_path = strdup(optarg);
Packit db064d
		break;
Packit db064d
	case 'r':
Packit db064d
		port_config++;
Packit db064d
		break;
Packit db064d
	case 'R':		/* nop */
Packit db064d
		break;
Packit db064d
	case 'k':
Packit db064d
		clear_errors = 1;
Packit db064d
		break;
Packit db064d
	case 'K':
Packit db064d
		clear_counts = 1;
Packit db064d
		break;
Packit db064d
	case 'o':
Packit db064d
		cfg->max_smps = strtoul(optarg, NULL, 0);
Packit db064d
		break;
Packit db064d
	default:
Packit db064d
		return -1;
Packit db064d
	}
Packit db064d
Packit db064d
	return 0;
Packit db064d
}
Packit db064d
Packit db064d
int main(int argc, char **argv)
Packit db064d
{
Packit db064d
	struct ibnd_config config = { 0 };
Packit db064d
	int resolved = -1;
Packit db064d
	ib_portid_t portid = { 0 };
Packit db064d
	ib_portid_t self_portid = { 0 };
Packit db064d
	int rc = 0;
Packit db064d
	ibnd_fabric_t *fabric = NULL;
Packit db064d
	ib_gid_t self_gid;
Packit db064d
	int port = 0;
Packit db064d
Packit db064d
	int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS,
Packit db064d
		IB_PERFORMANCE_CLASS
Packit db064d
	};
Packit db064d
Packit db064d
	const struct ibdiag_opt opts[] = {
Packit db064d
		{"suppress", 's', 1, "<err1,err2,...>",
Packit db064d
		 "suppress errors listed"},
Packit db064d
		{"suppress-common", 'c', 0, NULL,
Packit db064d
		 "suppress some of the common counters"},
Packit db064d
		{"node-name-map", 1, 1, "<file>", "node name map file"},
Packit db064d
		{"port-guid", 'G', 1, "<port_guid>",
Packit db064d
		 "report the node containing the port specified by <port_guid>"},
Packit db064d
		{"", 'S', 1, "<port_guid>",
Packit db064d
		 "Same as \"-G\" for backward compatibility"},
Packit db064d
		{"Direct", 'D', 1, "<dr_path>",
Packit db064d
		 "report the node containing the port specified by <dr_path>"},
Packit db064d
		{"skip-sl", 10, 0, NULL,"don't obtain SL to all destinations"},
Packit db064d
		{"report-port", 'r', 0, NULL,
Packit db064d
		 "report port link information"},
Packit db064d
		{"threshold-file", 8, 1, NULL,
Packit db064d
		 "specify an alternate threshold file, default: " DEF_THRES_FILE},
Packit db064d
		{"GNDN", 'R', 0, NULL,
Packit db064d
		 "(This option is obsolete and does nothing)"},
Packit db064d
		{"data", 2, 0, NULL, "include data counters for ports with errors"},
Packit db064d
		{"switch", 3, 0, NULL, "print data for switches only"},
Packit db064d
		{"ca", 4, 0, NULL, "print data for CA's only"},
Packit db064d
		{"router", 5, 0, NULL, "print data for routers only"},
Packit db064d
		{"details", 6, 0, NULL, "include transmit discard details"},
Packit db064d
		{"counters", 9, 0, NULL, "print data counters only"},
Packit db064d
		{"clear-errors", 'k', 0, NULL,
Packit db064d
		 "Clear error counters after read"},
Packit db064d
		{"clear-counts", 'K', 0, NULL,
Packit db064d
		 "Clear data counters after read"},
Packit db064d
		{"load-cache", 7, 1, "<file>",
Packit db064d
		 "filename of ibnetdiscover cache to load"},
Packit db064d
		{"outstanding_smps", 'o', 1, NULL,
Packit db064d
		 "specify the number of outstanding SMP's which should be "
Packit db064d
		 "issued during the scan"},
Packit db064d
		{}
Packit db064d
	};
Packit db064d
	char usage_args[] = "";
Packit db064d
Packit db064d
	memset(suppressed_fields, 0, sizeof suppressed_fields);
Packit db064d
	ibdiag_process_opts(argc, argv, &config, "cDGKLnRrSs", opts, process_opt,
Packit db064d
			    usage_args, NULL);
Packit db064d
Packit db064d
	argc -= optind;
Packit db064d
	argv += optind;
Packit db064d
Packit db064d
	if (!node_type_to_print)
Packit db064d
		node_type_to_print = PRINT_ALL;
Packit db064d
Packit db064d
	ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4);
Packit db064d
	if (!ibmad_port)
Packit db064d
		IBEXIT("Failed to open port; %s:%d\n", ibd_ca, ibd_ca_port);
Packit db064d
Packit db064d
	smp_mkey_set(ibmad_port, ibd_mkey);
Packit db064d
Packit db064d
	if (ibd_timeout) {
Packit db064d
		mad_rpc_set_timeout(ibmad_port, ibd_timeout);
Packit db064d
		config.timeout_ms = ibd_timeout;
Packit db064d
	}
Packit db064d
Packit db064d
	config.flags = ibd_ibnetdisc_flags;
Packit db064d
	config.mkey = ibd_mkey;
Packit db064d
Packit db064d
	if (dr_path && load_cache_file) {
Packit db064d
		mad_rpc_close_port(ibmad_port);
Packit db064d
		fprintf(stderr, "Cannot specify cache and direct route path\n");
Packit db064d
		exit(-1);
Packit db064d
	}
Packit db064d
Packit db064d
	if (resolve_self(ibd_ca, ibd_ca_port, &self_portid, &port, &self_gid.raw) < 0) {
Packit db064d
		mad_rpc_close_port(ibmad_port);
Packit db064d
		IBEXIT("can't resolve self port %s", argv[0]);
Packit db064d
	}
Packit db064d
Packit db064d
	node_name_map = open_node_name_map(node_name_map_file);
Packit db064d
Packit db064d
	/* limit the scan the fabric around the target */
Packit db064d
	if (dr_path) {
Packit db064d
		if ((resolved =
Packit db064d
		     resolve_portid_str(ibd_ca, ibd_ca_port, &portid, dr_path,
Packit db064d
					IB_DEST_DRPATH, NULL, ibmad_port)) < 0)
Packit db064d
			IBWARN("Failed to resolve %s; attempting full scan",
Packit db064d
			       dr_path);
Packit db064d
	} else if (port_guid_str) {
Packit db064d
		if ((resolved =
Packit db064d
		     resolve_portid_str(ibd_ca, ibd_ca_port, &portid,
Packit db064d
					port_guid_str, IB_DEST_GUID, ibd_sm_id,
Packit db064d
					       ibmad_port)) < 0)
Packit db064d
			IBWARN("Failed to resolve %s; attempting full scan",
Packit db064d
			       port_guid_str);
Packit db064d
		if(obtain_sl)
Packit db064d
			lid2sl_table[portid.lid] = portid.sl;
Packit db064d
	}
Packit db064d
Packit db064d
	mad_rpc_close_port(ibmad_port);
Packit db064d
Packit db064d
	if (load_cache_file) {
Packit db064d
		if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
Packit db064d
			fprintf(stderr, "loading cached fabric failed\n");
Packit db064d
			rc = -1;
Packit db064d
			goto close_name_map;
Packit db064d
		}
Packit db064d
	} else {
Packit db064d
		if (resolved >= 0) {
Packit db064d
			if (!config.max_hops)
Packit db064d
				config.max_hops = 1;
Packit db064d
			if (!(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
Packit db064d
						    &portid, &config)))
Packit db064d
				IBWARN("Single node discover failed;"
Packit db064d
				       " attempting full scan");
Packit db064d
		}
Packit db064d
Packit db064d
		if (!fabric && !(fabric = ibnd_discover_fabric(ibd_ca,
Packit db064d
							       ibd_ca_port,
Packit db064d
							       NULL,
Packit db064d
							       &config))) {
Packit db064d
			fprintf(stderr, "discover failed\n");
Packit db064d
			rc = -1;
Packit db064d
			goto close_name_map;
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
	set_thresholds();
Packit db064d
Packit db064d
	/* reopen the global ibmad_port */
Packit db064d
	ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port,
Packit db064d
				       mgmt_classes, 4);
Packit db064d
	if (!ibmad_port) {
Packit db064d
		ibnd_destroy_fabric(fabric);
Packit db064d
		close_node_name_map(node_name_map);
Packit db064d
		IBEXIT("Failed to reopen port: %s:%d\n",
Packit db064d
			ibd_ca, ibd_ca_port);
Packit db064d
	}
Packit db064d
Packit db064d
	smp_mkey_set(ibmad_port, ibd_mkey);
Packit db064d
Packit db064d
	if (ibd_timeout)
Packit db064d
		mad_rpc_set_timeout(ibmad_port, ibd_timeout);
Packit db064d
Packit db064d
	if (port_guid_str) {
Packit db064d
		ibnd_port_t *ndport = ibnd_find_port_guid(fabric, port_guid);
Packit db064d
		if (ndport)
Packit db064d
			print_node(ndport->node, NULL);
Packit db064d
		else
Packit db064d
			fprintf(stderr, "Failed to find node: %s\n",
Packit db064d
				port_guid_str);
Packit db064d
	} else if (dr_path) {
Packit db064d
		ibnd_port_t *ndport;
Packit db064d
Packit db064d
		uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
Packit db064d
		if (!smp_query_via(ni, &portid, IB_ATTR_NODE_INFO, 0,
Packit db064d
			   ibd_timeout, ibmad_port)) {
Packit db064d
				fprintf(stderr, "Failed to query local Node Info\n");
Packit db064d
				goto close_port;
Packit db064d
		}
Packit db064d
Packit db064d
		mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(port_guid));
Packit db064d
Packit db064d
		ndport = ibnd_find_port_guid(fabric, port_guid);
Packit db064d
		if (ndport) {
Packit db064d
			if(obtain_sl)
Packit db064d
				if(path_record_query(self_gid,ndport->guid))
Packit db064d
					goto close_port;
Packit db064d
			print_node(ndport->node, NULL);
Packit db064d
		} else
Packit db064d
			fprintf(stderr, "Failed to find node: %s\n", dr_path);
Packit db064d
	} else {
Packit db064d
		if(obtain_sl)
Packit db064d
			if(path_record_query(self_gid,0))
Packit db064d
				goto close_port;
Packit db064d
Packit db064d
		ibnd_iter_nodes(fabric, print_node, NULL);
Packit db064d
	}
Packit db064d
Packit db064d
	rc = print_summary();
Packit db064d
	if (rc)
Packit db064d
		rc = 1;
Packit db064d
Packit db064d
close_port:
Packit db064d
	mad_rpc_close_port(ibmad_port);
Packit db064d
	ibnd_destroy_fabric(fabric);
Packit db064d
Packit db064d
close_name_map:
Packit db064d
	close_node_name_map(node_name_map);
Packit db064d
	exit(rc);
Packit db064d
}