Blame src/ibportstate.c

Packit db064d
/*
Packit db064d
 * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
Packit db064d
 * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
Packit db064d
 * Copyright (c) 2011,2016 Oracle and/or its affiliates. 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
#include <stdio.h>
Packit db064d
#include <stdlib.h>
Packit db064d
#include <unistd.h>
Packit db064d
#include <string.h>
Packit db064d
#include <errno.h>
Packit db064d
Packit db064d
#include <infiniband/umad.h>
Packit db064d
#include <infiniband/mad.h>
Packit db064d
Packit db064d
#include "ibdiag_common.h"
Packit db064d
Packit db064d
enum port_ops {
Packit db064d
	QUERY,
Packit db064d
	ENABLE,
Packit db064d
	RESET,
Packit db064d
	DISABLE,
Packit db064d
	SPEED,
Packit db064d
	ESPEED,
Packit db064d
	FDR10SPEED,
Packit db064d
	WIDTH,
Packit db064d
	DOWN,
Packit db064d
	ARM,
Packit db064d
	ACTIVE,
Packit db064d
	VLS,
Packit db064d
	MTU,
Packit db064d
	LID,
Packit db064d
	SMLID,
Packit db064d
	LMC,
Packit db064d
	MKEY,
Packit db064d
	MKEYLEASE,
Packit db064d
	MKEYPROT,
Packit db064d
	ON,
Packit db064d
	OFF
Packit db064d
};
Packit db064d
Packit db064d
static struct ibmad_port *srcport;
Packit db064d
static uint64_t speed; /* no state change */
Packit db064d
static uint64_t espeed; /* no state change */
Packit db064d
static uint64_t fdr10; /* no state change */
Packit db064d
static uint64_t width; /* no state change */
Packit db064d
static uint64_t lid;
Packit db064d
static uint64_t smlid;
Packit db064d
static uint64_t lmc;
Packit db064d
static uint64_t mtu;
Packit db064d
static uint64_t vls; /* no state change */
Packit db064d
static uint64_t mkey;
Packit db064d
static uint64_t mkeylease;
Packit db064d
static uint64_t mkeyprot;
Packit db064d
Packit db064d
static struct {
Packit db064d
	const char *name;
Packit db064d
	uint64_t *val;
Packit db064d
	int set;
Packit db064d
} port_args[] = {
Packit db064d
	{"query", NULL, 0},	/* QUERY */
Packit db064d
	{"enable", NULL, 0},	/* ENABLE */
Packit db064d
	{"reset", NULL, 0},	/* RESET */
Packit db064d
	{"disable", NULL, 0},	/* DISABLE */
Packit db064d
	{"speed", &speed, 0},	/* SPEED */
Packit db064d
	{"espeed", &espeed, 0},	/* EXTENDED SPEED */
Packit db064d
	{"fdr10", &fdr10, 0},	/* FDR10 SPEED */
Packit db064d
	{"width", &width, 0},	/* WIDTH */
Packit db064d
	{"down", NULL, 0},	/* DOWN */
Packit db064d
	{"arm", NULL, 0},	/* ARM */
Packit db064d
	{"active", NULL, 0},	/* ACTIVE */
Packit db064d
	{"vls", &vls, 0},	/* VLS */
Packit db064d
	{"mtu", &mtu, 0},	/* MTU */
Packit db064d
	{"lid", &lid, 0},	/* LID */
Packit db064d
	{"smlid", &smlid, 0},	/* SMLID */
Packit db064d
	{"lmc", &lmc, 0},	/* LMC */
Packit db064d
	{"mkey", &mkey, 0},	/* MKEY */
Packit db064d
	{"mkeylease", &mkeylease, 0},	/* MKEY LEASE */
Packit db064d
	{"mkeyprot", &mkeyprot, 0},	/* MKEY PROTECT BITS */
Packit db064d
	{"on", NULL, 0},	/* ON */
Packit db064d
	{"off", NULL, 0},	/* OFF */
Packit db064d
};
Packit db064d
Packit db064d
#define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
Packit db064d
Packit db064d
/*******************************************/
Packit db064d
Packit db064d
/*
Packit db064d
 * Return 1 if node is a switch, else zero.
Packit db064d
 */
Packit db064d
static int get_node_info(ib_portid_t * dest, uint8_t * data)
Packit db064d
{
Packit db064d
	int node_type;
Packit db064d
Packit db064d
	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
Packit db064d
		IBEXIT("smp query nodeinfo failed");
Packit db064d
Packit db064d
	node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
Packit db064d
	if (node_type == IB_NODE_SWITCH)	/* Switch NodeType ? */
Packit db064d
		return 1;
Packit db064d
	else
Packit db064d
		return 0;
Packit db064d
}
Packit db064d
Packit db064d
static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
Packit db064d
			 int is_switch)
Packit db064d
{
Packit db064d
	uint8_t smp[IB_SMP_DATA_SIZE];
Packit db064d
	uint8_t *info;
Packit db064d
	int cap_mask;
Packit db064d
Packit db064d
	if (is_switch) {
Packit db064d
		if (!smp_query_via(smp, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
Packit db064d
			IBEXIT("smp query port 0 portinfo failed");
Packit db064d
		info = smp;
Packit db064d
	} else
Packit db064d
		info = data;
Packit db064d
Packit db064d
	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
Packit db064d
		IBEXIT("smp query portinfo failed");
Packit db064d
	cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
Packit db064d
	return (cap_mask & be32toh(IB_PORT_CAP_HAS_EXT_SPEEDS));
Packit db064d
}
Packit db064d
Packit db064d
static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
Packit db064d
			   int espeed_cap, int is_switch)
Packit db064d
{
Packit db064d
	char buf[2300];
Packit db064d
	char val[64];
Packit db064d
Packit db064d
	mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
Packit db064d
	mad_decode_field(data, IB_PORT_LID_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_SMLID_F, val);
Packit db064d
	mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LMC_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
Packit db064d
	mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
Packit db064d
		       sizeof buf - strlen(buf), val);
Packit db064d
	sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	if (espeed_cap) {
Packit db064d
		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val);
Packit db064d
		mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
Packit db064d
			       buf + strlen(buf), sizeof buf - strlen(buf),
Packit db064d
			       val);
Packit db064d
		sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val);
Packit db064d
		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F,
Packit db064d
			       buf + strlen(buf), sizeof buf - strlen(buf),
Packit db064d
			       val);
Packit db064d
		sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val);
Packit db064d
		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
Packit db064d
			       buf + strlen(buf), sizeof buf - strlen(buf),
Packit db064d
			       val);
Packit db064d
		sprintf(buf + strlen(buf), "%s", "\n");
Packit db064d
	}
Packit db064d
	if (!is_switch || portnum == 0) {
Packit db064d
		if (show_keys) {
Packit db064d
			mad_decode_field(data, IB_PORT_MKEY_F, val);
Packit db064d
			mad_dump_field(IB_PORT_MKEY_F, buf + strlen(buf),
Packit db064d
				       sizeof buf - strlen(buf), val);
Packit db064d
		} else
Packit db064d
			snprint_field(buf+strlen(buf), sizeof(buf)-strlen(buf),
Packit db064d
				      IB_PORT_MKEY_F, 32, NOT_DISPLAYED_STR);
Packit db064d
		sprintf(buf+strlen(buf), "%s", "\n");
Packit db064d
		mad_decode_field(data, IB_PORT_MKEY_LEASE_F, val);
Packit db064d
		mad_dump_field(IB_PORT_MKEY_LEASE_F, buf + strlen(buf),
Packit db064d
			       sizeof buf - strlen(buf), val);
Packit db064d
		sprintf(buf+strlen(buf), "%s", "\n");
Packit db064d
		mad_decode_field(data, IB_PORT_MKEY_PROT_BITS_F, val);
Packit db064d
		mad_dump_field(IB_PORT_MKEY_PROT_BITS_F, buf + strlen(buf),
Packit db064d
			       sizeof buf - strlen(buf), val);
Packit db064d
		sprintf(buf+strlen(buf), "%s", "\n");
Packit db064d
	}
Packit db064d
Packit db064d
	printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
Packit db064d
}
Packit db064d
Packit db064d
static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
Packit db064d
			  int espeed_cap, int is_switch)
Packit db064d
{
Packit db064d
	unsigned mod;
Packit db064d
Packit db064d
	mod = portnum;
Packit db064d
	if (espeed_cap)
Packit db064d
		mod |= 1<<31;
Packit db064d
	if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, mod, 0, srcport))
Packit db064d
		IBEXIT("smp set portinfo failed");
Packit db064d
Packit db064d
	printf("\nAfter PortInfo set:\n");
Packit db064d
	show_port_info(dest, data, portnum, espeed_cap, is_switch);
Packit db064d
}
Packit db064d
Packit db064d
static void get_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
Packit db064d
{
Packit db064d
	if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
Packit db064d
			   portnum, 0, srcport))
Packit db064d
		IBEXIT("smp query ext portinfo failed");
Packit db064d
}
Packit db064d
Packit db064d
static void show_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
Packit db064d
{
Packit db064d
	char buf[256];
Packit db064d
Packit db064d
	mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, IB_SMP_DATA_SIZE);
Packit db064d
Packit db064d
	printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest),
Packit db064d
	       portnum, buf);
Packit db064d
}
Packit db064d
Packit db064d
static void set_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
Packit db064d
{
Packit db064d
	if (!smp_set_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
Packit db064d
			 portnum, 0, srcport))
Packit db064d
		IBEXIT("smp set MLNX ext portinfo failed");
Packit db064d
Packit db064d
	printf("\nAfter MLNXExtendedPortInfo set:\n");
Packit db064d
	show_mlnx_ext_port_info(dest, data, portnum);
Packit db064d
}
Packit db064d
Packit db064d
static int get_link_width(int lwe, int lws)
Packit db064d
{
Packit db064d
	if (lwe == 255)
Packit db064d
		return lws;
Packit db064d
	else
Packit db064d
		return lwe;
Packit db064d
}
Packit db064d
Packit db064d
static int get_link_speed(int lse, int lss)
Packit db064d
{
Packit db064d
	if (lse == 15)
Packit db064d
		return lss;
Packit db064d
	else
Packit db064d
		return lse;
Packit db064d
}
Packit db064d
Packit db064d
static int get_link_speed_ext(int lsee, int lses)
Packit db064d
{
Packit db064d
	if (lsee == 31)
Packit db064d
		return lses;
Packit db064d
	else
Packit db064d
		return lsee;
Packit db064d
}
Packit db064d
Packit db064d
static void validate_width(int peerwidth, int lwa)
Packit db064d
{
Packit db064d
	if ((width & peerwidth & 0x8)) {
Packit db064d
		if (lwa != 8)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active width %d rather than 8 (12x)",
Packit db064d
			     lwa);
Packit db064d
	} else if ((width & peerwidth & 0x4)) {
Packit db064d
		if (lwa != 4)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active width %d rather than 4 (8x)",
Packit db064d
			     lwa);
Packit db064d
	} else if ((width & peerwidth & 0x2)) {
Packit db064d
		if (lwa != 2)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active width %d rather than 2 (4x)",
Packit db064d
			     lwa);
Packit db064d
	} else if ((width & peerwidth & 0x10)) {
Packit db064d
		if (lwa != 16)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active width %d rather than 16 (2x)",
Packit db064d
			      lwa);
Packit db064d
	} else if ((width & peerwidth & 0x1)) {
Packit db064d
		if (lwa != 1)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active width %d rather than 1 (1x)",
Packit db064d
			     lwa);
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
static void validate_speed(int peerspeed, int lsa)
Packit db064d
{
Packit db064d
	if ((speed & peerspeed & 0x4)) {
Packit db064d
		if (lsa != 4)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
Packit db064d
			     lsa);
Packit db064d
	} else if ((speed & peerspeed & 0x2)) {
Packit db064d
		if (lsa != 2)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)",
Packit db064d
			     lsa);
Packit db064d
	} else if ((speed & peerspeed & 0x1)) {
Packit db064d
		if (lsa != 1)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)",
Packit db064d
			     lsa);
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
static void validate_extended_speed(int peerespeed, int lsea)
Packit db064d
{
Packit db064d
	if ((espeed & peerespeed & 0x4)) {
Packit db064d
		if (lsea != 4)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active extended speed %d rather than 4 (53.125 Gbps)",
Packit db064d
			     lsea);
Packit db064d
	} else if ((espeed & peerespeed & 0x2)) {
Packit db064d
		if (lsea != 2)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)",
Packit db064d
			     lsea);
Packit db064d
	} else if ((espeed & peerespeed & 0x1)) {
Packit db064d
		if (lsea != 1)
Packit db064d
			IBWARN
Packit db064d
			    ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)",
Packit db064d
			     lsea);
Packit db064d
	}
Packit db064d
}
Packit db064d
Packit db064d
int main(int argc, char **argv)
Packit db064d
{
Packit db064d
	int mgmt_classes[3] =
Packit db064d
	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
Packit db064d
	ib_portid_t portid = { 0 };
Packit db064d
	int port_op = -1;
Packit db064d
	int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
Packit db064d
	int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea,
Packit db064d
	    fdr10s, fdr10e, fdr10a;
Packit db064d
	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
Packit db064d
	    peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e,
Packit db064d
	    peerfdr10a;
Packit db064d
	int peerwidth, peerspeed, peerespeed;
Packit db064d
	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
Packit db064d
	uint8_t data2[IB_SMP_DATA_SIZE] = { 0 };
Packit db064d
	ib_portid_t peerportid = { 0 };
Packit db064d
	int portnum = 0;
Packit db064d
	ib_portid_t selfportid = { 0 };
Packit db064d
	int selfport = 0;
Packit db064d
	int changed = 0;
Packit db064d
	int i;
Packit db064d
	uint32_t vendorid, rem_vendorid;
Packit db064d
	uint16_t devid, rem_devid;
Packit db064d
	uint64_t val;
Packit db064d
	char *endp;
Packit db064d
	char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
Packit db064d
	    "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n"
Packit db064d
	    "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n"
Packit db064d
	    "\tmkey, mkeylease, mkeyprot\n";
Packit db064d
	const char *usage_examples[] = {
Packit db064d
		"3 1 disable\t\t\t# by lid",
Packit db064d
		"-G 0x2C9000100D051 1 enable\t# by guid",
Packit db064d
		"-D 0 1\t\t\t# (query) by direct route",
Packit db064d
		"3 1 reset\t\t\t# by lid",
Packit db064d
		"3 1 speed 1\t\t\t# by lid",
Packit db064d
		"3 1 width 1\t\t\t# by lid",
Packit db064d
		"-D 0 1 lid 0x1234 arm\t\t# by direct route",
Packit db064d
		NULL
Packit db064d
	};
Packit db064d
Packit db064d
	ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL,
Packit db064d
			    usage_args, usage_examples);
Packit db064d
Packit db064d
	argc -= optind;
Packit db064d
	argv += optind;
Packit db064d
Packit db064d
	if (argc < 2)
Packit db064d
		ibdiag_show_usage();
Packit db064d
Packit db064d
	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
Packit db064d
	if (!srcport)
Packit db064d
		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
Packit db064d
Packit db064d
	smp_mkey_set(srcport, ibd_mkey);
Packit db064d
Packit db064d
	if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
Packit db064d
			       ibd_dest_type, ibd_sm_id, srcport) < 0)
Packit db064d
		IBEXIT("can't resolve destination port %s", argv[0]);
Packit db064d
Packit db064d
	if (argc > 1)
Packit db064d
		portnum = strtol(argv[1], NULL, 0);
Packit db064d
Packit db064d
	for (i = 2; i < argc; i++) {
Packit db064d
		int j;
Packit db064d
Packit db064d
		for (j = 0; j < NPORT_ARGS; j++) {
Packit db064d
			if (strcmp(argv[i], port_args[j].name))
Packit db064d
				continue;
Packit db064d
			port_args[j].set = 1;
Packit db064d
			if (!port_args[j].val) {
Packit db064d
				if (port_op >= 0)
Packit db064d
					IBEXIT("%s only one of: "
Packit db064d
						"query, enable, disable, "
Packit db064d
						"reset, down, arm, active, "
Packit db064d
						"can be specified",
Packit db064d
						port_args[j].name);
Packit db064d
				port_op = j;
Packit db064d
				break;
Packit db064d
			}
Packit db064d
			if (++i >= argc)
Packit db064d
				IBEXIT("%s requires an additional parameter",
Packit db064d
					port_args[j].name);
Packit db064d
			val = strtoull(argv[i], NULL, 0);
Packit db064d
			switch (j) {
Packit db064d
			case SPEED:
Packit db064d
				if (val > 15)
Packit db064d
					IBEXIT("invalid speed value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case ESPEED:
Packit db064d
				if (val > 31)
Packit db064d
					IBEXIT("invalid extended speed value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case FDR10SPEED:
Packit db064d
				if (val > 1)
Packit db064d
					IBEXIT("invalid fdr10 speed value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case WIDTH:
Packit db064d
				if ((val > 31 && val != 255))
Packit db064d
					IBEXIT("invalid width value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case VLS:
Packit db064d
				if (val == 0 || val > 5)
Packit db064d
					IBEXIT("invalid vls value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case MTU:
Packit db064d
				if (val == 0 || val > 5)
Packit db064d
					IBEXIT("invalid mtu value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case LID:
Packit db064d
				if (val == 0 || val >= 0xC000)
Packit db064d
					IBEXIT("invalid lid value 0x%" PRIx64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case SMLID:
Packit db064d
				if (val == 0 || val >= 0xC000)
Packit db064d
					IBEXIT("invalid smlid value 0x%" PRIx64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case LMC:
Packit db064d
				if (val > 7)
Packit db064d
					IBEXIT("invalid lmc value %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case MKEY:
Packit db064d
				errno = 0;
Packit db064d
				val = strtoull(argv[i], &endp, 0);
Packit db064d
				if (errno || *endp != '\0') {
Packit db064d
					errno = 0;
Packit db064d
					val = strtoull(getpass("New M_Key: "),
Packit db064d
						       &endp, 0);
Packit db064d
					if (errno || *endp != '\0') {
Packit db064d
						IBEXIT("Bad new M_Key\n");
Packit db064d
					}
Packit db064d
				}
Packit db064d
				/* All 64-bit values are legal */
Packit db064d
				break;
Packit db064d
			case MKEYLEASE:
Packit db064d
				if (val > 0xFFFF)
Packit db064d
					IBEXIT("invalid mkey lease time %" PRIu64,
Packit db064d
					       val);
Packit db064d
				break;
Packit db064d
			case MKEYPROT:
Packit db064d
				if (val > 3)
Packit db064d
					IBEXIT("invalid mkey protection bit setting %" PRIu64,
Packit db064d
					       val);
Packit db064d
			}
Packit db064d
			*port_args[j].val = val;
Packit db064d
			changed = 1;
Packit db064d
			break;
Packit db064d
		}
Packit db064d
		if (j == NPORT_ARGS)
Packit db064d
			IBEXIT("invalid operation: %s", argv[i]);
Packit db064d
	}
Packit db064d
	if (port_op < 0)
Packit db064d
		port_op = QUERY;
Packit db064d
Packit db064d
	is_switch = get_node_info(&portid, data);
Packit db064d
	vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
Packit db064d
	devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
Packit db064d
Packit db064d
	if ((port_args[MKEY].set || port_args[MKEYLEASE].set ||
Packit db064d
	     port_args[MKEYPROT].set) && is_switch && portnum != 0)
Packit db064d
		IBEXIT("Can't set M_Key fields on switch port != 0");
Packit db064d
Packit db064d
	if (port_op != QUERY || changed)
Packit db064d
		printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
Packit db064d
	else
Packit db064d
		printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
Packit db064d
	espeed_cap = get_port_info(&portid, data, portnum, is_switch);
Packit db064d
	show_port_info(&portid, data, portnum, espeed_cap, is_switch);
Packit db064d
	if (is_mlnx_ext_port_info_supported(vendorid, devid)) {
Packit db064d
		get_mlnx_ext_port_info(&portid, data2, portnum);
Packit db064d
		show_mlnx_ext_port_info(&portid, data2, portnum);
Packit db064d
	}
Packit db064d
Packit db064d
	if (port_op != QUERY || changed) {
Packit db064d
		/*
Packit db064d
		 * If we aren't setting the LID and the LID is the default,
Packit db064d
		 * the SMA command will fail due to an invalid LID.
Packit db064d
		 * Set it to something unlikely but valid.
Packit db064d
		 */
Packit db064d
		physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F);
Packit db064d
Packit db064d
		val = mad_get_field(data, 0, IB_PORT_LID_F);
Packit db064d
		if (!port_args[LID].set && (!val || val == 0xFFFF))
Packit db064d
			mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
Packit db064d
		val = mad_get_field(data, 0, IB_PORT_SMLID_F);
Packit db064d
		if (!port_args[SMLID].set && (!val || val == 0xFFFF))
Packit db064d
			mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
Packit db064d
		mad_set_field(data, 0, IB_PORT_STATE_F, 0);	/* NOP */
Packit db064d
		mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);	/* NOP */
Packit db064d
Packit db064d
		switch (port_op) {
Packit db064d
		case ON:
Packit db064d
			/* Enable only if state is Disable */
Packit db064d
			if(physstate != 3) {
Packit db064d
				printf("Port is already in enable state\n");
Packit db064d
				goto close_port;
Packit db064d
			}
Packit db064d
		case ENABLE:
Packit db064d
		case RESET:
Packit db064d
			/* Polling */
Packit db064d
			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
Packit db064d
			break;
Packit db064d
		case OFF:
Packit db064d
		case DISABLE:
Packit db064d
			printf("Disable may be irreversible\n");
Packit db064d
			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
Packit db064d
			break;
Packit db064d
		case DOWN:
Packit db064d
			mad_set_field(data, 0, IB_PORT_STATE_F, 1);
Packit db064d
			break;
Packit db064d
		case ARM:
Packit db064d
			mad_set_field(data, 0, IB_PORT_STATE_F, 3);
Packit db064d
			break;
Packit db064d
		case ACTIVE:
Packit db064d
			mad_set_field(data, 0, IB_PORT_STATE_F, 4);
Packit db064d
			break;
Packit db064d
		}
Packit db064d
Packit db064d
		/* always set enabled speeds/width - defaults to NOP */
Packit db064d
		mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
Packit db064d
		mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
Packit db064d
		mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);
Packit db064d
Packit db064d
		if (port_args[VLS].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
Packit db064d
		if (port_args[MTU].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
Packit db064d
		if (port_args[LID].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_LID_F, lid);
Packit db064d
		if (port_args[SMLID].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
Packit db064d
		if (port_args[LMC].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
Packit db064d
Packit db064d
		if (port_args[FDR10SPEED].set) {
Packit db064d
			mad_set_field(data2, 0,
Packit db064d
				      IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
Packit db064d
				      FDR10);
Packit db064d
			mad_set_field(data2, 0,
Packit db064d
				      IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
Packit db064d
				      fdr10);
Packit db064d
			set_mlnx_ext_port_info(&portid, data2, portnum);
Packit db064d
		}
Packit db064d
Packit db064d
		if (port_args[MKEY].set)
Packit db064d
			mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey);
Packit db064d
		if (port_args[MKEYLEASE].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F,
Packit db064d
				      mkeylease);
Packit db064d
		if (port_args[MKEYPROT].set)
Packit db064d
			mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F,
Packit db064d
				      mkeyprot);
Packit db064d
Packit db064d
		set_port_info(&portid, data, portnum, espeed_cap, is_switch);
Packit db064d
Packit db064d
	} else if (is_switch && portnum) {
Packit db064d
		/* Now, make sure PortState is Active */
Packit db064d
		/* Or is PortPhysicalState LinkUp sufficient ? */
Packit db064d
		mad_decode_field(data, IB_PORT_STATE_F, &state);
Packit db064d
		mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
Packit db064d
		if (state == 4) {	/* Active */
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
Packit db064d
					 &lwe);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
Packit db064d
					 &lws);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
Packit db064d
					 &lwa);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
Packit db064d
					 &lss;;
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
Packit db064d
					 &lsa);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
Packit db064d
					 &lse;;
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
Packit db064d
					 &fdr10s);
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
Packit db064d
					 &fdr10e);
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
Packit db064d
					 &fdr10a);
Packit db064d
			if (espeed_cap) {
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
Packit db064d
						 &lses);
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
Packit db064d
						 &lsea);
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
Packit db064d
						 &lsee);
Packit db064d
			}
Packit db064d
Packit db064d
			/* Setup portid for peer port */
Packit db064d
			memcpy(&peerportid, &portid, sizeof(peerportid));
Packit db064d
			if (portid.lid == 0) {
Packit db064d
				peerportid.drpath.cnt++;
Packit db064d
				if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) {
Packit db064d
					IBEXIT("Too many hops");
Packit db064d
				}
Packit db064d
			} else {
Packit db064d
				peerportid.drpath.cnt = 1;
Packit db064d
Packit db064d
				/* Set DrSLID to local lid */
Packit db064d
				if (resolve_self(ibd_ca, ibd_ca_port, &selfportid,
Packit db064d
						         &selfport, NULL) < 0)
Packit db064d
					IBEXIT("could not resolve self");
Packit db064d
				peerportid.drpath.drslid = (uint16_t) selfportid.lid;
Packit db064d
				peerportid.drpath.drdlid = 0xffff;
Packit db064d
			}
Packit db064d
			peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum;
Packit db064d
Packit db064d
			/* Get peer port NodeInfo to obtain peer port number */
Packit db064d
			is_peer_switch = get_node_info(&peerportid, data);
Packit db064d
			rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
Packit db064d
			rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
Packit db064d
Packit db064d
			mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
Packit db064d
					 &peerlocalportnum);
Packit db064d
Packit db064d
			printf("Peer PortInfo:\n");
Packit db064d
			/* Get peer port characteristics */
Packit db064d
			peer_espeed_cap = get_port_info(&peerportid, data,
Packit db064d
							peerlocalportnum,
Packit db064d
							is_peer_switch);
Packit db064d
			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
Packit db064d
				get_mlnx_ext_port_info(&peerportid, data2,
Packit db064d
						       peerlocalportnum);
Packit db064d
			show_port_info(&peerportid, data, peerlocalportnum,
Packit db064d
				       peer_espeed_cap, is_peer_switch);
Packit db064d
			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
Packit db064d
				show_mlnx_ext_port_info(&peerportid, data2,
Packit db064d
							peerlocalportnum);
Packit db064d
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
Packit db064d
					 &peerlwe);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
Packit db064d
					 &peerlws);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
Packit db064d
					 &peerlwa);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
Packit db064d
					 &peerlss);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
Packit db064d
					 &peerlsa);
Packit db064d
			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
Packit db064d
					 &peerlse);
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
Packit db064d
					 &peerfdr10s);
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
Packit db064d
					 &peerfdr10e);
Packit db064d
			mad_decode_field(data2,
Packit db064d
					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
Packit db064d
					 &peerfdr10a);
Packit db064d
			if (peer_espeed_cap) {
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
Packit db064d
						 &peerlses);
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
Packit db064d
						 &peerlsea);
Packit db064d
				mad_decode_field(data,
Packit db064d
						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
Packit db064d
						 &peerlsee);
Packit db064d
			}
Packit db064d
Packit db064d
			/* Now validate peer port characteristics */
Packit db064d
			/* Examine Link Width */
Packit db064d
			width = get_link_width(lwe, lws);
Packit db064d
			peerwidth = get_link_width(peerlwe, peerlws);
Packit db064d
			validate_width(peerwidth, lwa);
Packit db064d
Packit db064d
			/* Examine Link Speeds */
Packit db064d
			speed = get_link_speed(lse, lss);
Packit db064d
			peerspeed = get_link_speed(peerlse, peerlss);
Packit db064d
			validate_speed(peerspeed, lsa);
Packit db064d
Packit db064d
			if (espeed_cap && peer_espeed_cap) {
Packit db064d
				espeed = get_link_speed_ext(lsee, lses);
Packit db064d
				peerespeed = get_link_speed_ext(peerlsee,
Packit db064d
								peerlses);
Packit db064d
				validate_extended_speed(peerespeed, lsea);
Packit db064d
			} else {
Packit db064d
				if (fdr10e & FDR10 && peerfdr10e & FDR10) {
Packit db064d
					if (!(fdr10a & FDR10))
Packit db064d
						IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa);
Packit db064d
				}
Packit db064d
			}
Packit db064d
		}
Packit db064d
	}
Packit db064d
Packit db064d
close_port:
Packit db064d
	mad_rpc_close_port(srcport);
Packit db064d
	exit(0);
Packit db064d
}