1/*
2 * Copyright (c) 2006-2007 The Regents of the University of California.
3 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4 * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
5 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * Copyright (c) 2009 HNR Consulting. All rights reserved.
7 * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
8 *
9 * This software is available to you under a choice of one of two
10 * licenses.  You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
14 *
15 *     Redistribution and use in source and binary forms, with or
16 *     without modification, are permitted provided that the following
17 *     conditions are met:
18 *
19 *      - Redistributions of source code must retain the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer.
22 *
23 *      - Redistributions in binary form must reproduce the above
24 *        copyright notice, this list of conditions and the following
25 *        disclaimer in the documentation and/or other materials
26 *        provided with the distribution.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 * SOFTWARE.
36 *
37 */
38
39/**
40 * Define common functions which can be included in the various C based diags.
41 */
42
43#define _GNU_SOURCE
44#include <stdio.h>
45#include <errno.h>
46#include <string.h>
47#include <stdlib.h>
48#include <stdarg.h>
49#include <sys/types.h>
50#include <unistd.h>
51#include <ctype.h>
52#include <config.h>
53#include <getopt.h>
54#include <limits.h>
55#include <sys/stat.h>
56#include <stdarg.h>
57
58#include <infiniband/umad.h>
59#include <infiniband/mad.h>
60#include <ibdiag_common.h>
61#include <ibdiag_version.h>
62
63int ibverbose;
64enum MAD_DEST ibd_dest_type = IB_DEST_LID;
65ib_portid_t *ibd_sm_id;
66static ib_portid_t sm_portid = { 0 };
67
68/* general config options */
69#define IBDIAG_CONFIG_GENERAL IBDIAG_CONFIG_PATH"/ibdiag.conf"
70char *ibd_ca = NULL;
71int ibd_ca_port = 0;
72int ibd_timeout = 0;
73uint32_t ibd_ibnetdisc_flags = IBND_CONFIG_MLX_EPI;
74uint64_t ibd_mkey;
75uint64_t ibd_sakey = 0;
76int show_keys = 0;
77char *ibd_nd_format = NULL;
78
79static const char *prog_name;
80static const char *prog_args;
81static const char **prog_examples;
82static struct option *long_opts = NULL;
83static const struct ibdiag_opt *opts_map[256];
84
85static const char *get_build_version(void)
86{
87	return "BUILD VERSION: " IBDIAG_VERSION;
88}
89
90static void pretty_print(int start, int width, const char *str)
91{
92	int len = width - start;
93	const char *p, *e;
94
95	while (1) {
96		while (isspace(*str))
97			str++;
98		p = str;
99		do {
100			e = p + 1;
101			p = strchr(e, ' ');
102		} while (p && p - str < len);
103		if (!p) {
104			fprintf(stderr, "%s", str);
105			break;
106		}
107		if (e - str == 1)
108			e = p;
109		fprintf(stderr, "%.*s\n%*s", (int)(e - str), str, start, "");
110		str = e;
111	}
112}
113
114static inline int val_str_true(const char *val_str)
115{
116	return ((strncmp(val_str, "TRUE", strlen("TRUE")) == 0) ||
117		(strncmp(val_str, "true", strlen("true")) == 0));
118}
119
120void read_ibdiag_config(const char *file)
121{
122	char buf[1024];
123	char orig_buf[1024];
124	FILE *config_fd = NULL;
125	char *p_prefix, *p_last;
126	char *name;
127	char *val_str;
128	struct stat statbuf;
129
130	/* silently ignore missing config file */
131	if (stat(file, &statbuf))
132		return;
133
134	config_fd = fopen(file, "r");
135	if (!config_fd)
136		return;
137
138	while (fgets(buf, sizeof buf, config_fd) != NULL) {
139		p_prefix = strtok_r(buf, "\n", &p_last);
140		if (!p_prefix)
141			continue; /* ignore blank lines */
142
143		if (*p_prefix == '#')
144			continue; /* ignore comment lines */
145
146		strlcpy(orig_buf, buf, sizeof(orig_buf));
147		name = strtok_r(p_prefix, "=", &p_last);
148		val_str = strtok_r(NULL, "\n", &p_last);
149		if (!name || !val_str) {
150			fprintf(stderr, "%s: malformed line in \"%s\":\n%s\n",
151			    prog_name, file, orig_buf);
152			continue;
153		}
154
155		if (strncmp(name, "CA", strlen("CA")) == 0) {
156			free(ibd_ca);
157			ibd_ca = strdup(val_str);
158		} else if (strncmp(name, "Port", strlen("Port")) == 0) {
159			ibd_ca_port = strtoul(val_str, NULL, 0);
160		} else if (strncmp(name, "timeout", strlen("timeout")) == 0) {
161			ibd_timeout = strtoul(val_str, NULL, 0);
162		} else if (strncmp(name, "MLX_EPI", strlen("MLX_EPI")) == 0) {
163			if (val_str_true(val_str)) {
164				ibd_ibnetdisc_flags |= IBND_CONFIG_MLX_EPI;
165			} else {
166				ibd_ibnetdisc_flags &= ~IBND_CONFIG_MLX_EPI;
167			}
168		} else if (strncmp(name, "m_key", strlen("m_key")) == 0) {
169			ibd_mkey = strtoull(val_str, 0, 0);
170		} else if (strncmp(name, "sa_key",
171				   strlen("sa_key")) == 0) {
172			ibd_sakey = strtoull(val_str, 0, 0);
173		} else if (strncmp(name, "nd_format",
174				   strlen("nd_format")) == 0) {
175			free(ibd_nd_format);
176			ibd_nd_format = strdup(val_str);
177		}
178	}
179
180	fclose(config_fd);
181}
182
183
184void ibdiag_show_usage()
185{
186	struct option *o = long_opts;
187	int n;
188
189	fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name,
190		prog_args ? prog_args : "");
191
192	if (long_opts[0].name)
193		fprintf(stderr, "Options:\n");
194	for (o = long_opts; o->name; o++) {
195		const struct ibdiag_opt *io = opts_map[o->val];
196		n = fprintf(stderr, "  --%s", io->name);
197		if (isprint(io->letter))
198			n += fprintf(stderr, ", -%c", io->letter);
199		if (io->has_arg)
200			n += fprintf(stderr, " %s",
201				     io->arg_tmpl ? io->arg_tmpl : "<val>");
202		if (io->description && *io->description) {
203			n += fprintf(stderr, "%*s  ", 24 - n > 0 ? 24 - n : 0,
204				     "");
205			pretty_print(n, 74, io->description);
206		}
207		fprintf(stderr, "\n");
208	}
209
210	if (prog_examples) {
211		const char **p;
212		fprintf(stderr, "\nExamples:\n");
213		for (p = prog_examples; *p && **p; p++)
214			fprintf(stderr, "  %s %s\n", prog_name, *p);
215	}
216
217	fprintf(stderr, "\n");
218
219	exit(2);
220}
221
222static int process_opt(int ch, char *optarg)
223{
224	char *endp;
225	long val;
226
227	switch (ch) {
228	case 'z':
229		read_ibdiag_config(optarg);
230		break;
231	case 'h':
232		ibdiag_show_usage();
233		break;
234	case 'V':
235		fprintf(stderr, "%s %s\n", prog_name, get_build_version());
236		exit(0);
237	case 'e':
238		madrpc_show_errors(1);
239		break;
240	case 'v':
241		ibverbose++;
242		break;
243	case 'd':
244		ibdebug++;
245		madrpc_show_errors(1);
246		umad_debug(ibdebug - 1);
247		break;
248	case 'C':
249		ibd_ca = optarg;
250		break;
251	case 'P':
252		ibd_ca_port = strtoul(optarg, 0, 0);
253		if (ibd_ca_port < 0)
254			IBEXIT("cannot resolve CA port %d", ibd_ca_port);
255		break;
256	case 'D':
257		ibd_dest_type = IB_DEST_DRPATH;
258		break;
259	case 'L':
260		ibd_dest_type = IB_DEST_LID;
261		break;
262	case 'G':
263		ibd_dest_type = IB_DEST_GUID;
264		break;
265	case 't':
266		errno = 0;
267		val = strtol(optarg, &endp, 0);
268		if (errno || (endp && *endp != '\0') || val <= 0 ||
269		    val > INT_MAX)
270			IBEXIT("Invalid timeout \"%s\".  Timeout requires a "
271				"positive integer value < %d.", optarg, INT_MAX);
272		else {
273			madrpc_set_timeout((int)val);
274			ibd_timeout = (int)val;
275		}
276		break;
277	case 's':
278		/* srcport is not required when resolving via IB_DEST_LID */
279		if (resolve_portid_str(ibd_ca, ibd_ca_port, &sm_portid, optarg,
280				IB_DEST_LID, 0, NULL) < 0)
281			IBEXIT("cannot resolve SM destination port %s",
282				optarg);
283		ibd_sm_id = &sm_portid;
284		break;
285	case 'K':
286		show_keys = 1;
287		break;
288	case 'y':
289		errno = 0;
290		ibd_mkey = strtoull(optarg, &endp, 0);
291		if (errno || *endp != '\0') {
292			errno = 0;
293			ibd_mkey = strtoull(getpass("M_Key: "), &endp, 0);
294			if (errno || *endp != '\0') {
295				IBEXIT("Bad M_Key");
296			}
297                }
298                break;
299	default:
300		return -1;
301	}
302
303	return 0;
304}
305
306static const struct ibdiag_opt common_opts[] = {
307	{"config", 'z', 1, "<config>", "use config file, default: " IBDIAG_CONFIG_GENERAL},
308	{"Ca", 'C', 1, "<ca>", "Ca name to use"},
309	{"Port", 'P', 1, "<port>", "Ca port number to use"},
310	{"Direct", 'D', 0, NULL, "use Direct address argument"},
311	{"Lid", 'L', 0, NULL, "use LID address argument"},
312	{"Guid", 'G', 0, NULL, "use GUID address argument"},
313	{"timeout", 't', 1, "<ms>", "timeout in ms"},
314	{"sm_port", 's', 1, "<lid>", "SM port lid"},
315	{"show_keys", 'K', 0, NULL, "display security keys in output"},
316	{"m_key", 'y', 1, "<key>", "M_Key to use in request"},
317	{"errors", 'e', 0, NULL, "show send and receive errors"},
318	{"verbose", 'v', 0, NULL, "increase verbosity level"},
319	{"debug", 'd', 0, NULL, "raise debug level"},
320	{"help", 'h', 0, NULL, "help message"},
321	{"version", 'V', 0, NULL, "show version"},
322	{0}
323};
324
325static void make_opt(struct option *l, const struct ibdiag_opt *o,
326		     const struct ibdiag_opt *map[])
327{
328	l->name = o->name;
329	l->has_arg = o->has_arg;
330	l->flag = NULL;
331	l->val = o->letter;
332	if (!map[l->val])
333		map[l->val] = o;
334}
335
336static struct option *make_long_opts(const char *exclude_str,
337				     const struct ibdiag_opt *custom_opts,
338				     const struct ibdiag_opt *map[])
339{
340	struct option *long_opts, *l;
341	const struct ibdiag_opt *o;
342	unsigned n = 0;
343
344	if (custom_opts)
345		for (o = custom_opts; o->name; o++)
346			n++;
347
348	long_opts = malloc((sizeof(common_opts) / sizeof(common_opts[0]) + n) *
349			   sizeof(*long_opts));
350	if (!long_opts)
351		return NULL;
352
353	l = long_opts;
354
355	if (custom_opts)
356		for (o = custom_opts; o->name; o++)
357			make_opt(l++, o, map);
358
359	for (o = common_opts; o->name; o++) {
360		if (exclude_str && strchr(exclude_str, o->letter))
361			continue;
362		make_opt(l++, o, map);
363	}
364
365	memset(l, 0, sizeof(*l));
366
367	return long_opts;
368}
369
370static void make_str_opts(const struct option *o, char *p, unsigned size)
371{
372	unsigned i, n = 0;
373
374	for (n = 0; o->name && n + 2 + o->has_arg < size; o++) {
375		p[n++] = (char)o->val;
376		for (i = 0; i < (unsigned)o->has_arg; i++)
377			p[n++] = ':';
378	}
379	p[n] = '\0';
380}
381
382int ibdiag_process_opts(int argc, char *const argv[], void *cxt,
383			const char *exclude_common_str,
384			const struct ibdiag_opt custom_opts[],
385			int (*custom_handler) (void *cxt, int val,
386					       char *optarg),
387			const char *usage_args, const char *usage_examples[])
388{
389	char str_opts[1024];
390	const struct ibdiag_opt *o;
391
392	prog_name = argv[0];
393	prog_args = usage_args;
394	prog_examples = usage_examples;
395
396	if (long_opts)
397		free(long_opts);
398
399	long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map);
400	if (!long_opts)
401		return -1;
402
403	read_ibdiag_config(IBDIAG_CONFIG_GENERAL);
404
405	make_str_opts(long_opts, str_opts, sizeof(str_opts));
406
407	while (1) {
408		int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
409		if (ch == -1)
410			break;
411		o = opts_map[ch];
412		if (!o)
413			ibdiag_show_usage();
414		if (custom_handler) {
415			if (custom_handler(cxt, ch, optarg) &&
416			    process_opt(ch, optarg))
417				ibdiag_show_usage();
418		} else if (process_opt(ch, optarg))
419			ibdiag_show_usage();
420	}
421
422	return 0;
423}
424
425void ibexit(const char *fn, char *msg, ...)
426{
427	char buf[512];
428	va_list va;
429	int n;
430
431	va_start(va, msg);
432	n = vsprintf(buf, msg, va);
433	va_end(va);
434	buf[n] = 0;
435
436	if (ibdebug)
437		printf("%s: iberror: [pid %d] %s: failed: %s\n",
438		       prog_name ? prog_name : "", getpid(), fn, buf);
439	else
440		printf("%s: iberror: failed: %s\n",
441		       prog_name ? prog_name : "", buf);
442
443	exit(-1);
444}
445
446char *
447conv_cnt_human_readable(uint64_t val64, float *val, int data)
448{
449	uint64_t tmp = val64;
450	int ui = 0;
451	int div = 1;
452
453	tmp /= 1024;
454	while (tmp) {
455		ui++;
456		tmp /= 1024;
457		div *= 1024;
458	}
459
460	*val = (float)(val64);
461	if (data) {
462		*val *= 4;
463		if (*val/div > 1024) {
464			ui++;
465			div *= 1024;
466		}
467	}
468	*val /= div;
469
470	if (data) {
471		switch (ui) {
472			case 0:
473				return ("B");
474			case 1:
475				return ("KB");
476			case 2:
477				return ("MB");
478			case 3:
479				return ("GB");
480			case 4:
481				return ("TB");
482			case 5:
483				return ("PB");
484			case 6:
485				return ("EB");
486			default:
487				return ("");
488		}
489	} else {
490		switch (ui) {
491			case 0:
492				return ("");
493			case 1:
494				return ("K");
495			case 2:
496				return ("M");
497			case 3:
498				return ("G");
499			case 4:
500				return ("T");
501			case 5:
502				return ("P");
503			case 6:
504				return ("E");
505			default:
506				return ("");
507		}
508	}
509	return ("");
510}
511
512int is_port_info_extended_supported(ib_portid_t * dest, int port,
513				    struct ibmad_port *srcport)
514{
515	uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
516	uint32_t cap_mask;
517	uint16_t cap_mask2;
518
519	if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, port, 0, srcport))
520		IBEXIT("port info query failed");
521
522	mad_decode_field(data, IB_PORT_CAPMASK_F, &cap_mask);
523	if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_CAP_MASK2)) {
524		mad_decode_field(data, IB_PORT_CAPMASK2_F, &cap_mask2);
525		if (!(cap_mask2 &
526		      CL_NTOH16(IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED))) {
527			IBWARN("port info capability mask2 = 0x%x doesn't"
528			       " indicate PortInfoExtended support", cap_mask2);
529			return 0;
530		}
531	} else {
532		IBWARN("port info capability mask2 not supported");
533		return 0;
534	}
535
536	return 1;
537}
538
539int is_mlnx_ext_port_info_supported(uint32_t vendorid,
540				    uint16_t devid)
541{
542	if (ibd_ibnetdisc_flags & IBND_CONFIG_MLX_EPI) {
543
544		if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 ||
545		    ((vendorid == 0x119f) &&
546		     /* Bull SwitchX */
547		     (devid == 0x1b02 || devid == 0x1b50 ||
548		      /* Bull SwitchIB and SwitchIB2 */
549		      devid == 0x1ba0 ||
550		      (devid >= 0x1bd0 && devid <= 0x1bd5))))
551			return 1;
552		if ((devid >= 0x1003 && devid <= 0x1017) ||
553		    ((vendorid == 0x119f) &&
554		     /* Bull ConnectX3 */
555		     (devid == 0x1b33 || devid == 0x1b73 ||
556		      devid == 0x1b40 || devid == 0x1b41 ||
557		      devid == 0x1b60 || devid == 0x1b61 ||
558		      /* Bull ConnectIB */
559		      devid == 0x1b83 ||
560		      devid == 0x1b93 || devid == 0x1b94 ||
561		      /* Bull ConnectX4 */
562		      devid == 0x1bb4 || devid == 0x1bb5 ||
563		      devid == 0x1bc4)))
564			return 1;
565	}
566
567	return 0;
568}
569
570/** =========================================================================
571 * Resolve the SM portid using the umad layer rather than using
572 * ib_resolve_smlid_via which requires a PortInfo query on the local port.
573 */
574int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id)
575{
576	umad_port_t port;
577	int rc;
578
579	if (!sm_id)
580		return (-1);
581
582	if ((rc = umad_get_port(ca_name, portnum, &port)) < 0)
583		return rc;
584
585	memset(sm_id, 0, sizeof(*sm_id));
586	sm_id->lid = port.sm_lid;
587	sm_id->sl = port.sm_sl;
588
589	umad_release_port(&port);
590
591	return 0;
592}
593
594/** =========================================================================
595 * Resolve local CA characteristics using the umad layer rather than using
596 * ib_resolve_self_via which requires SMP queries on the local port.
597 */
598int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
599		 int *portnum, ibmad_gid_t *gid)
600{
601	umad_port_t port;
602	uint64_t prefix, guid;
603	int rc;
604
605	if (!(portid || portnum || gid))
606		return (-1);
607
608	if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0)
609		return rc;
610
611	if (portid) {
612		memset(portid, 0, sizeof(*portid));
613		portid->lid = port.base_lid;
614		portid->sl = port.sm_sl;
615	}
616	if (portnum)
617		*portnum = port.portnum;
618	if (gid) {
619		memset(gid, 0, sizeof(*gid));
620		prefix = cl_ntoh64(port.gid_prefix);
621		guid = cl_ntoh64(port.port_guid);
622		mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix);
623		mad_encode_field(*gid, IB_GID_GUID_F, &guid);
624	}
625
626	umad_release_port(&port);
627
628	return 0;
629}
630
631int resolve_gid(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
632		ibmad_gid_t gid, ib_portid_t * sm_id,
633		const struct ibmad_port *srcport)
634{
635	ib_portid_t sm_portid;
636	char buf[IB_SA_DATA_SIZE] = { 0 };
637
638	if (!sm_id) {
639		sm_id = &sm_portid;
640		if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
641			return -1;
642	}
643
644	if ((portid->lid =
645	     ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0)
646		return -1;
647
648	return 0;
649}
650
651int resolve_guid(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
652		 uint64_t *guid, ib_portid_t *sm_id,
653		 const struct ibmad_port *srcport)
654{
655	ib_portid_t sm_portid;
656	uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
657	uint64_t prefix;
658	ibmad_gid_t selfgid;
659
660	if (!sm_id) {
661		sm_id = &sm_portid;
662		if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
663			return -1;
664	}
665
666	if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0)
667		return -1;
668
669	memcpy(&prefix, portid->gid, sizeof(prefix));
670	if (!prefix)
671		mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
672				IB_DEFAULT_SUBN_PREFIX);
673	if (guid)
674		mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);
675
676	if ((portid->lid =
677	     ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0)
678		return -1;
679
680	mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl);
681	return 0;
682}
683
684/*
685 * Callers of this function should ensure their ibmad_port has been opened with
686 * IB_SA_CLASS as this function may require the SA to resolve addresses.
687 */
688int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
689		       char *addr_str, enum MAD_DEST dest_type,
690		       ib_portid_t *sm_id, const struct ibmad_port *srcport)
691{
692	ibmad_gid_t gid;
693	uint64_t guid;
694	int lid;
695	char *routepath;
696	ib_portid_t selfportid = { 0 };
697	int selfport = 0;
698
699	memset(portid, 0, sizeof *portid);
700
701	switch (dest_type) {
702	case IB_DEST_LID:
703		lid = strtol(addr_str, 0, 0);
704		if (!IB_LID_VALID(lid))
705			return -1;
706		return ib_portid_set(portid, lid, 0, 0);
707
708	case IB_DEST_DRPATH:
709		if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0)
710			return -1;
711		return 0;
712
713	case IB_DEST_GUID:
714		if (!(guid = strtoull(addr_str, 0, 0)))
715			return -1;
716
717		/* keep guid in portid? */
718		return resolve_guid(ca_name, ca_port, portid, &guid, sm_id,
719				    srcport);
720
721	case IB_DEST_DRSLID:
722		lid = strtol(addr_str, &routepath, 0);
723		routepath++;
724		if (!IB_LID_VALID(lid))
725			return -1;
726		ib_portid_set(portid, lid, 0, 0);
727
728		/* handle DR parsing and set DrSLID to local lid */
729		if (resolve_self(ca_name, ca_port, &selfportid, &selfport,
730				 NULL) < 0)
731			return -1;
732		if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) <
733		    0)
734			return -1;
735		return 0;
736
737	case IB_DEST_GID:
738		if (inet_pton(AF_INET6, addr_str, &gid) <= 0)
739			return -1;
740		return resolve_gid(ca_name, ca_port, portid, gid, sm_id,
741				   srcport);
742	default:
743		IBWARN("bad dest_type %d", dest_type);
744	}
745
746	return -1;
747}
748
749static unsigned int get_max_width(unsigned int num)
750{
751	unsigned r = 0;			/* 1x */
752
753	if (num & 8)
754		r = 3;			/* 12x */
755	else {
756		if (num & 4)
757			r = 2;		/* 8x */
758		else if (num & 2)
759			r = 1;		/* 4x */
760		else if (num & 0x10)
761			r = 4;		/* 2x */
762	}
763
764        return (1 << r);
765}
766
767static unsigned int get_max(unsigned int num)
768{
769	unsigned r = 0;		// r will be lg(num)
770
771	while (num >>= 1)	// unroll for more speed...
772		r++;
773
774	return (1 << r);
775}
776
777void get_max_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port)
778{
779	char buf[64];
780	uint32_t max_speed = 0;
781	uint32_t cap_mask, rem_cap_mask, fdr10;
782	uint8_t *info = NULL;
783
784	uint32_t max_width = get_max_width(mad_get_field(port->info, 0,
785						   IB_PORT_LINK_WIDTH_SUPPORTED_F)
786				     & mad_get_field(port->remoteport->info, 0,
787						     IB_PORT_LINK_WIDTH_SUPPORTED_F));
788	if ((max_width & mad_get_field(port->info, 0,
789				       IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0)
790		// we are not at the max supported width
791		// print what we could be at.
792		snprintf(width_msg, msg_size, "Could be %s",
793			 mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F,
794				      buf, 64, &max_width));
795
796	if (port->node->type == IB_NODE_SWITCH) {
797		if (port->node->ports[0])
798			info = (uint8_t *)&port->node->ports[0]->info;
799	}
800	else
801		info = (uint8_t *)&port->info;
802
803	if (info)
804		cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
805	else
806		cap_mask = 0;
807
808	info = NULL;
809	if (port->remoteport->node->type == IB_NODE_SWITCH) {
810		if (port->remoteport->node->ports[0])
811			info = (uint8_t *)&port->remoteport->node->ports[0]->info;
812	} else
813		info = (uint8_t *)&port->remoteport->info;
814
815	if (info)
816		rem_cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
817	else
818		rem_cap_mask = 0;
819	if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS) &&
820	    rem_cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
821		goto check_ext_speed;
822check_fdr10_supp:
823	fdr10 = (mad_get_field(port->ext_info, 0,
824			       IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10)
825		&& (mad_get_field(port->remoteport->ext_info, 0,
826				  IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10);
827	if (fdr10)
828		goto check_fdr10_active;
829
830	max_speed = get_max(mad_get_field(port->info, 0,
831					  IB_PORT_LINK_SPEED_SUPPORTED_F)
832			    & mad_get_field(port->remoteport->info, 0,
833					    IB_PORT_LINK_SPEED_SUPPORTED_F));
834	if ((max_speed & mad_get_field(port->info, 0,
835				       IB_PORT_LINK_SPEED_ACTIVE_F)) == 0)
836		// we are not at the max supported speed
837		// print what we could be at.
838		snprintf(speed_msg, msg_size, "Could be %s",
839			 mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F,
840				      buf, 64, &max_speed));
841	return;
842
843check_ext_speed:
844	if (mad_get_field(port->info, 0,
845			  IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0 ||
846	    mad_get_field(port->remoteport->info, 0,
847			  IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0)
848		goto check_fdr10_supp;
849	max_speed = get_max(mad_get_field(port->info, 0,
850					  IB_PORT_LINK_SPEED_EXT_SUPPORTED_F)
851			    & mad_get_field(port->remoteport->info, 0,
852					    IB_PORT_LINK_SPEED_EXT_SUPPORTED_F));
853	if ((max_speed & mad_get_field(port->info, 0,
854				       IB_PORT_LINK_SPEED_EXT_ACTIVE_F)) == 0)
855		// we are not at the max supported extended speed
856		// print what we could be at.
857		snprintf(speed_msg, msg_size, "Could be %s",
858			 mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
859				      buf, 64, &max_speed));
860	return;
861
862check_fdr10_active:
863	if ((mad_get_field(port->ext_info, 0,
864			   IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10) == 0) {
865		/* Special case QDR to try to avoid confusion with FDR10 */
866		if (mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F) == 4)	/* QDR (10.0 Gbps) */
867			snprintf(speed_msg, msg_size,
868				 "Could be FDR10 (Found link at QDR but expected speed is FDR10)");
869		else
870			snprintf(speed_msg, msg_size, "Could be FDR10");
871	}
872}
873
874int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
875		   const char *format, va_list va_args)
876{
877	int len, i, ret;
878
879	len = strlen(mad_field_name(f));
880	if (len + 2 > n || spacing + 1 > n)
881		return 0;
882
883	strncpy(buf, mad_field_name(f), n);
884	buf[len] = ':';
885	for (i = len+1; i < spacing+1; i++) {
886		buf[i] = '.';
887	}
888
889	ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args);
890	if (ret >= n - spacing)
891		buf[n] = '\0';
892
893	return ret + spacing;
894}
895
896int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
897		  const char *format, ...)
898{
899	va_list val;
900	int ret;
901
902	va_start(val, format);
903	ret = vsnprint_field(buf, n, f, spacing, format, val);
904	va_end(val);
905
906	return ret;
907}
908
909void dump_portinfo(void *pi, int tabs)
910{
911	int field, i;
912	char val[64];
913	char buf[1024];
914
915	for (field = IB_PORT_FIRST_F; field < IB_PORT_LAST_F; field++) {
916		for (i=0;i<tabs;i++)
917			printf("\t");
918		if (field == IB_PORT_MKEY_F && show_keys == 0) {
919			snprint_field(buf, 1024, field, 32, NOT_DISPLAYED_STR);
920		} else {
921			mad_decode_field(pi, field, val);
922			if (!mad_dump_field(field, buf, 1024, val))
923				return;
924		}
925		printf("%s\n", buf);
926	}
927
928	for (field = IB_PORT_CAPMASK2_F;
929	     field < IB_PORT_LINK_SPEED_EXT_LAST_F; field++) {
930		for (i=0;i<tabs;i++)
931			printf("\t");
932		mad_decode_field(pi, field, val);
933		if (!mad_dump_field(field, buf, 1024, val))
934			return;
935		printf("%s\n", buf);
936	}
937}
938
939op_fn_t *match_op(const match_rec_t match_tbl[], char *name)
940{
941	const match_rec_t *r;
942	for (r = match_tbl; r->name; r++)
943		if (!strcasecmp(r->name, name) ||
944		    (r->alias && !strcasecmp(r->alias, name)))
945			return r->fn;
946	return NULL;
947}
948