示例#1
0
static void fillMAD_Delete_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId, UInt8 *mgid, UInt8 *portGid)
{
	UInt64 mask = 0;
	struct _MCMemberRecord mr;

	memset(umad, 0, len);
	umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY);
	/* Ignore GRH */

	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_DELETE);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1);
	mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD);

	memset(&mr, 0, sizeof(mr));

	memcpy(mr.mgid, mgid, 16);
	mask |= (1 << 0);

	memcpy(mr.portGid, portGid, 16);
	mask |= (1 << 1);

	mr.scope_joinState = 0x1;
	/* Scope remains unset */
	mask |= (1 << 16);

	mask |= (1 << 17);

	memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &mr, sizeof(mr));

	mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask);
}
示例#2
0
static void fillMAD_Get_LFTRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt16 destLid, UInt64 trId)
{
	UInt64 mask;
	struct _LinearForwardingTableRecord lft;

	memset(umad, 0, len);
	umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY);
	/* Ignore GRH */

	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET_TABLE);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1);
	mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_LFTRECORD);

	if (destLid > 0) {
		memset(&lft, 0, sizeof(lft));
		lft.lid = hton16(destLid);

		mask = 0x1;	/* lid */
		memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &lft, sizeof(lft));
	}
	mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask);
}
int resolve_guid(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
		 uint64_t *guid, ib_portid_t *sm_id,
		 const struct ibmad_port *srcport)
{
	ib_portid_t sm_portid;
	uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
	uint64_t prefix;
	ibmad_gid_t selfgid;

	if (!sm_id) {
		sm_id = &sm_portid;
		if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
			return -1;
	}

	if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0)
		return -1;

	memcpy(&prefix, portid->gid, sizeof(prefix));
	if (!prefix)
		mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
				IB_DEFAULT_SUBN_PREFIX);
	if (guid)
		mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);

	if ((portid->lid =
	     ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0)
		return -1;

	mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl);
	return 0;
}
示例#4
0
static void fillMAD_Set_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId, UInt8 *mgid, UInt8 *portGid)
{
	UInt64 mask = 0;
	struct _MCMemberRecord mr;

	memset(umad, 0, len);
	umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY);
	/* Ignore GRH */

	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_SET);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1);
	mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD);

	memset(&mr, 0, sizeof(mr));

	memcpy(mr.mgid, mgid, 16);
	mask |= (1 << 0);

	memcpy(mr.portGid, portGid, 16);
	mask |= (1 << 1);

	mr.qkey = hton32(0x1);
	mask |= (1 << 2);

	mr.pkey = hton16(0xffff);
	mask |= (1 << 7);

	/* SL */
	mask |= (1 << 12);

	/* FlowLabel */
	mask |= (1 << 13);
	/* Traffic class */
	mask |= (1 << 6);

	mr.scope_joinState = (0x5 << 4) | 0x1;
	mask |= (1 << 15);
	mask |= (1 << 16);

	memcpy((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, &mr, sizeof(mr));

	mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, mask);
}
static char *congestion_key_info(ib_portid_t * dest, char **argv, int argc)
{
	uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
	uint8_t payload[IB_CC_DATA_SZ] = { 0 };
	uint64_t cc_key;
	uint32_t cc_keyprotectbit;
	uint32_t cc_keyleaseperiod;
	uint32_t cc_keyviolations;
	char *errstr;

	if (argc != 4)
		return "invalid number of parameters for CongestionKeyInfo";

	if ((errstr = parselonglongint(argv[0], &cc_key)))
		return errstr;
	if ((errstr = parseint(argv[1], &cc_keyprotectbit, 0)))
		return errstr;
	if ((errstr = parseint(argv[2], &cc_keyleaseperiod, 0)))
		return errstr;
	if ((errstr = parseint(argv[3], &cc_keyviolations, 0)))
		return errstr;

	if (cc_keyprotectbit != 0 && cc_keyprotectbit != 1)
		return "invalid cc_keyprotectbit value";

	if (cc_keyleaseperiod > USHRT_MAX)
		return "invalid cc_keyleaseperiod value";

	if (cc_keyviolations > USHRT_MAX)
		return "invalid cc_keyviolations value";

	mad_set_field64(payload,
			0,
			IB_CC_CONGESTION_KEY_INFO_CC_KEY_F,
			cc_key);

	mad_encode_field(payload,
			 IB_CC_CONGESTION_KEY_INFO_CC_KEY_PROTECT_BIT_F,
			 &cc_keyprotectbit);

	mad_encode_field(payload,
			 IB_CC_CONGESTION_KEY_INFO_CC_KEY_LEASE_PERIOD_F,
			 &cc_keyleaseperiod);

	/* spec says "setting the counter to a value other than zero results
	 * in the counter being left unchanged.  So if user wants no change,
	 * they gotta input non-zero
	 */
        mad_encode_field(payload,
			 IB_CC_CONGESTION_KEY_INFO_CC_KEY_VIOLATIONS_F,
			 &cc_keyviolations);
	
	if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_CONGESTION_KEY_INFO,
				  0, 0, NULL, srcport, cckey))
		return "congestion key info config failed";

	return NULL;
}
示例#6
0
int
ib_resolve_guid_via(ib_portid_t *portid, uint64_t *guid, ib_portid_t *sm_id, int timeout, const void *srcport)
{
	ib_portid_t sm_portid;
	char buf[IB_SA_DATA_SIZE] = {0};

	if (!sm_id) {
		sm_id = &sm_portid;
		if (ib_resolve_smlid_via(sm_id, timeout, srcport) < 0)
			return -1;
	}
	if (*(uint64_t*)&portid->gid == 0)
		mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F, IB_DEFAULT_SUBN_PREFIX);
	if (guid)
		mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);

	if ((portid->lid = ib_path_query_via(srcport, portid->gid, portid->gid, sm_id, buf)) < 0)
		return -1;

	return 0;
}
示例#7
0
static void fillMAD_Get_MCMemberRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId)
{
	memset(umad, 0, len);
	umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY);
	/* Ignore GRH */

	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET_TABLE);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1);
	mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_MCRECORD);
}
示例#8
0
static void fillMAD_Get_PathRecord(UInt8 *umad, SInt64 len, UInt16 smLid, UInt64 guid, UInt64 trId)
{
	UInt8 dgid[16];

	memset(umad, 0, len);
	umad_set_addr(umad, smLid, MAD_QP1, MAD_DEFAULT_SL, IB_DEFAULT_QP1_QKEY);
	/* Ignore GRH */

	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_METHOD_F, IB_MAD_METHOD_GET);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_CLASSVER_F, MAD_HEADER_CLASS_VERSION_SA);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_MGMTCLASS_F, IB_SA_CLASS);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_BASEVER_F, 1);
	mad_set_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F, trId);
	mad_set_field  (umad_get_mad(umad), 0, IB_MAD_ATTRID_F, IB_SA_ATTR_PATHRECORD);
	mad_set_field64(umad_get_mad(umad), 0, IB_SA_COMPMASK_F, 0x4);

	mad_set_field64(dgid, 0, IB_GID_PREFIX_F, IB_DEFAULT_SUBN_PREFIX);
	mad_set_field64(dgid, 0, IB_GID_GUID_F  , guid);

	/* 128 bit data
	 */
	mad_encode_field((UInt8 *)umad_get_mad(umad) + IB_SA_DATA_OFFS, IB_SA_PR_DGID_F, dgid);
}
示例#9
0
static void replace_sysimgguid(ibnd_node_t *node, void *user_data)
{
	struct guids *guids;
	uint64_t sysimgguid;

	guids = (struct guids *)user_data;

	sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
	if (sysimgguid == guids->before) {
		mad_set_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F,
				guids->after);
		guids->found++;
	}
}
示例#10
0
int ib_resolve_guid_via(ib_portid_t * portid, uint64_t * guid,
			ib_portid_t * sm_id, int timeout,
			const struct ibmad_port *srcport)
{
	ib_portid_t sm_portid;
	uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
	ib_portid_t self = { 0 };
	uint64_t selfguid, prefix;
	ibmad_gid_t selfgid;
	uint8_t nodeinfo[64];

	if (!sm_id) {
		sm_id = &sm_portid;
		if (ib_resolve_smlid_via(sm_id, timeout, srcport) < 0)
			return -1;
	}

	if (!smp_query_via(nodeinfo, &self, IB_ATTR_NODE_INFO, 0, 0, srcport))
		return -1;
	mad_decode_field(nodeinfo, IB_NODE_PORT_GUID_F, &selfguid);
	mad_set_field64(selfgid, 0, IB_GID_PREFIX_F, IB_DEFAULT_SUBN_PREFIX);
	mad_set_field64(selfgid, 0, IB_GID_GUID_F, selfguid);

	memcpy(&prefix, portid->gid, sizeof(prefix));
	if (!prefix)
		mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
				IB_DEFAULT_SUBN_PREFIX);
	if (guid)
		mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);

	if ((portid->lid =
	     ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0)
		return -1;

	mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl);
	return 0;
}
示例#11
0
int main(int argc, char **argv)
{
	int mgmt_classes[3] =
	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
	ib_portid_t portid = { 0 };
	int port_op = -1;
	int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
	int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea,
	    fdr10s, fdr10e, fdr10a;
	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
	    peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e,
	    peerfdr10a;
	int peerwidth, peerspeed, peerespeed;
	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
	uint8_t data2[IB_SMP_DATA_SIZE] = { 0 };
	ib_portid_t peerportid = { 0 };
	int portnum = 0;
	ib_portid_t selfportid = { 0 };
	int selfport = 0;
	int changed = 0;
	int i;
	uint32_t vendorid, rem_vendorid;
	uint16_t devid, rem_devid;
	uint64_t val;
	char *endp;
	char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
	    "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n"
	    "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n"
	    "\tmkey, mkeylease, mkeyprot\n";
	const char *usage_examples[] = {
		"3 1 disable\t\t\t# by lid",
		"-G 0x2C9000100D051 1 enable\t# by guid",
		"-D 0 1\t\t\t# (query) by direct route",
		"3 1 reset\t\t\t# by lid",
		"3 1 speed 1\t\t\t# by lid",
		"3 1 width 1\t\t\t# by lid",
		"-D 0 1 lid 0x1234 arm\t\t# by direct route",
		NULL
	};

	ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL,
			    usage_args, usage_examples);

	argc -= optind;
	argv += optind;

	if (argc < 2)
		ibdiag_show_usage();

	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
	if (!srcport)
		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);

	smp_mkey_set(srcport, ibd_mkey);

	if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
			       ibd_dest_type, ibd_sm_id, srcport) < 0)
		IBEXIT("can't resolve destination port %s", argv[0]);

	if (argc > 1)
		portnum = strtol(argv[1], 0, 0);

	for (i = 2; i < argc; i++) {
		int j;

		for (j = 0; j < NPORT_ARGS; j++) {
			if (strcmp(argv[i], port_args[j].name))
				continue;
			port_args[j].set = 1;
			if (!port_args[j].val) {
				if (port_op >= 0)
					IBEXIT("%s only one of: ",
						"query, enable, disable, "
						"reset, down, arm, active, "
						"can be specified",
						port_args[j].name);
				port_op = j;
				break;
			}
			if (++i >= argc)
				IBEXIT("%s requires an additional parameter",
					port_args[j].name);
			val = strtoull(argv[i], 0, 0);
			switch (j) {
			case SPEED:
				if (val > 15)
					IBEXIT("invalid speed value %ld", val);
				break;
			case ESPEED:
				if (val > 31)
					IBEXIT("invalid extended speed value %ld", val);
				break;
			case FDR10SPEED:
				if (val > 1)
					IBEXIT("invalid fdr10 speed value %ld", val);
				break;
			case WIDTH:
				if ((val > 31 && val != 255))
					IBEXIT("invalid width value %ld", val);
				break;
			case VLS:
				if (val == 0 || val > 5)
					IBEXIT("invalid vls value %ld", val);
				break;
			case MTU:
				if (val == 0 || val > 5)
					IBEXIT("invalid mtu value %ld", val);
				break;
			case LID:
				if (val == 0 || val >= 0xC000)
					IBEXIT("invalid lid value 0x%lx", val);
				break;
			case SMLID:
				if (val == 0 || val >= 0xC000)
					IBEXIT("invalid smlid value 0x%lx",
						val);
				break;
			case LMC:
				if (val > 7)
					IBEXIT("invalid lmc value %ld", val);
				break;
			case MKEY:
				errno = 0;
				val = strtoull(argv[i], &endp, 0);
				if (errno || *endp != '\0') {
					errno = 0;
					val = strtoull(getpass("New M_Key: "),
						       &endp, 0);
					if (errno || *endp != '\0') {
						IBEXIT("Bad new M_Key\n");
					}
				}
				/* All 64-bit values are legal */
				break;
			case MKEYLEASE:
				if (val > 0xFFFF)
					IBEXIT("invalid mkey lease time %ld", val);
				break;
			case MKEYPROT:
				if (val > 3)
					IBEXIT("invalid mkey protection bit setting %ld", val);
			}
			*port_args[j].val = val;
			changed = 1;
			break;
		}
		if (j == NPORT_ARGS)
			IBEXIT("invalid operation: %s", argv[i]);
	}
	if (port_op < 0)
		port_op = QUERY;

	is_switch = get_node_info(&portid, data);
	vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
	devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);

	if ((port_args[MKEY].set || port_args[MKEYLEASE].set ||
	     port_args[MKEYPROT].set) && is_switch && portnum != 0)
		IBEXIT("Can't set M_Key fields on switch port != 0");

	if (port_op != QUERY || changed)
		printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
	else
		printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
	espeed_cap = get_port_info(&portid, data, portnum, is_switch);
	show_port_info(&portid, data, portnum, espeed_cap, is_switch);
	if (is_mlnx_ext_port_info_supported(vendorid, devid)) {
		get_mlnx_ext_port_info(&portid, data2, portnum);
		show_mlnx_ext_port_info(&portid, data2, portnum);
	}

	if (port_op != QUERY || changed) {
		/*
		 * If we aren't setting the LID and the LID is the default,
		 * the SMA command will fail due to an invalid LID.
		 * Set it to something unlikely but valid.
		 */
		physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F);

		val = mad_get_field(data, 0, IB_PORT_LID_F);
		if (!port_args[LID].set && (!val || val == 0xFFFF))
			mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
		val = mad_get_field(data, 0, IB_PORT_SMLID_F);
		if (!port_args[SMLID].set && (!val || val == 0xFFFF))
			mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
		mad_set_field(data, 0, IB_PORT_STATE_F, 0);	/* NOP */
		mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);	/* NOP */

		switch (port_op) {
		case ON:
			/* Enable only if state is Disable */
			if(physstate != 3) {
				printf("Port is already in enable state\n");
				goto close_port;
			}
		case ENABLE:
		case RESET:
			/* Polling */
			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
			break;
		case OFF:
		case DISABLE:
			printf("Disable may be irreversible\n");
			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
			break;
		case DOWN:
			mad_set_field(data, 0, IB_PORT_STATE_F, 1);
			break;
		case ARM:
			mad_set_field(data, 0, IB_PORT_STATE_F, 3);
			break;
		case ACTIVE:
			mad_set_field(data, 0, IB_PORT_STATE_F, 4);
			break;
		}

		/* always set enabled speeds/width - defaults to NOP */
		mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
		mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
		mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);

		if (port_args[VLS].set)
			mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
		if (port_args[MTU].set)
			mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
		if (port_args[LID].set)
			mad_set_field(data, 0, IB_PORT_LID_F, lid);
		if (port_args[SMLID].set)
			mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
		if (port_args[LMC].set)
			mad_set_field(data, 0, IB_PORT_LMC_F, lmc);

		if (port_args[FDR10SPEED].set) {
			mad_set_field(data2, 0,
				      IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
				      FDR10);
			mad_set_field(data2, 0,
				      IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
				      fdr10);
			set_mlnx_ext_port_info(&portid, data2, portnum);
		}

		if (port_args[MKEY].set)
			mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey);
		if (port_args[MKEYLEASE].set)
			mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F,
				      mkeylease);
		if (port_args[MKEYPROT].set)
			mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F,
				      mkeyprot);

		set_port_info(&portid, data, portnum, espeed_cap, is_switch);

	} else if (is_switch && portnum) {
		/* Now, make sure PortState is Active */
		/* Or is PortPhysicalState LinkUp sufficient ? */
		mad_decode_field(data, IB_PORT_STATE_F, &state);
		mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
		if (state == 4) {	/* Active */
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
					 &lwe);
			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
					 &lws);
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
					 &lwa);
			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
					 &lss);
			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
					 &lsa);
			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
					 &lse);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
					 &fdr10s);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
					 &fdr10e);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
					 &fdr10a);
			if (espeed_cap) {
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
						 &lses);
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
						 &lsea);
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
						 &lsee);
			}

			/* Setup portid for peer port */
			memcpy(&peerportid, &portid, sizeof(peerportid));
			if (portid.lid == 0) {
				peerportid.drpath.cnt++;
				if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) {
					IBEXIT("Too many hops");
				}
			} else {
				peerportid.drpath.cnt = 1;

				/* Set DrSLID to local lid */
				if (resolve_self(ibd_ca, ibd_ca_port, &selfportid,
						         &selfport, 0) < 0)
					IBEXIT("could not resolve self");
				peerportid.drpath.drslid = (uint16_t) selfportid.lid;
				peerportid.drpath.drdlid = 0xffff;
			}
			peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum;

			/* Get peer port NodeInfo to obtain peer port number */
			is_peer_switch = get_node_info(&peerportid, data);
			rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
			rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);

			mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
					 &peerlocalportnum);

			printf("Peer PortInfo:\n");
			/* Get peer port characteristics */
			peer_espeed_cap = get_port_info(&peerportid, data,
							peerlocalportnum,
							is_peer_switch);
			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
				get_mlnx_ext_port_info(&peerportid, data2,
						       peerlocalportnum);
			show_port_info(&peerportid, data, peerlocalportnum,
				       peer_espeed_cap, is_peer_switch);
			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
				show_mlnx_ext_port_info(&peerportid, data2,
							peerlocalportnum);

			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
					 &peerlwe);
			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
					 &peerlws);
			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
					 &peerlwa);
			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
					 &peerlss);
			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
					 &peerlsa);
			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
					 &peerlse);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
					 &peerfdr10s);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
					 &peerfdr10e);
			mad_decode_field(data2,
					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
					 &peerfdr10a);
			if (peer_espeed_cap) {
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
						 &peerlses);
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
						 &peerlsea);
				mad_decode_field(data,
						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
						 &peerlsee);
			}

			/* Now validate peer port characteristics */
			/* Examine Link Width */
			width = get_link_width(lwe, lws);
			peerwidth = get_link_width(peerlwe, peerlws);
			validate_width(width, peerwidth, lwa);

			/* Examine Link Speeds */
			speed = get_link_speed(lse, lss);
			peerspeed = get_link_speed(peerlse, peerlss);
			validate_speed(speed, peerspeed, lsa);

			if (espeed_cap && peer_espeed_cap) {
				espeed = get_link_speed_ext(lsee, lses);
				peerespeed = get_link_speed_ext(peerlsee,
								peerlses);
				validate_extended_speed(espeed, peerespeed,
							lsea);
			} else {
				if (fdr10e & FDR10 && peerfdr10e & FDR10) {
					if (!(fdr10a & FDR10))
						IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa);
				}
			}
		}
	}

close_port:
	mad_rpc_close_port(srcport);
	exit(0);
}