xref: /NextBSD/contrib/ofed/management/infiniband-diags/src/saquery.c (revision 65145fa4c81da358fcbc3b650156dab705dfa34e)
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 
64 struct 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 
72 char *argv0 = "saquery";
73 
74 static char *node_name_map_file = NULL;
75 static nn_map_t *node_name_map = NULL;
76 static 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)
83 osmv_query_res_t result;
84 osm_log_t log_osm;
85 osm_mad_pool_t mad_pool;
86 osm_vendor_t *vendor = NULL;
87 int osm_debug = 0;
88 uint32_t sa_timeout_ms = DEFAULT_SA_TIMEOUT_MS;
89 char *sa_hca_name = NULL;
90 uint32_t sa_port_num = 0;
91 
92 enum {
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 
102 char *requested_name = NULL;
103 ib_net16_t requested_lid = 0;
104 int requested_lid_flag = 0;
105 ib_net64_t requested_guid = 0;
106 int requested_guid_flag = 0;
107 
format_buf(char * in,char * out,unsigned size)108 static 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  */
query_res_cb(osmv_query_res_t * res)125 static void query_res_cb(osmv_query_res_t * res)
126 {
127 	result = *res;
128 }
129 
print_node_desc(ib_node_record_t * node_record)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 
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 
print_node_record(ib_node_record_t * node_record)142 static 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 
dump_path_record(void * data)207 static 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 
dump_class_port_info(void * data)250 static 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 
dump_portinfo_record(void * data)297 static 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 
dump_one_portinfo_record(void * data)317 static 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 
dump_multicast_group_record(void * data)336 static 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 
dump_multicast_member_record(void * data)355 static 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 
dump_service_record(void * data)403 static 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 
dump_inform_info_record(void * data)493 static 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 
dump_one_link_record(void * data)574 static 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 
dump_one_slvl_record(void * data)586 static 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 
dump_one_vlarb_record(void * data)608 static 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 
dump_one_pkey_tbl_record(void * data)637 static 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 
dump_one_lft_record(void * data)658 static 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 
dump_one_mft_record(void * data)672 static 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 }
dump_results(osmv_query_res_t * r,void (* dump_func)(void *))691 static 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 
return_mad(void)700 static 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  */
714 static ib_api_status_t
get_any_records(osm_bind_handle_t h,ib_net16_t attr_id,ib_net32_t attr_mod,ib_net64_t comp_mask,void * attr,ib_net16_t attr_offset,ib_net64_t sm_key)715 get_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  */
759 static ib_api_status_t
get_all_records(osm_bind_handle_t h,ib_net16_t query_id,ib_net16_t attr_offset,int trusted)760 get_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  */
770 static ib_api_status_t
get_lid_from_name(osm_bind_handle_t h,const char * name,ib_net16_t * lid)771 get_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 
get_lid(osm_bind_handle_t h,const char * name)798 static 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 
parse_lid_and_ports(osm_bind_handle_t h,char * str,int * lid,int * port1,int * port2)813 static 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  */
856 static ib_api_status_t
get_issm_records(osm_bind_handle_t h,ib_net32_t capability_mask)857 get_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 
print_node_records(osm_bind_handle_t h)871 static 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 
918 static ib_api_status_t
get_print_path_rec_lid(osm_bind_handle_t h,ib_net16_t src_lid,ib_net16_t dst_lid)919 get_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 
956 static ib_api_status_t
get_print_path_rec_gid(osm_bind_handle_t h,const ib_gid_t * src_gid,const ib_gid_t * dst_gid)957 get_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 
get_print_class_port_info(osm_bind_handle_t h)994 static 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 
query_path_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1026 static 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 
print_issm_records(osm_bind_handle_t h)1041 static 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 
print_multicast_member_records(osm_bind_handle_t h)1066 static 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 
1088 return_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 
print_multicast_group_records(osm_bind_handle_t h)1098 static 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 
query_class_port_info(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1113 static 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 
query_node_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1119 static 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 
query_portinfo_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1125 static 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 
query_mcmember_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1160 static 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 
query_service_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1166 static 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 
query_informinfo_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1182 static 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 
query_link_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1199 static 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 
query_sl2vl_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1243 static 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 
query_vlarb_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1280 static 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 
query_pkey_tbl_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1317 static 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 
query_lft_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1354 static 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 
query_mft_records(const struct query_cmd * q,osm_bind_handle_t h,int argc,char * argv[])1387 static 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 
get_bind_handle(void)1425 static 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 
clean_up(void)1495 static void clean_up(void)
1496 {
1497 	osm_mad_pool_destroy(&mad_pool);
1498 	osm_vendor_delete(&vendor);
1499 }
1500 
1501 static 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 
find_query(const char * name)1531 static 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 
find_query_by_type(ib_net16_t type)1544 static 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 
usage(void)1555 static 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 
1609 enum 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 
main(int argc,char ** argv)1619 int 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