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