ibportstate.c revision 329564
1/*
2 * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
3 * Copyright (c) 2010,2011 Mellanox Technologies LTD.  All rights reserved.
4 * Copyright (c) 2011,2016 Oracle and/or its affiliates. All rights reserved.
5 *
6 * This software is available to you under a choice of one of two
7 * licenses.  You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
11 *
12 *     Redistribution and use in source and binary forms, with or
13 *     without modification, are permitted provided that the following
14 *     conditions are met:
15 *
16 *      - Redistributions of source code must retain the above
17 *        copyright notice, this list of conditions and the following
18 *        disclaimer.
19 *
20 *      - Redistributions in binary form must reproduce the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer in the documentation and/or other materials
23 *        provided with the distribution.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32 * SOFTWARE.
33 *
34 */
35
36#if HAVE_CONFIG_H
37#  include <config.h>
38#endif				/* HAVE_CONFIG_H */
39
40#include <stdio.h>
41#include <stdlib.h>
42#include <unistd.h>
43#include <string.h>
44#include <getopt.h>
45#include <errno.h>
46
47#include <infiniband/umad.h>
48#include <infiniband/mad.h>
49
50#include "ibdiag_common.h"
51
52enum port_ops {
53	QUERY,
54	ENABLE,
55	RESET,
56	DISABLE,
57	SPEED,
58	ESPEED,
59	FDR10SPEED,
60	WIDTH,
61	DOWN,
62	ARM,
63	ACTIVE,
64	VLS,
65	MTU,
66	LID,
67	SMLID,
68	LMC,
69	MKEY,
70	MKEYLEASE,
71	MKEYPROT,
72	ON,
73	OFF
74};
75
76struct ibmad_port *srcport;
77uint64_t speed = 0; /* no state change */
78uint64_t espeed = 0; /* no state change */
79uint64_t fdr10 = 0; /* no state change */
80uint64_t width = 0; /* no state change */
81uint64_t lid;
82uint64_t smlid;
83uint64_t lmc;
84uint64_t mtu;
85uint64_t vls = 0; /* no state change */
86uint64_t mkey;
87uint64_t mkeylease;
88uint64_t mkeyprot;
89
90struct {
91	const char *name;
92	uint64_t *val;
93	int set;
94} port_args[] = {
95	{"query", NULL, 0},	/* QUERY */
96	{"enable", NULL, 0},	/* ENABLE */
97	{"reset", NULL, 0},	/* RESET */
98	{"disable", NULL, 0},	/* DISABLE */
99	{"speed", &speed, 0},	/* SPEED */
100	{"espeed", &espeed, 0},	/* EXTENDED SPEED */
101	{"fdr10", &fdr10, 0},	/* FDR10 SPEED */
102	{"width", &width, 0},	/* WIDTH */
103	{"down", NULL, 0},	/* DOWN */
104	{"arm", NULL, 0},	/* ARM */
105	{"active", NULL, 0},	/* ACTIVE */
106	{"vls", &vls, 0},	/* VLS */
107	{"mtu", &mtu, 0},	/* MTU */
108	{"lid", &lid, 0},	/* LID */
109	{"smlid", &smlid, 0},	/* SMLID */
110	{"lmc", &lmc, 0},	/* LMC */
111	{"mkey", &mkey, 0},	/* MKEY */
112	{"mkeylease", &mkeylease, 0},	/* MKEY LEASE */
113	{"mkeyprot", &mkeyprot, 0},	/* MKEY PROTECT BITS */
114	{"on", NULL, 0},	/* ON */
115	{"off", NULL, 0},	/* OFF */
116};
117
118#define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
119
120/*******************************************/
121
122/*
123 * Return 1 if node is a switch, else zero.
124 */
125static int get_node_info(ib_portid_t * dest, uint8_t * data)
126{
127	int node_type;
128
129	if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
130		IBEXIT("smp query nodeinfo failed");
131
132	node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
133	if (node_type == IB_NODE_SWITCH)	/* Switch NodeType ? */
134		return 1;
135	else
136		return 0;
137}
138
139static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
140			 int is_switch)
141{
142	uint8_t smp[IB_SMP_DATA_SIZE];
143	uint8_t *info;
144	int cap_mask;
145
146	if (is_switch) {
147		if (!smp_query_via(smp, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
148			IBEXIT("smp query port 0 portinfo failed");
149		info = smp;
150	} else
151		info = data;
152
153	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
154		IBEXIT("smp query portinfo failed");
155	cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
156	return (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS));
157}
158
159static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
160			   int espeed_cap, int is_switch)
161{
162	char buf[2300];
163	char val[64];
164
165	mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
166	mad_decode_field(data, IB_PORT_LID_F, val);
167	mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
168		       sizeof buf - strlen(buf), val);
169	sprintf(buf + strlen(buf), "%s", "\n");
170	mad_decode_field(data, IB_PORT_SMLID_F, val);
171	mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
172		       sizeof buf - strlen(buf), val);
173	sprintf(buf + strlen(buf), "%s", "\n");
174	mad_decode_field(data, IB_PORT_LMC_F, val);
175	mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
176		       sizeof buf - strlen(buf), val);
177	sprintf(buf + strlen(buf), "%s", "\n");
178	mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
179	mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
180		       sizeof buf - strlen(buf), val);
181	sprintf(buf + strlen(buf), "%s", "\n");
182	mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
183	mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
184		       sizeof buf - strlen(buf), val);
185	sprintf(buf + strlen(buf), "%s", "\n");
186	mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
187	mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
188		       sizeof buf - strlen(buf), val);
189	sprintf(buf + strlen(buf), "%s", "\n");
190	mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
191	mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
192		       sizeof buf - strlen(buf), val);
193	sprintf(buf + strlen(buf), "%s", "\n");
194	mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
195	mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
196		       sizeof buf - strlen(buf), val);
197	sprintf(buf + strlen(buf), "%s", "\n");
198	mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
199	mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
200		       sizeof buf - strlen(buf), val);
201	sprintf(buf + strlen(buf), "%s", "\n");
202	if (espeed_cap) {
203		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val);
204		mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
205			       buf + strlen(buf), sizeof buf - strlen(buf),
206			       val);
207		sprintf(buf + strlen(buf), "%s", "\n");
208		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val);
209		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F,
210			       buf + strlen(buf), sizeof buf - strlen(buf),
211			       val);
212		sprintf(buf + strlen(buf), "%s", "\n");
213		mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val);
214		mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
215			       buf + strlen(buf), sizeof buf - strlen(buf),
216			       val);
217		sprintf(buf + strlen(buf), "%s", "\n");
218	}
219	if (!is_switch || portnum == 0) {
220		if (show_keys) {
221			mad_decode_field(data, IB_PORT_MKEY_F, val);
222			mad_dump_field(IB_PORT_MKEY_F, buf + strlen(buf),
223				       sizeof buf - strlen(buf), val);
224		} else
225			snprint_field(buf+strlen(buf), sizeof(buf)-strlen(buf),
226				      IB_PORT_MKEY_F, 32, NOT_DISPLAYED_STR);
227		sprintf(buf+strlen(buf), "%s", "\n");
228		mad_decode_field(data, IB_PORT_MKEY_LEASE_F, val);
229		mad_dump_field(IB_PORT_MKEY_LEASE_F, buf + strlen(buf),
230			       sizeof buf - strlen(buf), val);
231		sprintf(buf+strlen(buf), "%s", "\n");
232		mad_decode_field(data, IB_PORT_MKEY_PROT_BITS_F, val);
233		mad_dump_field(IB_PORT_MKEY_PROT_BITS_F, buf + strlen(buf),
234			       sizeof buf - strlen(buf), val);
235		sprintf(buf+strlen(buf), "%s", "\n");
236	}
237
238	printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
239}
240
241static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
242			  int espeed_cap, int is_switch)
243{
244	unsigned mod;
245
246	mod = portnum;
247	if (espeed_cap)
248		mod |= 1<<31;
249	if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, mod, 0, srcport))
250		IBEXIT("smp set portinfo failed");
251
252	printf("\nAfter PortInfo set:\n");
253	show_port_info(dest, data, portnum, espeed_cap, is_switch);
254}
255
256static void get_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
257{
258	if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
259			   portnum, 0, srcport))
260		IBEXIT("smp query ext portinfo failed");
261}
262
263static void show_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
264{
265	char buf[256];
266
267	mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, IB_SMP_DATA_SIZE);
268
269	printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest),
270	       portnum, buf);
271}
272
273static void set_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
274{
275	if (!smp_set_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
276			 portnum, 0, srcport))
277		IBEXIT("smp set MLNX ext portinfo failed");
278
279	printf("\nAfter MLNXExtendedPortInfo set:\n");
280	show_mlnx_ext_port_info(dest, data, portnum);
281}
282
283static int get_link_width(int lwe, int lws)
284{
285	if (lwe == 255)
286		return lws;
287	else
288		return lwe;
289}
290
291static int get_link_speed(int lse, int lss)
292{
293	if (lse == 15)
294		return lss;
295	else
296		return lse;
297}
298
299static int get_link_speed_ext(int lsee, int lses)
300{
301	if (lsee == 31)
302		return lses;
303	else
304		return lsee;
305}
306
307static void validate_width(int width, int peerwidth, int lwa)
308{
309	if ((width & peerwidth & 0x8)) {
310		if (lwa != 8)
311			IBWARN
312			    ("Peer ports operating at active width %d rather than 8 (12x)",
313			     lwa);
314	} else if ((width & peerwidth & 0x4)) {
315		if (lwa != 4)
316			IBWARN
317			    ("Peer ports operating at active width %d rather than 4 (8x)",
318			     lwa);
319	} else if ((width & peerwidth & 0x2)) {
320		if (lwa != 2)
321			IBWARN
322			    ("Peer ports operating at active width %d rather than 2 (4x)",
323			     lwa);
324	} else if ((width & peerwidth & 0x10)) {
325		if (lwa != 16)
326			IBWARN
327			    ("Peer ports operating at active width %d rather than 16 (2x)",
328			      lwa);
329	} else if ((width & peerwidth & 0x1)) {
330		if (lwa != 1)
331			IBWARN
332			    ("Peer ports operating at active width %d rather than 1 (1x)",
333			     lwa);
334	}
335}
336
337static void validate_speed(int speed, int peerspeed, int lsa)
338{
339	if ((speed & peerspeed & 0x4)) {
340		if (lsa != 4)
341			IBWARN
342			    ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
343			     lsa);
344	} else if ((speed & peerspeed & 0x2)) {
345		if (lsa != 2)
346			IBWARN
347			    ("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)",
348			     lsa);
349	} else if ((speed & peerspeed & 0x1)) {
350		if (lsa != 1)
351			IBWARN
352			    ("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)",
353			     lsa);
354	}
355}
356
357static void validate_extended_speed(int espeed, int peerespeed, int lsea)
358{
359	if ((espeed & peerespeed & 0x2)) {
360		if (lsea != 2)
361			IBWARN
362			    ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)",
363			     lsea);
364	} else if ((espeed & peerespeed & 0x1)) {
365		if (lsea != 1)
366			IBWARN
367			    ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)",
368			     lsea);
369	}
370}
371
372int main(int argc, char **argv)
373{
374	int mgmt_classes[3] =
375	    { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
376	ib_portid_t portid = { 0 };
377	int port_op = -1;
378	int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
379	int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea,
380	    fdr10s, fdr10e, fdr10a;
381	int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
382	    peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e,
383	    peerfdr10a;
384	int peerwidth, peerspeed, peerespeed;
385	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
386	uint8_t data2[IB_SMP_DATA_SIZE] = { 0 };
387	ib_portid_t peerportid = { 0 };
388	int portnum = 0;
389	ib_portid_t selfportid = { 0 };
390	int selfport = 0;
391	int changed = 0;
392	int i;
393	uint32_t vendorid, rem_vendorid;
394	uint16_t devid, rem_devid;
395	uint64_t val;
396	char *endp;
397	char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
398	    "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n"
399	    "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n"
400	    "\tmkey, mkeylease, mkeyprot\n";
401	const char *usage_examples[] = {
402		"3 1 disable\t\t\t# by lid",
403		"-G 0x2C9000100D051 1 enable\t# by guid",
404		"-D 0 1\t\t\t# (query) by direct route",
405		"3 1 reset\t\t\t# by lid",
406		"3 1 speed 1\t\t\t# by lid",
407		"3 1 width 1\t\t\t# by lid",
408		"-D 0 1 lid 0x1234 arm\t\t# by direct route",
409		NULL
410	};
411
412	ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL,
413			    usage_args, usage_examples);
414
415	argc -= optind;
416	argv += optind;
417
418	if (argc < 2)
419		ibdiag_show_usage();
420
421	srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
422	if (!srcport)
423		IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
424
425	smp_mkey_set(srcport, ibd_mkey);
426
427	if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
428			       ibd_dest_type, ibd_sm_id, srcport) < 0)
429		IBEXIT("can't resolve destination port %s", argv[0]);
430
431	if (argc > 1)
432		portnum = strtol(argv[1], 0, 0);
433
434	for (i = 2; i < argc; i++) {
435		int j;
436
437		for (j = 0; j < NPORT_ARGS; j++) {
438			if (strcmp(argv[i], port_args[j].name))
439				continue;
440			port_args[j].set = 1;
441			if (!port_args[j].val) {
442				if (port_op >= 0)
443					IBEXIT("%s only one of: ",
444						"query, enable, disable, "
445						"reset, down, arm, active, "
446						"can be specified",
447						port_args[j].name);
448				port_op = j;
449				break;
450			}
451			if (++i >= argc)
452				IBEXIT("%s requires an additional parameter",
453					port_args[j].name);
454			val = strtoull(argv[i], 0, 0);
455			switch (j) {
456			case SPEED:
457				if (val > 15)
458					IBEXIT("invalid speed value %ld", val);
459				break;
460			case ESPEED:
461				if (val > 31)
462					IBEXIT("invalid extended speed value %ld", val);
463				break;
464			case FDR10SPEED:
465				if (val > 1)
466					IBEXIT("invalid fdr10 speed value %ld", val);
467				break;
468			case WIDTH:
469				if ((val > 31 && val != 255))
470					IBEXIT("invalid width value %ld", val);
471				break;
472			case VLS:
473				if (val == 0 || val > 5)
474					IBEXIT("invalid vls value %ld", val);
475				break;
476			case MTU:
477				if (val == 0 || val > 5)
478					IBEXIT("invalid mtu value %ld", val);
479				break;
480			case LID:
481				if (val == 0 || val >= 0xC000)
482					IBEXIT("invalid lid value 0x%lx", val);
483				break;
484			case SMLID:
485				if (val == 0 || val >= 0xC000)
486					IBEXIT("invalid smlid value 0x%lx",
487						val);
488				break;
489			case LMC:
490				if (val > 7)
491					IBEXIT("invalid lmc value %ld", val);
492				break;
493			case MKEY:
494				errno = 0;
495				val = strtoull(argv[i], &endp, 0);
496				if (errno || *endp != '\0') {
497					errno = 0;
498					val = strtoull(getpass("New M_Key: "),
499						       &endp, 0);
500					if (errno || *endp != '\0') {
501						IBEXIT("Bad new M_Key\n");
502					}
503				}
504				/* All 64-bit values are legal */
505				break;
506			case MKEYLEASE:
507				if (val > 0xFFFF)
508					IBEXIT("invalid mkey lease time %ld", val);
509				break;
510			case MKEYPROT:
511				if (val > 3)
512					IBEXIT("invalid mkey protection bit setting %ld", val);
513			}
514			*port_args[j].val = val;
515			changed = 1;
516			break;
517		}
518		if (j == NPORT_ARGS)
519			IBEXIT("invalid operation: %s", argv[i]);
520	}
521	if (port_op < 0)
522		port_op = QUERY;
523
524	is_switch = get_node_info(&portid, data);
525	vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
526	devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
527
528	if ((port_args[MKEY].set || port_args[MKEYLEASE].set ||
529	     port_args[MKEYPROT].set) && is_switch && portnum != 0)
530		IBEXIT("Can't set M_Key fields on switch port != 0");
531
532	if (port_op != QUERY || changed)
533		printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
534	else
535		printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
536	espeed_cap = get_port_info(&portid, data, portnum, is_switch);
537	show_port_info(&portid, data, portnum, espeed_cap, is_switch);
538	if (is_mlnx_ext_port_info_supported(vendorid, devid)) {
539		get_mlnx_ext_port_info(&portid, data2, portnum);
540		show_mlnx_ext_port_info(&portid, data2, portnum);
541	}
542
543	if (port_op != QUERY || changed) {
544		/*
545		 * If we aren't setting the LID and the LID is the default,
546		 * the SMA command will fail due to an invalid LID.
547		 * Set it to something unlikely but valid.
548		 */
549		physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F);
550
551		val = mad_get_field(data, 0, IB_PORT_LID_F);
552		if (!port_args[LID].set && (!val || val == 0xFFFF))
553			mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
554		val = mad_get_field(data, 0, IB_PORT_SMLID_F);
555		if (!port_args[SMLID].set && (!val || val == 0xFFFF))
556			mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
557		mad_set_field(data, 0, IB_PORT_STATE_F, 0);	/* NOP */
558		mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);	/* NOP */
559
560		switch (port_op) {
561		case ON:
562			/* Enable only if state is Disable */
563			if(physstate != 3) {
564				printf("Port is already in enable state\n");
565				goto close_port;
566			}
567		case ENABLE:
568		case RESET:
569			/* Polling */
570			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
571			break;
572		case OFF:
573		case DISABLE:
574			printf("Disable may be irreversible\n");
575			mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
576			break;
577		case DOWN:
578			mad_set_field(data, 0, IB_PORT_STATE_F, 1);
579			break;
580		case ARM:
581			mad_set_field(data, 0, IB_PORT_STATE_F, 3);
582			break;
583		case ACTIVE:
584			mad_set_field(data, 0, IB_PORT_STATE_F, 4);
585			break;
586		}
587
588		/* always set enabled speeds/width - defaults to NOP */
589		mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
590		mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
591		mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);
592
593		if (port_args[VLS].set)
594			mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
595		if (port_args[MTU].set)
596			mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
597		if (port_args[LID].set)
598			mad_set_field(data, 0, IB_PORT_LID_F, lid);
599		if (port_args[SMLID].set)
600			mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
601		if (port_args[LMC].set)
602			mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
603
604		if (port_args[FDR10SPEED].set) {
605			mad_set_field(data2, 0,
606				      IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
607				      FDR10);
608			mad_set_field(data2, 0,
609				      IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
610				      fdr10);
611			set_mlnx_ext_port_info(&portid, data2, portnum);
612		}
613
614		if (port_args[MKEY].set)
615			mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey);
616		if (port_args[MKEYLEASE].set)
617			mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F,
618				      mkeylease);
619		if (port_args[MKEYPROT].set)
620			mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F,
621				      mkeyprot);
622
623		set_port_info(&portid, data, portnum, espeed_cap, is_switch);
624
625	} else if (is_switch && portnum) {
626		/* Now, make sure PortState is Active */
627		/* Or is PortPhysicalState LinkUp sufficient ? */
628		mad_decode_field(data, IB_PORT_STATE_F, &state);
629		mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
630		if (state == 4) {	/* Active */
631			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
632					 &lwe);
633			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
634					 &lws);
635			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
636					 &lwa);
637			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
638					 &lss);
639			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
640					 &lsa);
641			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
642					 &lse);
643			mad_decode_field(data2,
644					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
645					 &fdr10s);
646			mad_decode_field(data2,
647					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
648					 &fdr10e);
649			mad_decode_field(data2,
650					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
651					 &fdr10a);
652			if (espeed_cap) {
653				mad_decode_field(data,
654						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
655						 &lses);
656				mad_decode_field(data,
657						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
658						 &lsea);
659				mad_decode_field(data,
660						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
661						 &lsee);
662			}
663
664			/* Setup portid for peer port */
665			memcpy(&peerportid, &portid, sizeof(peerportid));
666			if (portid.lid == 0) {
667				peerportid.drpath.cnt++;
668				if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) {
669					IBEXIT("Too many hops");
670				}
671			} else {
672				peerportid.drpath.cnt = 1;
673
674				/* Set DrSLID to local lid */
675				if (resolve_self(ibd_ca, ibd_ca_port, &selfportid,
676						         &selfport, 0) < 0)
677					IBEXIT("could not resolve self");
678				peerportid.drpath.drslid = (uint16_t) selfportid.lid;
679				peerportid.drpath.drdlid = 0xffff;
680			}
681			peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum;
682
683			/* Get peer port NodeInfo to obtain peer port number */
684			is_peer_switch = get_node_info(&peerportid, data);
685			rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
686			rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
687
688			mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
689					 &peerlocalportnum);
690
691			printf("Peer PortInfo:\n");
692			/* Get peer port characteristics */
693			peer_espeed_cap = get_port_info(&peerportid, data,
694							peerlocalportnum,
695							is_peer_switch);
696			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
697				get_mlnx_ext_port_info(&peerportid, data2,
698						       peerlocalportnum);
699			show_port_info(&peerportid, data, peerlocalportnum,
700				       peer_espeed_cap, is_peer_switch);
701			if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
702				show_mlnx_ext_port_info(&peerportid, data2,
703							peerlocalportnum);
704
705			mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
706					 &peerlwe);
707			mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
708					 &peerlws);
709			mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
710					 &peerlwa);
711			mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
712					 &peerlss);
713			mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
714					 &peerlsa);
715			mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
716					 &peerlse);
717			mad_decode_field(data2,
718					 IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
719					 &peerfdr10s);
720			mad_decode_field(data2,
721					 IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
722					 &peerfdr10e);
723			mad_decode_field(data2,
724					 IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
725					 &peerfdr10a);
726			if (peer_espeed_cap) {
727				mad_decode_field(data,
728						 IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
729						 &peerlses);
730				mad_decode_field(data,
731						 IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
732						 &peerlsea);
733				mad_decode_field(data,
734						 IB_PORT_LINK_SPEED_EXT_ENABLED_F,
735						 &peerlsee);
736			}
737
738			/* Now validate peer port characteristics */
739			/* Examine Link Width */
740			width = get_link_width(lwe, lws);
741			peerwidth = get_link_width(peerlwe, peerlws);
742			validate_width(width, peerwidth, lwa);
743
744			/* Examine Link Speeds */
745			speed = get_link_speed(lse, lss);
746			peerspeed = get_link_speed(peerlse, peerlss);
747			validate_speed(speed, peerspeed, lsa);
748
749			if (espeed_cap && peer_espeed_cap) {
750				espeed = get_link_speed_ext(lsee, lses);
751				peerespeed = get_link_speed_ext(peerlsee,
752								peerlses);
753				validate_extended_speed(espeed, peerespeed,
754							lsea);
755			} else {
756				if (fdr10e & FDR10 && peerfdr10e & FDR10) {
757					if (!(fdr10a & FDR10))
758						IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa);
759				}
760			}
761		}
762	}
763
764close_port:
765	mad_rpc_close_port(srcport);
766	exit(0);
767}
768