saquery.c revision 275448
1/*
2 * Copyright (c) 2006,2007 The Regents of the University of California.
3 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
4 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
5 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 *
7 * Produced at Lawrence Livermore National Laboratory.
8 * Written by Ira Weiny <weiny2@llnl.gov>.
9 *
10 * This software is available to you under a choice of one of two
11 * licenses.  You may choose to be licensed under the terms of the GNU
12 * General Public License (GPL) Version 2, available from the file
13 * COPYING in the main directory of this source tree, or the
14 * OpenIB.org BSD license below:
15 *
16 *     Redistribution and use in source and binary forms, with or
17 *     without modification, are permitted provided that the following
18 *     conditions are met:
19 *
20 *      - Redistributions of source code must retain the above
21 *        copyright notice, this list of conditions and the following
22 *        disclaimer.
23 *
24 *      - Redistributions in binary form must reproduce the above
25 *        copyright notice, this list of conditions and the following
26 *        disclaimer in the documentation and/or other materials
27 *        provided with the distribution.
28 *
29 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
33 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
34 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
35 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * SOFTWARE.
37 *
38 */
39
40#include <unistd.h>
41#include <stdio.h>
42#include <sys/types.h>
43#include <sys/socket.h>
44#include <arpa/inet.h>
45#include <assert.h>
46#include <ctype.h>
47#include <string.h>
48
49#define _GNU_SOURCE
50#include <getopt.h>
51
52#include <infiniband/mad.h>
53#include <opensm/osm_log.h>
54#include <vendor/osm_vendor_api.h>
55#include <vendor/osm_vendor_sa_api.h>
56#include <opensm/osm_mad_pool.h>
57#include <complib/cl_debug.h>
58#include <complib/cl_nodenamemap.h>
59
60#include <netinet/in.h>
61
62#include "ibdiag_common.h"
63
64struct query_cmd {
65	const char *name, *alias;
66	ib_net16_t query_type;
67	const char *usage;
68	int (*handler) (const struct query_cmd * q, osm_bind_handle_t h,
69			int argc, char *argv[]);
70};
71
72char *argv0 = "saquery";
73
74static char *node_name_map_file = NULL;
75static nn_map_t *node_name_map = NULL;
76static ib_net64_t smkey = OSM_DEFAULT_SA_KEY;
77
78/**
79 * Declare some globals because I don't want this to be too complex.
80 */
81#define MAX_PORTS (8)
82#define DEFAULT_SA_TIMEOUT_MS (1000)
83osmv_query_res_t result;
84osm_log_t log_osm;
85osm_mad_pool_t mad_pool;
86osm_vendor_t *vendor = NULL;
87int osm_debug = 0;
88uint32_t sa_timeout_ms = DEFAULT_SA_TIMEOUT_MS;
89char *sa_hca_name = NULL;
90uint32_t sa_port_num = 0;
91
92enum {
93	ALL,
94	LID_ONLY,
95	UNIQUE_LID_ONLY,
96	GUID_ONLY,
97	ALL_DESC,
98	NAME_OF_LID,
99	NAME_OF_GUID,
100} node_print_desc = ALL;
101
102char *requested_name = NULL;
103ib_net16_t requested_lid = 0;
104int requested_lid_flag = 0;
105ib_net64_t requested_guid = 0;
106int requested_guid_flag = 0;
107
108static void format_buf(char *in, char *out, unsigned size)
109{
110	unsigned i;
111
112	for (i = 0; i < size - 3 && *in; i++) {
113		*out++ = *in;
114		if (*in++ == '\n' && *in) {
115			*out++ = '\t';
116			*out++ = '\t';
117		}
118	}
119	*out = '\0';
120}
121
122/**
123 * Call back for the various record requests.
124 */
125static void query_res_cb(osmv_query_res_t * res)
126{
127	result = *res;
128}
129
130static void print_node_desc(ib_node_record_t * node_record)
131{
132	ib_node_info_t *p_ni = &(node_record->node_info);
133	ib_node_desc_t *p_nd = &(node_record->node_desc);
134
135	if (p_ni->node_type == IB_NODE_TYPE_CA) {
136		printf("%6d  \"%s\"\n",
137		       cl_ntoh16(node_record->lid),
138		       clean_nodedesc((char *)p_nd->description));
139	}
140}
141
142static void print_node_record(ib_node_record_t * node_record)
143{
144	ib_node_info_t *p_ni = NULL;
145	ib_node_desc_t *p_nd = NULL;
146	char *name;
147
148	p_ni = &(node_record->node_info);
149	p_nd = &(node_record->node_desc);
150
151	switch (node_print_desc) {
152	case LID_ONLY:
153	case UNIQUE_LID_ONLY:
154		printf("%d\n", cl_ntoh16(node_record->lid));
155		return;
156	case GUID_ONLY:
157		printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
158		return;
159	case NAME_OF_LID:
160	case NAME_OF_GUID:
161		name = remap_node_name(node_name_map,
162				       cl_ntoh64(p_ni->node_guid),
163				       (char *)p_nd->description);
164		printf("%s\n", name);
165		free(name);
166		return;
167	case ALL:
168	default:
169		break;
170	}
171
172	printf("NodeRecord dump:\n"
173	       "\t\tlid.....................0x%X\n"
174	       "\t\treserved................0x%X\n"
175	       "\t\tbase_version............0x%X\n"
176	       "\t\tclass_version...........0x%X\n"
177	       "\t\tnode_type...............%s\n"
178	       "\t\tnum_ports...............0x%X\n"
179	       "\t\tsys_guid................0x%016" PRIx64 "\n"
180	       "\t\tnode_guid...............0x%016" PRIx64 "\n"
181	       "\t\tport_guid...............0x%016" PRIx64 "\n"
182	       "\t\tpartition_cap...........0x%X\n"
183	       "\t\tdevice_id...............0x%X\n"
184	       "\t\trevision................0x%X\n"
185	       "\t\tport_num................0x%X\n"
186	       "\t\tvendor_id...............0x%X\n"
187	       "\t\tNodeDescription.........%s\n"
188	       "",
189	       cl_ntoh16(node_record->lid),
190	       cl_ntoh16(node_record->resv),
191	       p_ni->base_version,
192	       p_ni->class_version,
193	       ib_get_node_type_str(p_ni->node_type),
194	       p_ni->num_ports,
195	       cl_ntoh64(p_ni->sys_guid),
196	       cl_ntoh64(p_ni->node_guid),
197	       cl_ntoh64(p_ni->port_guid),
198	       cl_ntoh16(p_ni->partition_cap),
199	       cl_ntoh16(p_ni->device_id),
200	       cl_ntoh32(p_ni->revision),
201	       ib_node_info_get_local_port_num(p_ni),
202	       cl_ntoh32(ib_node_info_get_vendor_id(p_ni)),
203	       clean_nodedesc((char *)node_record->node_desc.description)
204	    );
205}
206
207static void dump_path_record(void *data)
208{
209	char gid_str[INET6_ADDRSTRLEN];
210	char gid_str2[INET6_ADDRSTRLEN];
211	ib_path_rec_t *p_pr = data;
212	printf("PathRecord dump:\n"
213	       "\t\tservice_id..............0x%016" PRIx64 "\n"
214	       "\t\tdgid....................%s\n"
215	       "\t\tsgid....................%s\n"
216	       "\t\tdlid....................0x%X\n"
217	       "\t\tslid....................0x%X\n"
218	       "\t\thop_flow_raw............0x%X\n"
219	       "\t\ttclass..................0x%X\n"
220	       "\t\tnum_path_revers.........0x%X\n"
221	       "\t\tpkey....................0x%X\n"
222	       "\t\tqos_class...............0x%X\n"
223	       "\t\tsl......................0x%X\n"
224	       "\t\tmtu.....................0x%X\n"
225	       "\t\trate....................0x%X\n"
226	       "\t\tpkt_life................0x%X\n"
227	       "\t\tpreference..............0x%X\n"
228	       "\t\tresv2...................0x%X\n"
229	       "\t\tresv3...................0x%X\n"
230	       "",
231	       cl_ntoh64(p_pr->service_id),
232	       inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),
233	       inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),
234	       cl_ntoh16(p_pr->dlid),
235	       cl_ntoh16(p_pr->slid),
236	       cl_ntoh32(p_pr->hop_flow_raw),
237	       p_pr->tclass,
238	       p_pr->num_path,
239	       cl_ntoh16(p_pr->pkey),
240	       ib_path_rec_qos_class(p_pr),
241	       ib_path_rec_sl(p_pr),
242	       p_pr->mtu,
243	       p_pr->rate,
244	       p_pr->pkt_life,
245	       p_pr->preference,
246	       *(uint32_t *) & p_pr->resv2, *((uint16_t *) & p_pr->resv2 + 2)
247	    );
248}
249
250static void dump_class_port_info(void *data)
251{
252	char gid_str[INET6_ADDRSTRLEN];
253	char gid_str2[INET6_ADDRSTRLEN];
254	ib_class_port_info_t *class_port_info = data;
255
256	printf("SA ClassPortInfo:\n"
257	       "\t\tBase version.............%d\n"
258	       "\t\tClass version............%d\n"
259	       "\t\tCapability mask..........0x%04X\n"
260	       "\t\tCapability mask 2........0x%08X\n"
261	       "\t\tResponse time value......0x%02X\n"
262	       "\t\tRedirect GID.............%s\n"
263	       "\t\tRedirect TC/SL/FL........0x%08X\n"
264	       "\t\tRedirect LID.............0x%04X\n"
265	       "\t\tRedirect PKey............0x%04X\n"
266	       "\t\tRedirect QP..............0x%08X\n"
267	       "\t\tRedirect QKey............0x%08X\n"
268	       "\t\tTrap GID.................%s\n"
269	       "\t\tTrap TC/SL/FL............0x%08X\n"
270	       "\t\tTrap LID.................0x%04X\n"
271	       "\t\tTrap PKey................0x%04X\n"
272	       "\t\tTrap HL/QP...............0x%08X\n"
273	       "\t\tTrap QKey................0x%08X\n"
274	       "",
275	       class_port_info->base_ver,
276	       class_port_info->class_ver,
277	       cl_ntoh16(class_port_info->cap_mask),
278	       ib_class_cap_mask2(class_port_info),
279	       ib_class_resp_time_val(class_port_info),
280	       inet_ntop(AF_INET6, &(class_port_info->redir_gid), gid_str,
281			 sizeof gid_str),
282	       cl_ntoh32(class_port_info->redir_tc_sl_fl),
283	       cl_ntoh16(class_port_info->redir_lid),
284	       cl_ntoh16(class_port_info->redir_pkey),
285	       cl_ntoh32(class_port_info->redir_qp),
286	       cl_ntoh32(class_port_info->redir_qkey),
287	       inet_ntop(AF_INET6, &(class_port_info->trap_gid), gid_str2,
288			 sizeof gid_str2),
289	       cl_ntoh32(class_port_info->trap_tc_sl_fl),
290	       cl_ntoh16(class_port_info->trap_lid),
291	       cl_ntoh16(class_port_info->trap_pkey),
292	       cl_ntoh32(class_port_info->trap_hop_qp),
293	       cl_ntoh32(class_port_info->trap_qkey)
294	    );
295}
296
297static void dump_portinfo_record(void *data)
298{
299	ib_portinfo_record_t *p_pir = data;
300	const ib_port_info_t *const p_pi = &p_pir->port_info;
301
302	printf("PortInfoRecord dump:\n"
303	       "\t\tEndPortLid..............0x%X\n"
304	       "\t\tPortNum.................0x%X\n"
305	       "\t\tbase_lid................0x%X\n"
306	       "\t\tmaster_sm_base_lid......0x%X\n"
307	       "\t\tcapability_mask.........0x%X\n"
308	       "",
309	       cl_ntoh16(p_pir->lid),
310	       p_pir->port_num,
311	       cl_ntoh16(p_pi->base_lid),
312	       cl_ntoh16(p_pi->master_sm_base_lid),
313	       cl_ntoh32(p_pi->capability_mask)
314	    );
315}
316
317static void dump_one_portinfo_record(void *data)
318{
319	char buf[2048], buf2[4096];
320	ib_portinfo_record_t *pir = data;
321	ib_port_info_t *pi = &pir->port_info;
322
323	mad_dump_portinfo(buf, sizeof(buf), pi, sizeof(*pi));
324
325	format_buf(buf, buf2, sizeof(buf2));
326
327	printf("PortInfoRecord dump:\n"
328		"\tRID:\n"
329		"\t\tEndPortLid..............%u\n"
330		"\t\tPortNum.................0x%x\n"
331		"\t\tReserved................0x%x\n"
332		"\tPortInfo dump:\n\t\t%s",
333		cl_ntoh16(pir->lid), pir->port_num, pir->resv, buf2);
334}
335
336static void dump_multicast_group_record(void *data)
337{
338	char gid_str[INET6_ADDRSTRLEN];
339	ib_member_rec_t *p_mcmr = data;
340	uint8_t sl;
341	ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &sl, NULL, NULL);
342	printf("MCMemberRecord group dump:\n"
343	       "\t\tMGID....................%s\n"
344	       "\t\tMlid....................0x%X\n"
345	       "\t\tMtu.....................0x%X\n"
346	       "\t\tpkey....................0x%X\n"
347	       "\t\tRate....................0x%X\n"
348	       "\t\tSL......................0x%X\n"
349	       "",
350	       inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str),
351	       cl_ntoh16(p_mcmr->mlid),
352	       p_mcmr->mtu, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, sl);
353}
354
355static void dump_multicast_member_record(void *data)
356{
357	char gid_str[INET6_ADDRSTRLEN];
358	char gid_str2[INET6_ADDRSTRLEN];
359	ib_member_rec_t *p_mcmr = data;
360	uint16_t mlid = cl_ntoh16(p_mcmr->mlid);
361	int i = 0;
362	char *node_name = "<unknown>";
363
364	/* go through the node records searching for a port guid which matches
365	 * this port gid interface id.
366	 * This gives us a node name to print, if available.
367	 */
368	for (i = 0; i < result.result_cnt; i++) {
369		ib_node_record_t *nr =
370		    osmv_get_query_node_rec(result.p_result_madw, i);
371		if (nr->node_info.port_guid ==
372		    p_mcmr->port_gid.unicast.interface_id) {
373			node_name =
374			    clean_nodedesc((char *)nr->node_desc.description);
375			break;
376		}
377	}
378
379	if (requested_name) {
380		if (strtol(requested_name, NULL, 0) == mlid) {
381			printf("\t\tPortGid.................%s (%s)\n",
382			       inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
383					 gid_str, sizeof gid_str), node_name);
384		}
385	} else {
386		printf("MCMemberRecord member dump:\n"
387		       "\t\tMGID....................%s\n"
388		       "\t\tMlid....................0x%X\n"
389		       "\t\tPortGid.................%s\n"
390		       "\t\tScopeState..............0x%X\n"
391		       "\t\tProxyJoin...............0x%X\n"
392		       "\t\tNodeDescription.........%s\n"
393		       "",
394		       inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,
395				 sizeof gid_str),
396		       cl_ntoh16(p_mcmr->mlid),
397		       inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
398				 gid_str2, sizeof gid_str2),
399		       p_mcmr->scope_state, p_mcmr->proxy_join, node_name);
400	}
401}
402
403static void dump_service_record(void *data)
404{
405	char gid_str[INET6_ADDRSTRLEN];
406	char buf_service_key[35];
407	char buf_service_name[65];
408	ib_service_record_t *p_sr = data;
409
410	sprintf(buf_service_key,
411		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
412		p_sr->service_key[0], p_sr->service_key[1],
413		p_sr->service_key[2], p_sr->service_key[3],
414		p_sr->service_key[4], p_sr->service_key[5],
415		p_sr->service_key[6], p_sr->service_key[7],
416		p_sr->service_key[8], p_sr->service_key[9],
417		p_sr->service_key[10], p_sr->service_key[11],
418		p_sr->service_key[12], p_sr->service_key[13],
419		p_sr->service_key[14], p_sr->service_key[15]);
420	strncpy(buf_service_name, (char *)p_sr->service_name, 64);
421	buf_service_name[64] = '\0';
422
423	printf("ServiceRecord dump:\n"
424	       "\t\tServiceID...............0x%016" PRIx64 "\n"
425	       "\t\tServiceGID..............%s\n"
426	       "\t\tServiceP_Key............0x%X\n"
427	       "\t\tServiceLease............0x%X\n"
428	       "\t\tServiceKey..............%s\n"
429	       "\t\tServiceName.............%s\n"
430	       "\t\tServiceData8.1..........0x%X\n"
431	       "\t\tServiceData8.2..........0x%X\n"
432	       "\t\tServiceData8.3..........0x%X\n"
433	       "\t\tServiceData8.4..........0x%X\n"
434	       "\t\tServiceData8.5..........0x%X\n"
435	       "\t\tServiceData8.6..........0x%X\n"
436	       "\t\tServiceData8.7..........0x%X\n"
437	       "\t\tServiceData8.8..........0x%X\n"
438	       "\t\tServiceData8.9..........0x%X\n"
439	       "\t\tServiceData8.10.........0x%X\n"
440	       "\t\tServiceData8.11.........0x%X\n"
441	       "\t\tServiceData8.12.........0x%X\n"
442	       "\t\tServiceData8.13.........0x%X\n"
443	       "\t\tServiceData8.14.........0x%X\n"
444	       "\t\tServiceData8.15.........0x%X\n"
445	       "\t\tServiceData8.16.........0x%X\n"
446	       "\t\tServiceData16.1.........0x%X\n"
447	       "\t\tServiceData16.2.........0x%X\n"
448	       "\t\tServiceData16.3.........0x%X\n"
449	       "\t\tServiceData16.4.........0x%X\n"
450	       "\t\tServiceData16.5.........0x%X\n"
451	       "\t\tServiceData16.6.........0x%X\n"
452	       "\t\tServiceData16.7.........0x%X\n"
453	       "\t\tServiceData16.8.........0x%X\n"
454	       "\t\tServiceData32.1.........0x%X\n"
455	       "\t\tServiceData32.2.........0x%X\n"
456	       "\t\tServiceData32.3.........0x%X\n"
457	       "\t\tServiceData32.4.........0x%X\n"
458	       "\t\tServiceData64.1.........0x%016" PRIx64 "\n"
459	       "\t\tServiceData64.2.........0x%016" PRIx64 "\n"
460	       "",
461	       cl_ntoh64(p_sr->service_id),
462	       inet_ntop(AF_INET6, p_sr->service_gid.raw, gid_str,
463			 sizeof gid_str),
464	       cl_ntoh16(p_sr->service_pkey),
465	       cl_ntoh32(p_sr->service_lease),
466	       buf_service_key,
467	       buf_service_name,
468	       p_sr->service_data8[0], p_sr->service_data8[1],
469	       p_sr->service_data8[2], p_sr->service_data8[3],
470	       p_sr->service_data8[4], p_sr->service_data8[5],
471	       p_sr->service_data8[6], p_sr->service_data8[7],
472	       p_sr->service_data8[8], p_sr->service_data8[9],
473	       p_sr->service_data8[10], p_sr->service_data8[11],
474	       p_sr->service_data8[12], p_sr->service_data8[13],
475	       p_sr->service_data8[14], p_sr->service_data8[15],
476	       cl_ntoh16(p_sr->service_data16[0]),
477	       cl_ntoh16(p_sr->service_data16[1]),
478	       cl_ntoh16(p_sr->service_data16[2]),
479	       cl_ntoh16(p_sr->service_data16[3]),
480	       cl_ntoh16(p_sr->service_data16[4]),
481	       cl_ntoh16(p_sr->service_data16[5]),
482	       cl_ntoh16(p_sr->service_data16[6]),
483	       cl_ntoh16(p_sr->service_data16[7]),
484	       cl_ntoh32(p_sr->service_data32[0]),
485	       cl_ntoh32(p_sr->service_data32[1]),
486	       cl_ntoh32(p_sr->service_data32[2]),
487	       cl_ntoh32(p_sr->service_data32[3]),
488	       cl_ntoh64(p_sr->service_data64[0]),
489	       cl_ntoh64(p_sr->service_data64[1])
490	    );
491}
492
493static void dump_inform_info_record(void *data)
494{
495	char gid_str[INET6_ADDRSTRLEN];
496	char gid_str2[INET6_ADDRSTRLEN];
497	ib_inform_info_record_t *p_iir = data;
498	uint32_t qpn;
499	uint8_t resp_time_val;
500
501	ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.
502					 qpn_resp_time_val, &qpn,
503					 &resp_time_val);
504
505	if (p_iir->inform_info.is_generic) {
506		printf("InformInfoRecord dump:\n"
507		       "\t\tRID\n"
508		       "\t\tSubscriberGID...........%s\n"
509		       "\t\tSubscriberEnum..........0x%X\n"
510		       "\t\tInformInfo dump:\n"
511		       "\t\tgid.....................%s\n"
512		       "\t\tlid_range_begin.........0x%X\n"
513		       "\t\tlid_range_end...........0x%X\n"
514		       "\t\tis_generic..............0x%X\n"
515		       "\t\tsubscribe...............0x%X\n"
516		       "\t\ttrap_type...............0x%X\n"
517		       "\t\ttrap_num................%u\n"
518		       "\t\tqpn.....................0x%06X\n"
519		       "\t\tresp_time_val...........0x%X\n"
520		       "\t\tnode_type...............0x%06X\n"
521		       "",
522		       inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
523				 sizeof gid_str),
524		       cl_ntoh16(p_iir->subscriber_enum),
525		       inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2,
526				 sizeof gid_str2),
527		       cl_ntoh16(p_iir->inform_info.lid_range_begin),
528		       cl_ntoh16(p_iir->inform_info.lid_range_end),
529		       p_iir->inform_info.is_generic,
530		       p_iir->inform_info.subscribe,
531		       cl_ntoh16(p_iir->inform_info.trap_type),
532		       cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
533		       cl_ntoh32(qpn),
534		       resp_time_val,
535		       cl_ntoh32(ib_inform_info_get_prod_type
536				 (&p_iir->inform_info))
537		    );
538	} else {
539		printf("InformInfoRecord dump:\n"
540		       "\t\tRID\n"
541		       "\t\tSubscriberGID...........%s\n"
542		       "\t\tSubscriberEnum..........0x%X\n"
543		       "\t\tInformInfo dump:\n"
544		       "\t\tgid.....................%s\n"
545		       "\t\tlid_range_begin.........0x%X\n"
546		       "\t\tlid_range_end...........0x%X\n"
547		       "\t\tis_generic..............0x%X\n"
548		       "\t\tsubscribe...............0x%X\n"
549		       "\t\ttrap_type...............0x%X\n"
550		       "\t\tdev_id..................0x%X\n"
551		       "\t\tqpn.....................0x%06X\n"
552		       "\t\tresp_time_val...........0x%X\n"
553		       "\t\tvendor_id...............0x%06X\n"
554		       "",
555		       inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
556				 sizeof gid_str),
557		       cl_ntoh16(p_iir->subscriber_enum),
558		       inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
559				 gid_str2, sizeof gid_str2),
560		       cl_ntoh16(p_iir->inform_info.lid_range_begin),
561		       cl_ntoh16(p_iir->inform_info.lid_range_end),
562		       p_iir->inform_info.is_generic,
563		       p_iir->inform_info.subscribe,
564		       cl_ntoh16(p_iir->inform_info.trap_type),
565		       cl_ntoh16(p_iir->inform_info.g_or_v.vend.dev_id),
566		       cl_ntoh32(qpn),
567		       resp_time_val,
568		       cl_ntoh32(ib_inform_info_get_prod_type
569				 (&p_iir->inform_info))
570		    );
571	}
572}
573
574static void dump_one_link_record(void *data)
575{
576	ib_link_record_t *lr = data;
577	printf("LinkRecord dump:\n"
578	       "\t\tFromLID....................%u\n"
579	       "\t\tFromPort...................%u\n"
580	       "\t\tToPort.....................%u\n"
581	       "\t\tToLID......................%u\n",
582	       cl_ntoh16(lr->from_lid), lr->from_port_num,
583	       lr->to_port_num, cl_ntoh16(lr->to_lid));
584}
585
586static void dump_one_slvl_record(void *data)
587{
588	ib_slvl_table_record_t *slvl = data;
589	ib_slvl_table_t *t = &slvl->slvl_tbl;
590	printf("SL2VLTableRecord dump:\n"
591	       "\t\tLID........................%u\n"
592	       "\t\tInPort.....................%u\n"
593	       "\t\tOutPort....................%u\n"
594	       "\t\tSL: 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|\n"
595	       "\t\tVL:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u"
596	       "|%2u|%2u|%2u|\n",
597	       cl_ntoh16(slvl->lid), slvl->in_port_num, slvl->out_port_num,
598	       ib_slvl_table_get(t, 0), ib_slvl_table_get(t, 1),
599	       ib_slvl_table_get(t, 2), ib_slvl_table_get(t, 3),
600	       ib_slvl_table_get(t, 4), ib_slvl_table_get(t, 5),
601	       ib_slvl_table_get(t, 6), ib_slvl_table_get(t, 7),
602	       ib_slvl_table_get(t, 8), ib_slvl_table_get(t, 9),
603	       ib_slvl_table_get(t, 10), ib_slvl_table_get(t, 11),
604	       ib_slvl_table_get(t, 12), ib_slvl_table_get(t, 13),
605	       ib_slvl_table_get(t, 14), ib_slvl_table_get(t, 15));
606}
607
608static void dump_one_vlarb_record(void *data)
609{
610	ib_vl_arb_table_record_t *vlarb = data;
611	ib_vl_arb_element_t *e = vlarb->vl_arb_tbl.vl_entry;
612	int i;
613	printf("VLArbTableRecord dump:\n"
614	       "\t\tLID........................%u\n"
615	       "\t\tPort.......................%u\n"
616	       "\t\tBlock......................%u\n",
617	       cl_ntoh16(vlarb->lid), vlarb->port_num, vlarb->block_num);
618	for (i = 0; i < 32; i += 16) {
619		printf("\t\tVL    :%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
620		       "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",
621		       e[i + 0].vl, e[i + 1].vl, e[i + 2].vl, e[i + 3].vl,
622		       e[i + 4].vl, e[i + 5].vl, e[i + 6].vl, e[i + 7].vl,
623		       e[i + 8].vl, e[i + 9].vl, e[i + 10].vl, e[i + 11].vl,
624		       e[i + 12].vl, e[i + 13].vl, e[i + 14].vl, e[i + 15].vl);
625		printf("\n\t\tWeight:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
626		       "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",
627		       e[i + 0].weight, e[i + 1].weight, e[i + 2].weight,
628		       e[i + 3].weight, e[i + 4].weight, e[i + 5].weight,
629		       e[i + 6].weight, e[i + 7].weight, e[i + 8].weight,
630		       e[i + 9].weight, e[i + 10].weight, e[i + 11].weight,
631		       e[i + 12].weight, e[i + 13].weight, e[i + 14].weight,
632		       e[i + 15].weight);
633		printf("\n");
634	}
635}
636
637static void dump_one_pkey_tbl_record(void *data)
638{
639	ib_pkey_table_record_t *pktr = data;
640	ib_net16_t *p = pktr->pkey_tbl.pkey_entry;
641	int i;
642	printf("PKeyTableRecord dump:\n"
643	       "\t\tLID........................%u\n"
644	       "\t\tPort.......................%u\n"
645	       "\t\tBlock......................%u\n"
646	       "\t\tPKey Table:\n",
647	       cl_ntoh16(pktr->lid), pktr->port_num, pktr->block_num);
648	for (i = 0; i < 32; i += 8)
649		printf("\t\t0x%04x 0x%04x 0x%04x 0x%04x"
650		       " 0x%04x 0x%04x 0x%04x 0x%04x\n",
651		       cl_ntoh16(p[i + 0]), cl_ntoh16(p[i + 1]),
652		       cl_ntoh16(p[i + 2]), cl_ntoh16(p[i + 3]),
653		       cl_ntoh16(p[i + 4]), cl_ntoh16(p[i + 5]),
654		       cl_ntoh16(p[i + 6]), cl_ntoh16(p[i + 7]));
655	printf("\n");
656}
657
658static void dump_one_lft_record(void *data)
659{
660	ib_lft_record_t *lftr = data;
661	unsigned block = cl_ntoh16(lftr->block_num);
662	int i;
663	printf("LFT Record dump:\n"
664	       "\t\tLID........................%u\n"
665	       "\t\tBlock......................%u\n"
666	       "\t\tLFT:\n\t\tLID\tPort Number\n", cl_ntoh16(lftr->lid), block);
667	for (i = 0; i < 64; i++)
668		printf("\t\t%u\t%u\n", block * 64 + i, lftr->lft[i]);
669	printf("\n");
670}
671
672static void dump_one_mft_record(void *data)
673{
674	ib_mft_record_t *mftr = data;
675	unsigned position = cl_ntoh16(mftr->position_block_num) >> 12;
676	unsigned block = cl_ntoh16(mftr->position_block_num) &
677	    IB_MCAST_BLOCK_ID_MASK_HO;
678	int i;
679	printf("MFT Record dump:\n"
680	       "\t\tLID........................%u\n"
681	       "\t\tPosition...................%u\n"
682	       "\t\tBlock......................%u\n"
683	       "\t\tMFT:\n\t\tMLID\tPort Mask\n",
684	       cl_ntoh16(mftr->lid), position, block);
685	for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
686		printf("\t\t0x%x\t0x%x\n",
687		       IB_LID_MCAST_START_HO + block * 64 + i,
688		       cl_ntoh16(mftr->mft[i]));
689	printf("\n");
690}
691static void dump_results(osmv_query_res_t * r, void (*dump_func) (void *))
692{
693	int i;
694	for (i = 0; i < r->result_cnt; i++) {
695		void *data = osmv_get_query_result(r->p_result_madw, i);
696		dump_func(data);
697	}
698}
699
700static void return_mad(void)
701{
702	/*
703	 * Return the IB query MAD to the pool as necessary.
704	 */
705	if (result.p_result_madw != NULL) {
706		osm_mad_pool_put(&mad_pool, result.p_result_madw);
707		result.p_result_madw = NULL;
708	}
709}
710
711/**
712 * Get any record(s)
713 */
714static ib_api_status_t
715get_any_records(osm_bind_handle_t h,
716		ib_net16_t attr_id, ib_net32_t attr_mod, ib_net64_t comp_mask,
717		void *attr, ib_net16_t attr_offset, ib_net64_t sm_key)
718{
719	ib_api_status_t status;
720	osmv_query_req_t req;
721	osmv_user_query_t user;
722
723	memset(&req, 0, sizeof(req));
724	memset(&user, 0, sizeof(user));
725
726	user.attr_id = attr_id;
727	user.attr_offset = attr_offset;
728	user.attr_mod = attr_mod;
729	user.comp_mask = comp_mask;
730	user.p_attr = attr;
731
732	req.query_type = OSMV_QUERY_USER_DEFINED;
733	req.timeout_ms = sa_timeout_ms;
734	req.retry_cnt = 1;
735	req.flags = OSM_SA_FLAGS_SYNC;
736	req.query_context = NULL;
737	req.pfn_query_cb = query_res_cb;
738	req.p_query_input = &user;
739	req.sm_key = sm_key;
740
741	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
742		fprintf(stderr, "Query SA failed: %s\n",
743			ib_get_err_str(status));
744		return status;
745	}
746
747	if (result.status != IB_SUCCESS) {
748		fprintf(stderr, "Query result returned: %s\n",
749			ib_get_err_str(result.status));
750		return result.status;
751	}
752
753	return status;
754}
755
756/**
757 * Get all the records available for requested query type.
758 */
759static ib_api_status_t
760get_all_records(osm_bind_handle_t h,
761		ib_net16_t query_id, ib_net16_t attr_offset, int trusted)
762{
763	return get_any_records(h, query_id, 0, 0, NULL, attr_offset,
764			       trusted ? smkey : 0);
765}
766
767/**
768 * return the lid from the node descriptor (name) supplied
769 */
770static ib_api_status_t
771get_lid_from_name(osm_bind_handle_t h, const char *name, ib_net16_t * lid)
772{
773	int i = 0;
774	ib_node_record_t *node_record = NULL;
775	ib_node_info_t *p_ni = NULL;
776	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(*node_record));
777	ib_api_status_t status;
778
779	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);
780	if (status != IB_SUCCESS)
781		return (status);
782
783	for (i = 0; i < result.result_cnt; i++) {
784		node_record = osmv_get_query_node_rec(result.p_result_madw, i);
785		p_ni = &(node_record->node_info);
786		if (name
787		    && strncmp(name, (char *)node_record->node_desc.description,
788			       sizeof(node_record->node_desc.description)) ==
789		    0) {
790			*lid = cl_ntoh16(node_record->lid);
791			break;
792		}
793	}
794	return_mad();
795	return (status);
796}
797
798static ib_net16_t get_lid(osm_bind_handle_t h, const char *name)
799{
800	ib_net16_t rc_lid = 0;
801
802	if (!name)
803		return (0);
804	if (isalpha(name[0]))
805		assert(get_lid_from_name(h, name, &rc_lid) == IB_SUCCESS);
806	else
807		rc_lid = atoi(name);
808	if (rc_lid == 0)
809		fprintf(stderr, "Failed to find lid for \"%s\"\n", name);
810	return (rc_lid);
811}
812
813static int parse_lid_and_ports(osm_bind_handle_t h,
814			       char *str, int *lid, int *port1, int *port2)
815{
816	char *p, *e;
817
818	if (port1)
819		*port1 = -1;
820	if (port2)
821		*port2 = -1;
822
823	p = strchr(str, '/');
824	if (p)
825		*p = '\0';
826	if (lid)
827		*lid = get_lid(h, str);
828
829	if (!p)
830		return 0;
831	str = p + 1;
832	p = strchr(str, '/');
833	if (p)
834		*p = '\0';
835	if (port1) {
836		*port1 = strtoul(str, &e, 0);
837		if (e == str)
838			*port1 = -1;
839	}
840
841	if (!p)
842		return 0;
843	str = p + 1;
844	if (port2) {
845		*port2 = strtoul(str, &e, 0);
846		if (e == str)
847			*port2 = -1;
848	}
849
850	return 0;
851}
852
853/*
854 * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.
855 */
856static ib_api_status_t
857get_issm_records(osm_bind_handle_t h, ib_net32_t capability_mask)
858{
859	ib_portinfo_record_t attr;
860
861	memset(&attr, 0, sizeof(attr));
862	attr.port_info.capability_mask = capability_mask;
863
864	return get_any_records(h, IB_MAD_ATTR_PORTINFO_RECORD,
865			       cl_hton32(1 << 31), IB_PIR_COMPMASK_CAPMASK,
866			       &attr,
867			       ib_get_attr_offset(sizeof(ib_portinfo_record_t)),
868			       0);
869}
870
871static ib_api_status_t print_node_records(osm_bind_handle_t h)
872{
873	int i = 0;
874	ib_node_record_t *node_record = NULL;
875	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(*node_record));
876	ib_api_status_t status;
877
878	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);
879	if (status != IB_SUCCESS)
880		return (status);
881
882	if (node_print_desc == ALL_DESC) {
883		printf("   LID \"name\"\n");
884		printf("================\n");
885	}
886	for (i = 0; i < result.result_cnt; i++) {
887		node_record = osmv_get_query_node_rec(result.p_result_madw, i);
888		if (node_print_desc == ALL_DESC) {
889			print_node_desc(node_record);
890		} else if (node_print_desc == NAME_OF_LID) {
891			if (requested_lid == cl_ntoh16(node_record->lid)) {
892				print_node_record(node_record);
893			}
894		} else if (node_print_desc == NAME_OF_GUID) {
895			ib_node_info_t *p_ni = &(node_record->node_info);
896
897			if (requested_guid == cl_ntoh64(p_ni->port_guid)) {
898				print_node_record(node_record);
899			}
900		} else {
901			if (!requested_name ||
902			    (strncmp(requested_name,
903				     (char *)node_record->node_desc.description,
904				     sizeof(node_record->node_desc.
905					    description)) == 0)) {
906				print_node_record(node_record);
907				if (node_print_desc == UNIQUE_LID_ONLY) {
908					return_mad();
909					exit(0);
910				}
911			}
912		}
913	}
914	return_mad();
915	return (status);
916}
917
918static ib_api_status_t
919get_print_path_rec_lid(osm_bind_handle_t h,
920		       ib_net16_t src_lid, ib_net16_t dst_lid)
921{
922	osmv_query_req_t req;
923	osmv_lid_pair_t lid_pair;
924	ib_api_status_t status;
925
926	lid_pair.src_lid = cl_hton16(src_lid);
927	lid_pair.dest_lid = cl_hton16(dst_lid);
928
929	memset(&req, 0, sizeof(req));
930
931	req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;
932	req.timeout_ms = sa_timeout_ms;
933	req.retry_cnt = 1;
934	req.flags = OSM_SA_FLAGS_SYNC;
935	req.query_context = NULL;
936	req.pfn_query_cb = query_res_cb;
937	req.p_query_input = (void *)&lid_pair;
938	req.sm_key = 0;
939
940	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
941		fprintf(stderr, "ERROR: Query SA failed: %s\n",
942			ib_get_err_str(status));
943		return (status);
944	}
945	if (result.status != IB_SUCCESS) {
946		fprintf(stderr, "ERROR: Query result returned: %s\n",
947			ib_get_err_str(result.status));
948		return (result.status);
949	}
950	status = result.status;
951	dump_results(&result, dump_path_record);
952	return_mad();
953	return (status);
954}
955
956static ib_api_status_t
957get_print_path_rec_gid(osm_bind_handle_t h,
958		       const ib_gid_t * src_gid, const ib_gid_t * dst_gid)
959{
960	osmv_query_req_t req;
961	osmv_gid_pair_t gid_pair;
962	ib_api_status_t status;
963
964	gid_pair.src_gid = *src_gid;
965	gid_pair.dest_gid = *dst_gid;
966
967	memset(&req, 0, sizeof(req));
968
969	req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;
970	req.timeout_ms = sa_timeout_ms;
971	req.retry_cnt = 1;
972	req.flags = OSM_SA_FLAGS_SYNC;
973	req.query_context = NULL;
974	req.pfn_query_cb = query_res_cb;
975	req.p_query_input = (void *)&gid_pair;
976	req.sm_key = 0;
977
978	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
979		fprintf(stderr, "ERROR: Query SA failed: %s\n",
980			ib_get_err_str(status));
981		return (status);
982	}
983	if (result.status != IB_SUCCESS) {
984		fprintf(stderr, "ERROR: Query result returned: %s\n",
985			ib_get_err_str(result.status));
986		return (result.status);
987	}
988	status = result.status;
989	dump_results(&result, dump_path_record);
990	return_mad();
991	return (status);
992}
993
994static ib_api_status_t get_print_class_port_info(osm_bind_handle_t h)
995{
996	osmv_query_req_t req;
997	ib_api_status_t status;
998
999	memset(&req, 0, sizeof(req));
1000
1001	req.query_type = OSMV_QUERY_CLASS_PORT_INFO;
1002	req.timeout_ms = sa_timeout_ms;
1003	req.retry_cnt = 1;
1004	req.flags = OSM_SA_FLAGS_SYNC;
1005	req.query_context = NULL;
1006	req.pfn_query_cb = query_res_cb;
1007	req.p_query_input = NULL;
1008	req.sm_key = 0;
1009
1010	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
1011		fprintf(stderr, "ERROR: Query SA failed: %s\n",
1012			ib_get_err_str(status));
1013		return (status);
1014	}
1015	if (result.status != IB_SUCCESS) {
1016		fprintf(stderr, "ERROR: Query result returned: %s\n",
1017			ib_get_err_str(result.status));
1018		return (result.status);
1019	}
1020	status = result.status;
1021	dump_results(&result, dump_class_port_info);
1022	return_mad();
1023	return (status);
1024}
1025
1026static int query_path_records(const struct query_cmd *q,
1027			      osm_bind_handle_t h, int argc, char *argv[])
1028{
1029	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(ib_path_rec_t));
1030	ib_api_status_t status;
1031
1032	status = get_all_records(h, IB_MAD_ATTR_PATH_RECORD, attr_offset, 0);
1033	if (status != IB_SUCCESS)
1034		return (status);
1035
1036	dump_results(&result, dump_path_record);
1037	return_mad();
1038	return (status);
1039}
1040
1041static ib_api_status_t print_issm_records(osm_bind_handle_t h)
1042{
1043	ib_api_status_t status;
1044
1045	/* First, get IsSM records */
1046	status = get_issm_records(h, IB_PORT_CAP_IS_SM);
1047	if (status != IB_SUCCESS)
1048		return (status);
1049
1050	printf("IsSM ports\n");
1051	dump_results(&result, dump_portinfo_record);
1052	return_mad();
1053
1054	/* Now, get IsSMdisabled records */
1055	status = get_issm_records(h, IB_PORT_CAP_SM_DISAB);
1056	if (status != IB_SUCCESS)
1057		return (status);
1058
1059	printf("\nIsSMdisabled ports\n");
1060	dump_results(&result, dump_portinfo_record);
1061	return_mad();
1062
1063	return (status);
1064}
1065
1066static ib_api_status_t print_multicast_member_records(osm_bind_handle_t h)
1067{
1068	osmv_query_res_t mc_group_result;
1069	ib_api_status_t status;
1070
1071	status = get_all_records(h, IB_MAD_ATTR_MCMEMBER_RECORD,
1072				 ib_get_attr_offset(sizeof(ib_member_rec_t)),
1073				 1);
1074	if (status != IB_SUCCESS)
1075		return (status);
1076
1077	mc_group_result = result;
1078
1079	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD,
1080				 ib_get_attr_offset(sizeof(ib_node_record_t)),
1081				 0);
1082	if (status != IB_SUCCESS)
1083		goto return_mc;
1084
1085	dump_results(&mc_group_result, dump_multicast_member_record);
1086	return_mad();
1087
1088return_mc:
1089	/* return_mad for the mc_group_result */
1090	if (mc_group_result.p_result_madw != NULL) {
1091		osm_mad_pool_put(&mad_pool, mc_group_result.p_result_madw);
1092		mc_group_result.p_result_madw = NULL;
1093	}
1094
1095	return (status);
1096}
1097
1098static ib_api_status_t print_multicast_group_records(osm_bind_handle_t h)
1099{
1100	ib_api_status_t status;
1101
1102	status = get_all_records(h, IB_MAD_ATTR_MCMEMBER_RECORD,
1103				 ib_get_attr_offset(sizeof(ib_member_rec_t)),
1104				 0);
1105	if (status != IB_SUCCESS)
1106		return (status);
1107
1108	dump_results(&result, dump_multicast_group_record);
1109	return_mad();
1110	return (status);
1111}
1112
1113static int query_class_port_info(const struct query_cmd *q,
1114				 osm_bind_handle_t h, int argc, char *argv[])
1115{
1116	return get_print_class_port_info(h);
1117}
1118
1119static int query_node_records(const struct query_cmd *q,
1120			      osm_bind_handle_t h, int argc, char *argv[])
1121{
1122	return print_node_records(h);
1123}
1124
1125static int query_portinfo_records(const struct query_cmd *q,
1126				  osm_bind_handle_t h, int argc, char *argv[])
1127{
1128	ib_portinfo_record_t pir;
1129	ib_net64_t comp_mask = 0;
1130	int lid = 0, port = -1;
1131	ib_api_status_t status;
1132
1133	if (argc > 0)
1134		parse_lid_and_ports(h, argv[0], &lid, &port, NULL);
1135
1136	memset(&pir, 0, sizeof(pir));
1137
1138	if (lid > 0) {
1139		pir.lid = cl_hton16(lid);
1140		comp_mask |= IB_PIR_COMPMASK_LID;
1141	}
1142	if (port >= 0) {
1143		pir.port_num = cl_hton16(port);
1144		comp_mask |= IB_PIR_COMPMASK_PORTNUM;
1145	}
1146
1147	status = get_any_records(h, IB_MAD_ATTR_PORTINFO_RECORD, 0,
1148				 comp_mask, &pir,
1149				 ib_get_attr_offset(sizeof(pir)), 0);
1150
1151	if (status != IB_SUCCESS)
1152		return status;
1153
1154	dump_results(&result, dump_one_portinfo_record);
1155	return_mad();
1156
1157	return 0;
1158}
1159
1160static int query_mcmember_records(const struct query_cmd *q,
1161				   osm_bind_handle_t h, int argc, char *argv[])
1162{
1163	return print_multicast_member_records(h);
1164}
1165
1166static int query_service_records(const struct query_cmd *q,
1167				 osm_bind_handle_t h, int argc, char *argv[])
1168{
1169	ib_net16_t attr_offset =
1170	    ib_get_attr_offset(sizeof(ib_service_record_t));
1171	ib_api_status_t status;
1172
1173	status = get_all_records(h, IB_MAD_ATTR_SERVICE_RECORD, attr_offset, 0);
1174	if (status != IB_SUCCESS)
1175		return (status);
1176
1177	dump_results(&result, dump_service_record);
1178	return_mad();
1179	return (status);
1180}
1181
1182static int query_informinfo_records(const struct query_cmd *q,
1183				    osm_bind_handle_t h, int argc, char *argv[])
1184{
1185	ib_net16_t attr_offset =
1186	    ib_get_attr_offset(sizeof(ib_inform_info_record_t));
1187	ib_api_status_t status;
1188
1189	status =
1190	    get_all_records(h, IB_MAD_ATTR_INFORM_INFO_RECORD, attr_offset, 0);
1191	if (status != IB_SUCCESS)
1192		return (status);
1193
1194	dump_results(&result, dump_inform_info_record);
1195	return_mad();
1196	return (status);
1197}
1198
1199static int query_link_records(const struct query_cmd *q,
1200			      osm_bind_handle_t h, int argc, char *argv[])
1201{
1202	ib_link_record_t lr;
1203	ib_net64_t comp_mask = 0;
1204	int from_lid = 0, to_lid = 0, from_port = -1, to_port = -1;
1205	ib_api_status_t status;
1206
1207	if (argc > 0)
1208		parse_lid_and_ports(h, argv[0], &from_lid, &from_port, NULL);
1209
1210	if (argc > 1)
1211		parse_lid_and_ports(h, argv[1], &to_lid, &to_port, NULL);
1212
1213	memset(&lr, 0, sizeof(lr));
1214
1215	if (from_lid > 0) {
1216		lr.from_lid = cl_hton16(from_lid);
1217		comp_mask |= IB_LR_COMPMASK_FROM_LID;
1218	}
1219	if (from_port >= 0) {
1220		lr.from_port_num = from_port;
1221		comp_mask |= IB_LR_COMPMASK_FROM_PORT;
1222	}
1223	if (to_lid > 0) {
1224		lr.to_lid = cl_hton16(to_lid);
1225		comp_mask |= IB_LR_COMPMASK_TO_LID;
1226	}
1227	if (to_port >= 0) {
1228		lr.to_port_num = to_port;
1229		comp_mask |= IB_LR_COMPMASK_TO_PORT;
1230	}
1231
1232	status = get_any_records(h, IB_MAD_ATTR_LINK_RECORD, 0,
1233				 comp_mask, &lr,
1234				 ib_get_attr_offset(sizeof(lr)), 0);
1235	if (status != IB_SUCCESS)
1236		return status;
1237
1238	dump_results(&result, dump_one_link_record);
1239	return_mad();
1240	return status;
1241}
1242
1243static int query_sl2vl_records(const struct query_cmd *q,
1244			       osm_bind_handle_t h, int argc, char *argv[])
1245{
1246	ib_slvl_table_record_t slvl;
1247	ib_net64_t comp_mask = 0;
1248	int lid = 0, in_port = -1, out_port = -1;
1249	ib_api_status_t status;
1250
1251	if (argc > 0)
1252		parse_lid_and_ports(h, argv[0], &lid, &in_port, &out_port);
1253
1254	memset(&slvl, 0, sizeof(slvl));
1255
1256	if (lid > 0) {
1257		slvl.lid = cl_hton16(lid);
1258		comp_mask |= IB_SLVL_COMPMASK_LID;
1259	}
1260	if (in_port >= 0) {
1261		slvl.in_port_num = in_port;
1262		comp_mask |= IB_SLVL_COMPMASK_IN_PORT;
1263	}
1264	if (out_port >= 0) {
1265		slvl.out_port_num = out_port;
1266		comp_mask |= IB_SLVL_COMPMASK_OUT_PORT;
1267	}
1268
1269	status = get_any_records(h, IB_MAD_ATTR_SLVL_RECORD, 0,
1270				 comp_mask, &slvl,
1271				 ib_get_attr_offset(sizeof(slvl)), 0);
1272	if (status != IB_SUCCESS)
1273		return status;
1274
1275	dump_results(&result, dump_one_slvl_record);
1276	return_mad();
1277	return status;
1278}
1279
1280static int query_vlarb_records(const struct query_cmd *q,
1281			       osm_bind_handle_t h, int argc, char *argv[])
1282{
1283	ib_vl_arb_table_record_t vlarb;
1284	ib_net64_t comp_mask = 0;
1285	int lid = 0, port = -1, block = -1;
1286	ib_api_status_t status;
1287
1288	if (argc > 0)
1289		parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1290
1291	memset(&vlarb, 0, sizeof(vlarb));
1292
1293	if (lid > 0) {
1294		vlarb.lid = cl_hton16(lid);
1295		comp_mask |= IB_VLA_COMPMASK_LID;
1296	}
1297	if (port >= 0) {
1298		vlarb.port_num = port;
1299		comp_mask |= IB_VLA_COMPMASK_OUT_PORT;
1300	}
1301	if (block >= 0) {
1302		vlarb.block_num = block;
1303		comp_mask |= IB_VLA_COMPMASK_BLOCK;
1304	}
1305
1306	status = get_any_records(h, IB_MAD_ATTR_VLARB_RECORD, 0,
1307				 comp_mask, &vlarb,
1308				 ib_get_attr_offset(sizeof(vlarb)), 0);
1309	if (status != IB_SUCCESS)
1310		return status;
1311
1312	dump_results(&result, dump_one_vlarb_record);
1313	return_mad();
1314	return status;
1315}
1316
1317static int query_pkey_tbl_records(const struct query_cmd *q,
1318				  osm_bind_handle_t h, int argc, char *argv[])
1319{
1320	ib_pkey_table_record_t pktr;
1321	ib_net64_t comp_mask = 0;
1322	int lid = 0, port = -1, block = -1;
1323	ib_api_status_t status;
1324
1325	if (argc > 0)
1326		parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1327
1328	memset(&pktr, 0, sizeof(pktr));
1329
1330	if (lid > 0) {
1331		pktr.lid = cl_hton16(lid);
1332		comp_mask |= IB_PKEY_COMPMASK_LID;
1333	}
1334	if (port >= 0) {
1335		pktr.port_num = port;
1336		comp_mask |= IB_PKEY_COMPMASK_PORT;
1337	}
1338	if (block >= 0) {
1339		pktr.block_num = block;
1340		comp_mask |= IB_PKEY_COMPMASK_BLOCK;
1341	}
1342
1343	status = get_any_records(h, IB_MAD_ATTR_PKEY_TBL_RECORD, 0,
1344				 comp_mask, &pktr,
1345				 ib_get_attr_offset(sizeof(pktr)), smkey);
1346	if (status != IB_SUCCESS)
1347		return status;
1348
1349	dump_results(&result, dump_one_pkey_tbl_record);
1350	return_mad();
1351	return status;
1352}
1353
1354static int query_lft_records(const struct query_cmd *q,
1355			     osm_bind_handle_t h, int argc, char *argv[])
1356{
1357	ib_lft_record_t lftr;
1358	ib_net64_t comp_mask = 0;
1359	int lid = 0, block = -1;
1360	ib_api_status_t status;
1361
1362	if (argc > 0)
1363		parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
1364
1365	memset(&lftr, 0, sizeof(lftr));
1366
1367	if (lid > 0) {
1368		lftr.lid = cl_hton16(lid);
1369		comp_mask |= IB_LFTR_COMPMASK_LID;
1370	}
1371	if (block >= 0) {
1372		lftr.block_num = cl_hton16(block);
1373		comp_mask |= IB_LFTR_COMPMASK_BLOCK;
1374	}
1375
1376	status = get_any_records(h, IB_MAD_ATTR_LFT_RECORD, 0,
1377				 comp_mask, &lftr,
1378				 ib_get_attr_offset(sizeof(lftr)), 0);
1379	if (status != IB_SUCCESS)
1380		return status;
1381
1382	dump_results(&result, dump_one_lft_record);
1383	return_mad();
1384	return status;
1385}
1386
1387static int query_mft_records(const struct query_cmd *q,
1388			     osm_bind_handle_t h, int argc, char *argv[])
1389{
1390	ib_mft_record_t mftr;
1391	ib_net64_t comp_mask = 0;
1392	int lid = 0, block = -1, position = -1;
1393	ib_api_status_t status;
1394
1395	if (argc > 0)
1396		parse_lid_and_ports(h, argv[0], &lid, &position, &block);
1397
1398	memset(&mftr, 0, sizeof(mftr));
1399
1400	if (lid > 0) {
1401		mftr.lid = cl_hton16(lid);
1402		comp_mask |= IB_MFTR_COMPMASK_LID;
1403	}
1404	if (position >= 0) {
1405		mftr.position_block_num = cl_hton16(position << 12);
1406		comp_mask |= IB_MFTR_COMPMASK_POSITION;
1407	}
1408	if (block >= 0) {
1409		mftr.position_block_num |=
1410		    cl_hton16(block & IB_MCAST_BLOCK_ID_MASK_HO);
1411		comp_mask |= IB_MFTR_COMPMASK_BLOCK;
1412	}
1413
1414	status = get_any_records(h, IB_MAD_ATTR_MFT_RECORD, 0,
1415				 comp_mask, &mftr,
1416				 ib_get_attr_offset(sizeof(mftr)), 0);
1417	if (status != IB_SUCCESS)
1418		return status;
1419
1420	dump_results(&result, dump_one_mft_record);
1421	return_mad();
1422	return status;
1423}
1424
1425static osm_bind_handle_t get_bind_handle(void)
1426{
1427	uint32_t i = 0;
1428	uint64_t port_guid = (uint64_t) - 1;
1429	osm_bind_handle_t h;
1430	ib_api_status_t status;
1431	ib_port_attr_t attr_array[MAX_PORTS];
1432	uint32_t num_ports = MAX_PORTS;
1433	uint32_t ca_name_index = 0;
1434
1435	complib_init();
1436
1437	osm_log_construct(&log_osm);
1438	if ((status = osm_log_init_v2(&log_osm, TRUE, 0x0001, NULL,
1439				      0, TRUE)) != IB_SUCCESS) {
1440		fprintf(stderr, "Failed to init osm_log: %s\n",
1441			ib_get_err_str(status));
1442		exit(-1);
1443	}
1444	osm_log_set_level(&log_osm, OSM_LOG_NONE);
1445	if (osm_debug)
1446		osm_log_set_level(&log_osm, OSM_LOG_DEFAULT_LEVEL);
1447
1448	vendor = osm_vendor_new(&log_osm, sa_timeout_ms);
1449	osm_mad_pool_construct(&mad_pool);
1450	if ((status = osm_mad_pool_init(&mad_pool)) != IB_SUCCESS) {
1451		fprintf(stderr, "Failed to init mad pool: %s\n",
1452			ib_get_err_str(status));
1453		exit(-1);
1454	}
1455
1456	if ((status =
1457	     osm_vendor_get_all_port_attr(vendor, attr_array,
1458					  &num_ports)) != IB_SUCCESS) {
1459		fprintf(stderr, "Failed to get port attributes: %s\n",
1460			ib_get_err_str(status));
1461		exit(-1);
1462	}
1463
1464	for (i = 0; i < num_ports; i++) {
1465		if (i > 1 && cl_ntoh64(attr_array[i].port_guid)
1466		    != (cl_ntoh64(attr_array[i - 1].port_guid) + 1))
1467			ca_name_index++;
1468		if (sa_port_num && sa_port_num != attr_array[i].port_num)
1469			continue;
1470		if (sa_hca_name
1471		    && strcmp(sa_hca_name,
1472			      vendor->ca_names[ca_name_index]) != 0)
1473			continue;
1474		if (attr_array[i].link_state == IB_LINK_ACTIVE) {
1475			port_guid = attr_array[i].port_guid;
1476			break;
1477		}
1478	}
1479
1480	if (port_guid == (uint64_t) - 1) {
1481		fprintf(stderr,
1482			"Failed to find active port, check port status with \"ibstat\"\n");
1483		exit(-1);
1484	}
1485
1486	h = osmv_bind_sa(vendor, &mad_pool, port_guid);
1487
1488	if (h == OSM_BIND_INVALID_HANDLE) {
1489		fprintf(stderr, "Failed to bind to SA\n");
1490		exit(-1);
1491	}
1492	return h;
1493}
1494
1495static void clean_up(void)
1496{
1497	osm_mad_pool_destroy(&mad_pool);
1498	osm_vendor_delete(&vendor);
1499}
1500
1501static const struct query_cmd query_cmds[] = {
1502	{"ClassPortInfo", "CPI", IB_MAD_ATTR_CLASS_PORT_INFO,
1503	 NULL, query_class_port_info},
1504	{"NodeRecord", "NR", IB_MAD_ATTR_NODE_RECORD,
1505	 NULL, query_node_records},
1506	{"PortInfoRecord", "PIR", IB_MAD_ATTR_PORTINFO_RECORD,
1507	 "[[lid]/[port]]", query_portinfo_records},
1508	{"SL2VLTableRecord", "SL2VL", IB_MAD_ATTR_SLVL_RECORD,
1509	 "[[lid]/[in_port]/[out_port]]", query_sl2vl_records},
1510	{"PKeyTableRecord", "PKTR", IB_MAD_ATTR_PKEY_TBL_RECORD,
1511	 "[[lid]/[port]/[block]]", query_pkey_tbl_records},
1512	{"VLArbitrationTableRecord", "VLAR", IB_MAD_ATTR_VLARB_RECORD,
1513	 "[[lid]/[port]/[block]]", query_vlarb_records},
1514	{"InformInfoRecord", "IIR", IB_MAD_ATTR_INFORM_INFO_RECORD,
1515	 NULL, query_informinfo_records},
1516	{"LinkRecord", "LR", IB_MAD_ATTR_LINK_RECORD,
1517	 "[[from_lid]/[from_port]] [[to_lid]/[to_port]]", query_link_records},
1518	{"ServiceRecord", "SR", IB_MAD_ATTR_SERVICE_RECORD,
1519	 NULL, query_service_records},
1520	{"PathRecord", "PR", IB_MAD_ATTR_PATH_RECORD,
1521	 NULL, query_path_records},
1522	{"MCMemberRecord", "MCMR", IB_MAD_ATTR_MCMEMBER_RECORD,
1523	 NULL, query_mcmember_records},
1524	{"LFTRecord", "LFTR", IB_MAD_ATTR_LFT_RECORD,
1525	 "[[lid]/[block]]", query_lft_records},
1526	{"MFTRecord", "MFTR", IB_MAD_ATTR_MFT_RECORD,
1527	 "[[mlid]/[position]/[block]]", query_mft_records},
1528	{0}
1529};
1530
1531static const struct query_cmd *find_query(const char *name)
1532{
1533	const struct query_cmd *q;
1534	unsigned len = strlen(name);
1535
1536	for (q = query_cmds; q->name; q++)
1537		if (!strncasecmp(name, q->name, len) ||
1538		    (q->alias && !strncasecmp(name, q->alias, len)))
1539			return q;
1540
1541	return NULL;
1542}
1543
1544static const struct query_cmd *find_query_by_type(ib_net16_t type)
1545{
1546	const struct query_cmd *q;
1547
1548	for (q = query_cmds; q->name; q++)
1549		if (q->query_type == type)
1550			return q;
1551
1552	return NULL;
1553}
1554
1555static void usage(void)
1556{
1557	const struct query_cmd *q;
1558
1559	fprintf(stderr, "Usage: %s [-h -d -p -N] [--list | -D] [-S -I -L -l -G"
1560		" -O -U -c -s -g -m --src-to-dst <src:dst> --sgid-to-dgid <src-dst> "
1561		"-C <ca_name> -P <ca_port> -t(imeout) <msec>] [query-name] [<name> | <lid> | <guid>]\n",
1562		argv0);
1563	fprintf(stderr, "   Queries node records by default\n");
1564	fprintf(stderr, "   -d enable debugging\n");
1565	fprintf(stderr, "   -p get PathRecord info\n");
1566	fprintf(stderr, "   -N get NodeRecord info\n");
1567	fprintf(stderr, "   --list | -D the node desc of the CA's\n");
1568	fprintf(stderr, "   -S get ServiceRecord info\n");
1569	fprintf(stderr, "   -I get InformInfoRecord (subscription) info\n");
1570	fprintf(stderr, "   -L return the Lids of the name specified\n");
1571	fprintf(stderr, "   -l return the unique Lid of the name specified\n");
1572	fprintf(stderr, "   -G return the Guids of the name specified\n");
1573	fprintf(stderr, "   -O return name for the Lid specified\n");
1574	fprintf(stderr, "   -U return name for the Guid specified\n");
1575	fprintf(stderr, "   -c get the SA's class port info\n");
1576	fprintf(stderr, "   -s return the PortInfoRecords with isSM or "
1577		"isSMdisabled capability mask bit on\n");
1578	fprintf(stderr, "   -g get multicast group info\n");
1579	fprintf(stderr, "   -m get multicast member info\n");
1580	fprintf(stderr, "      (if multicast group specified, list member GIDs"
1581		" only for group specified\n");
1582	fprintf(stderr, "      specified, for example 'saquery -m 0xC000')\n");
1583	fprintf(stderr, "   -x get LinkRecord info\n");
1584	fprintf(stderr, "   --src-to-dst get a PathRecord for <src:dst>\n"
1585		"                where src and dst are either node "
1586		"names or LIDs\n");
1587	fprintf(stderr, "   --sgid-to-dgid get a PathRecord for <sgid-dgid>\n"
1588		"                where sgid and dgid are addresses in "
1589		"IPv6 format\n");
1590	fprintf(stderr, "   -C <ca_name> specify the SA query HCA\n");
1591	fprintf(stderr, "   -P <ca_port> specify the SA query port\n");
1592	fprintf(stderr, "   --smkey <val> specify SM_Key value for the query."
1593		" If non-numeric value \n"
1594		"                 (like 'x') is specified then "
1595		"saquery will prompt for a value\n");
1596	fprintf(stderr, "   -t | --timeout <msec> specify the SA query "
1597		"response timeout (default %u msec)\n", DEFAULT_SA_TIMEOUT_MS);
1598	fprintf(stderr,
1599		"   --node-name-map <node-name-map> specify a node name map\n");
1600	fprintf(stderr, "\n   Supported query names (and aliases):\n");
1601	for (q = query_cmds; q->name; q++)
1602		fprintf(stderr, "      %s (%s) %s\n", q->name,
1603			q->alias ? q->alias : "", q->usage ? q->usage : "");
1604	fprintf(stderr, "\n");
1605
1606	exit(-1);
1607}
1608
1609enum saquery_command {
1610	SAQUERY_CMD_QUERY,
1611	SAQUERY_CMD_NODE_RECORD,
1612	SAQUERY_CMD_PATH_RECORD,
1613	SAQUERY_CMD_CLASS_PORT_INFO,
1614	SAQUERY_CMD_ISSM,
1615	SAQUERY_CMD_MCGROUPS,
1616	SAQUERY_CMD_MCMEMBERS,
1617};
1618
1619int main(int argc, char **argv)
1620{
1621	int ch = 0;
1622	osm_bind_handle_t h;
1623	enum saquery_command command = SAQUERY_CMD_QUERY;
1624	const struct query_cmd *q = NULL;
1625	char *src = NULL, *dst = NULL;
1626	char *sgid = NULL, *dgid = NULL;
1627	ib_net16_t query_type = 0;
1628	ib_net16_t src_lid, dst_lid;
1629	ib_api_status_t status;
1630
1631	static char const str_opts[] = "pVNDLlGOUcSIsgmxdhP:C:t:";
1632	static const struct option long_opts[] = {
1633		{"p", 0, 0, 'p'},
1634		{"Version", 0, 0, 'V'},
1635		{"N", 0, 0, 'N'},
1636		{"L", 0, 0, 'L'},
1637		{"l", 0, 0, 'l'},
1638		{"G", 0, 0, 'G'},
1639		{"O", 0, 0, 'O'},
1640		{"U", 0, 0, 'U'},
1641		{"s", 0, 0, 's'},
1642		{"g", 0, 0, 'g'},
1643		{"m", 0, 0, 'm'},
1644		{"x", 0, 0, 'x'},
1645		{"d", 0, 0, 'd'},
1646		{"c", 0, 0, 'c'},
1647		{"S", 0, 0, 'S'},
1648		{"I", 0, 0, 'I'},
1649		{"P", 1, 0, 'P'},
1650		{"C", 1, 0, 'C'},
1651		{"help", 0, 0, 'h'},
1652		{"list", 0, 0, 'D'},
1653		{"src-to-dst", 1, 0, 1},
1654		{"sgid-to-dgid", 1, 0, 2},
1655		{"timeout", 1, 0, 't'},
1656		{"node-name-map", 1, 0, 3},
1657		{"smkey", 1, 0, 4},
1658		{}
1659	};
1660
1661	argv0 = argv[0];
1662
1663	while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL)) != -1) {
1664		switch (ch) {
1665		case 1:
1666			{
1667				char *opt = strdup(optarg);
1668				char *ch = strchr(opt, ':');
1669				if (!ch) {
1670					fprintf(stderr,
1671						"ERROR: --src-to-dst <node>:<node>\n");
1672					usage();
1673				}
1674				*ch++ = '\0';
1675				if (*opt)
1676					src = strdup(opt);
1677				if (*ch)
1678					dst = strdup(ch);
1679				free(opt);
1680				command = SAQUERY_CMD_PATH_RECORD;
1681				break;
1682			}
1683		case 2:
1684			{
1685				char *opt = strdup(optarg);
1686				char *tok1 = strtok(opt, "-");
1687				char *tok2 = strtok(NULL, "\0");
1688
1689				if (tok1 && tok2) {
1690					sgid = strdup(tok1);
1691					dgid = strdup(tok2);
1692				} else {
1693					fprintf(stderr,
1694						"ERROR: --sgid-to-dgid <GID>-<GID>\n");
1695					usage();
1696				}
1697				free(opt);
1698				command = SAQUERY_CMD_PATH_RECORD;
1699				break;
1700			}
1701		case 3:
1702			node_name_map_file = strdup(optarg);
1703			break;
1704		case 4:
1705			if (!isxdigit(*optarg) &&
1706			    !(optarg = getpass("SM_Key: "))) {
1707				fprintf(stderr, "cannot get SM_Key\n");
1708				usage();
1709			}
1710			smkey = cl_hton64(strtoull(optarg, NULL, 0));
1711			break;
1712		case 'p':
1713			command = SAQUERY_CMD_PATH_RECORD;
1714			break;
1715		case 'V':
1716			fprintf(stderr, "%s %s\n", argv0, get_build_version());
1717			exit(-1);
1718		case 'D':
1719			node_print_desc = ALL_DESC;
1720			break;
1721		case 'c':
1722			command = SAQUERY_CMD_CLASS_PORT_INFO;
1723			break;
1724		case 'S':
1725			query_type = IB_MAD_ATTR_SERVICE_RECORD;
1726			break;
1727		case 'I':
1728			query_type = IB_MAD_ATTR_INFORM_INFO_RECORD;
1729			break;
1730		case 'N':
1731			command = SAQUERY_CMD_NODE_RECORD;
1732			break;
1733		case 'L':
1734			node_print_desc = LID_ONLY;
1735			break;
1736		case 'l':
1737			node_print_desc = UNIQUE_LID_ONLY;
1738			break;
1739		case 'G':
1740			node_print_desc = GUID_ONLY;
1741			break;
1742		case 'O':
1743			node_print_desc = NAME_OF_LID;
1744			break;
1745		case 'U':
1746			node_print_desc = NAME_OF_GUID;
1747			break;
1748		case 's':
1749			command = SAQUERY_CMD_ISSM;
1750			break;
1751		case 'g':
1752			command = SAQUERY_CMD_MCGROUPS;
1753			break;
1754		case 'm':
1755			command = SAQUERY_CMD_MCMEMBERS;
1756			break;
1757		case 'x':
1758			query_type = IB_MAD_ATTR_LINK_RECORD;
1759			break;
1760		case 'd':
1761			osm_debug = 1;
1762			break;
1763		case 'C':
1764			sa_hca_name = optarg;
1765			break;
1766		case 'P':
1767			sa_port_num = strtoul(optarg, NULL, 0);
1768			break;
1769		case 't':
1770			sa_timeout_ms = strtoul(optarg, NULL, 0);
1771			break;
1772		case 'h':
1773		default:
1774			usage();
1775		}
1776	}
1777	argc -= optind;
1778	argv += optind;
1779
1780	if (!query_type) {
1781		if (!argc || !(q = find_query(argv[0])))
1782			query_type = IB_MAD_ATTR_NODE_RECORD;
1783		else {
1784			query_type = q->query_type;
1785			argc--;
1786			argv++;
1787		}
1788	}
1789
1790	if (argc) {
1791		if (node_print_desc == NAME_OF_LID) {
1792			requested_lid = (ib_net16_t) strtoul(argv[0], NULL, 0);
1793			requested_lid_flag++;
1794		} else if (node_print_desc == NAME_OF_GUID) {
1795			requested_guid = (ib_net64_t) strtoul(argv[0], NULL, 0);
1796			requested_guid_flag++;
1797		} else {
1798			requested_name = argv[0];
1799		}
1800	}
1801
1802	if ((node_print_desc == LID_ONLY ||
1803	     node_print_desc == UNIQUE_LID_ONLY ||
1804	     node_print_desc == GUID_ONLY) && !requested_name) {
1805		fprintf(stderr, "ERROR: name not specified\n");
1806		usage();
1807	}
1808
1809	if (node_print_desc == NAME_OF_LID && !requested_lid_flag) {
1810		fprintf(stderr, "ERROR: lid not specified\n");
1811		usage();
1812	}
1813
1814	if (node_print_desc == NAME_OF_GUID && !requested_guid_flag) {
1815		fprintf(stderr, "ERROR: guid not specified\n");
1816		usage();
1817	}
1818
1819	/* Note: lid cannot be 0; see infiniband spec 4.1.3 */
1820	if (node_print_desc == NAME_OF_LID && !requested_lid) {
1821		fprintf(stderr, "ERROR: lid invalid\n");
1822		usage();
1823	}
1824
1825	h = get_bind_handle();
1826	node_name_map = open_node_name_map(node_name_map_file);
1827
1828	switch (command) {
1829	case SAQUERY_CMD_NODE_RECORD:
1830		status = print_node_records(h);
1831		break;
1832	case SAQUERY_CMD_PATH_RECORD:
1833		if (src && dst) {
1834			src_lid = get_lid(h, src);
1835			dst_lid = get_lid(h, dst);
1836			printf("Path record for %s -> %s\n", src, dst);
1837			if (src_lid == 0 || dst_lid == 0) {
1838				status = IB_UNKNOWN_ERROR;
1839			} else {
1840				status =
1841				    get_print_path_rec_lid(h, src_lid, dst_lid);
1842			}
1843		} else if (sgid && dgid) {
1844			struct in6_addr src_addr, dst_addr;
1845
1846			if (inet_pton(AF_INET6, sgid, &src_addr) <= 0) {
1847				fprintf(stderr, "invalid src gid: %s\n", sgid);
1848				exit(-1);
1849			}
1850			if (inet_pton(AF_INET6, dgid, &dst_addr) <= 0) {
1851				fprintf(stderr, "invalid dst gid: %s\n", dgid);
1852				exit(-1);
1853			}
1854			status = get_print_path_rec_gid(h,
1855					(ib_gid_t *) & src_addr.s6_addr,
1856					(ib_gid_t *) & dst_addr.s6_addr);
1857		} else {
1858			status = query_path_records(q, h, 0, NULL);
1859		}
1860		break;
1861	case SAQUERY_CMD_CLASS_PORT_INFO:
1862		status = get_print_class_port_info(h);
1863		break;
1864	case SAQUERY_CMD_ISSM:
1865		status = print_issm_records(h);
1866		break;
1867	case SAQUERY_CMD_MCGROUPS:
1868		status = print_multicast_group_records(h);
1869		break;
1870	case SAQUERY_CMD_MCMEMBERS:
1871		status = print_multicast_member_records(h);
1872		break;
1873	default:
1874		if ((!q && !(q = find_query_by_type(query_type)))
1875		    || !q->handler) {
1876			fprintf(stderr, "Unknown query type %d\n",
1877				ntohs(query_type));
1878			status = IB_UNKNOWN_ERROR;
1879		} else
1880			status = q->handler(q, h, argc, argv);
1881		break;
1882	}
1883
1884	if (src)
1885		free(src);
1886	if (dst)
1887		free(dst);
1888	clean_up();
1889	close_node_name_map(node_name_map);
1890	return (status);
1891}
1892