1219820Sjeff/*
2219820Sjeff * Copyright (c) 2006,2007 The Regents of the University of California.
3219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
4219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
5219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6219820Sjeff *
7219820Sjeff * Produced at Lawrence Livermore National Laboratory.
8219820Sjeff * Written by Ira Weiny <weiny2@llnl.gov>.
9219820Sjeff *
10219820Sjeff * This software is available to you under a choice of one of two
11219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
12219820Sjeff * General Public License (GPL) Version 2, available from the file
13219820Sjeff * COPYING in the main directory of this source tree, or the
14219820Sjeff * OpenIB.org BSD license below:
15219820Sjeff *
16219820Sjeff *     Redistribution and use in source and binary forms, with or
17219820Sjeff *     without modification, are permitted provided that the following
18219820Sjeff *     conditions are met:
19219820Sjeff *
20219820Sjeff *      - Redistributions of source code must retain the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer.
23219820Sjeff *
24219820Sjeff *      - Redistributions in binary form must reproduce the above
25219820Sjeff *        copyright notice, this list of conditions and the following
26219820Sjeff *        disclaimer in the documentation and/or other materials
27219820Sjeff *        provided with the distribution.
28219820Sjeff *
29219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
33219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
34219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
35219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36219820Sjeff * SOFTWARE.
37219820Sjeff *
38219820Sjeff */
39219820Sjeff
40219820Sjeff#include <unistd.h>
41219820Sjeff#include <stdio.h>
42219820Sjeff#include <sys/types.h>
43219820Sjeff#include <sys/socket.h>
44219820Sjeff#include <arpa/inet.h>
45219820Sjeff#include <assert.h>
46219820Sjeff#include <ctype.h>
47219820Sjeff#include <string.h>
48219820Sjeff
49219820Sjeff#define _GNU_SOURCE
50219820Sjeff#include <getopt.h>
51219820Sjeff
52219820Sjeff#include <infiniband/mad.h>
53219820Sjeff#include <infiniband/opensm/osm_log.h>
54219820Sjeff#include <infiniband/vendor/osm_vendor_api.h>
55219820Sjeff#include <infiniband/vendor/osm_vendor_sa_api.h>
56219820Sjeff#include <infiniband/opensm/osm_mad_pool.h>
57219820Sjeff#include <infiniband/complib/cl_debug.h>
58219820Sjeff#include <infiniband/complib/cl_nodenamemap.h>
59219820Sjeff
60219820Sjeff#include <netinet/in.h>
61219820Sjeff
62219820Sjeff#include "ibdiag_common.h"
63219820Sjeff
64219820Sjeffstruct query_cmd {
65219820Sjeff	const char *name, *alias;
66219820Sjeff	ib_net16_t query_type;
67219820Sjeff	const char *usage;
68219820Sjeff	int (*handler) (const struct query_cmd * q, osm_bind_handle_t h,
69219820Sjeff			int argc, char *argv[]);
70219820Sjeff};
71219820Sjeff
72219820Sjeffchar *argv0 = "saquery";
73219820Sjeff
74219820Sjeffstatic char *node_name_map_file = NULL;
75219820Sjeffstatic nn_map_t *node_name_map = NULL;
76219820Sjeffstatic ib_net64_t smkey = OSM_DEFAULT_SA_KEY;
77219820Sjeff
78219820Sjeff/**
79219820Sjeff * Declare some globals because I don't want this to be too complex.
80219820Sjeff */
81219820Sjeff#define MAX_PORTS (8)
82219820Sjeff#define DEFAULT_SA_TIMEOUT_MS (1000)
83219820Sjeffosmv_query_res_t result;
84219820Sjeffosm_log_t log_osm;
85219820Sjeffosm_mad_pool_t mad_pool;
86219820Sjeffosm_vendor_t *vendor = NULL;
87219820Sjeffint osm_debug = 0;
88219820Sjeffuint32_t sa_timeout_ms = DEFAULT_SA_TIMEOUT_MS;
89219820Sjeffchar *sa_hca_name = NULL;
90219820Sjeffuint32_t sa_port_num = 0;
91219820Sjeff
92219820Sjeffenum {
93219820Sjeff	ALL,
94219820Sjeff	LID_ONLY,
95219820Sjeff	UNIQUE_LID_ONLY,
96219820Sjeff	GUID_ONLY,
97219820Sjeff	ALL_DESC,
98219820Sjeff	NAME_OF_LID,
99219820Sjeff	NAME_OF_GUID,
100219820Sjeff} node_print_desc = ALL;
101219820Sjeff
102219820Sjeffchar *requested_name = NULL;
103219820Sjeffib_net16_t requested_lid = 0;
104219820Sjeffint requested_lid_flag = 0;
105219820Sjeffib_net64_t requested_guid = 0;
106219820Sjeffint requested_guid_flag = 0;
107219820Sjeff
108219820Sjeffstatic void format_buf(char *in, char *out, unsigned size)
109219820Sjeff{
110219820Sjeff	unsigned i;
111219820Sjeff
112219820Sjeff	for (i = 0; i < size - 3 && *in; i++) {
113219820Sjeff		*out++ = *in;
114219820Sjeff		if (*in++ == '\n' && *in) {
115219820Sjeff			*out++ = '\t';
116219820Sjeff			*out++ = '\t';
117219820Sjeff		}
118219820Sjeff	}
119219820Sjeff	*out = '\0';
120219820Sjeff}
121219820Sjeff
122219820Sjeff/**
123219820Sjeff * Call back for the various record requests.
124219820Sjeff */
125219820Sjeffstatic void query_res_cb(osmv_query_res_t * res)
126219820Sjeff{
127219820Sjeff	result = *res;
128219820Sjeff}
129219820Sjeff
130219820Sjeffstatic void print_node_desc(ib_node_record_t * node_record)
131219820Sjeff{
132219820Sjeff	ib_node_info_t *p_ni = &(node_record->node_info);
133219820Sjeff	ib_node_desc_t *p_nd = &(node_record->node_desc);
134219820Sjeff
135219820Sjeff	if (p_ni->node_type == IB_NODE_TYPE_CA) {
136219820Sjeff		printf("%6d  \"%s\"\n",
137219820Sjeff		       cl_ntoh16(node_record->lid),
138219820Sjeff		       clean_nodedesc((char *)p_nd->description));
139219820Sjeff	}
140219820Sjeff}
141219820Sjeff
142219820Sjeffstatic void print_node_record(ib_node_record_t * node_record)
143219820Sjeff{
144219820Sjeff	ib_node_info_t *p_ni = NULL;
145219820Sjeff	ib_node_desc_t *p_nd = NULL;
146219820Sjeff	char *name;
147219820Sjeff
148219820Sjeff	p_ni = &(node_record->node_info);
149219820Sjeff	p_nd = &(node_record->node_desc);
150219820Sjeff
151219820Sjeff	switch (node_print_desc) {
152219820Sjeff	case LID_ONLY:
153219820Sjeff	case UNIQUE_LID_ONLY:
154219820Sjeff		printf("%d\n", cl_ntoh16(node_record->lid));
155219820Sjeff		return;
156219820Sjeff	case GUID_ONLY:
157219820Sjeff		printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
158219820Sjeff		return;
159219820Sjeff	case NAME_OF_LID:
160219820Sjeff	case NAME_OF_GUID:
161219820Sjeff		name = remap_node_name(node_name_map,
162219820Sjeff				       cl_ntoh64(p_ni->node_guid),
163219820Sjeff				       (char *)p_nd->description);
164219820Sjeff		printf("%s\n", name);
165219820Sjeff		free(name);
166219820Sjeff		return;
167219820Sjeff	case ALL:
168219820Sjeff	default:
169219820Sjeff		break;
170219820Sjeff	}
171219820Sjeff
172219820Sjeff	printf("NodeRecord dump:\n"
173219820Sjeff	       "\t\tlid.....................0x%X\n"
174219820Sjeff	       "\t\treserved................0x%X\n"
175219820Sjeff	       "\t\tbase_version............0x%X\n"
176219820Sjeff	       "\t\tclass_version...........0x%X\n"
177219820Sjeff	       "\t\tnode_type...............%s\n"
178219820Sjeff	       "\t\tnum_ports...............0x%X\n"
179219820Sjeff	       "\t\tsys_guid................0x%016" PRIx64 "\n"
180219820Sjeff	       "\t\tnode_guid...............0x%016" PRIx64 "\n"
181219820Sjeff	       "\t\tport_guid...............0x%016" PRIx64 "\n"
182219820Sjeff	       "\t\tpartition_cap...........0x%X\n"
183219820Sjeff	       "\t\tdevice_id...............0x%X\n"
184219820Sjeff	       "\t\trevision................0x%X\n"
185219820Sjeff	       "\t\tport_num................0x%X\n"
186219820Sjeff	       "\t\tvendor_id...............0x%X\n"
187219820Sjeff	       "\t\tNodeDescription.........%s\n"
188219820Sjeff	       "",
189219820Sjeff	       cl_ntoh16(node_record->lid),
190219820Sjeff	       cl_ntoh16(node_record->resv),
191219820Sjeff	       p_ni->base_version,
192219820Sjeff	       p_ni->class_version,
193219820Sjeff	       ib_get_node_type_str(p_ni->node_type),
194219820Sjeff	       p_ni->num_ports,
195219820Sjeff	       cl_ntoh64(p_ni->sys_guid),
196219820Sjeff	       cl_ntoh64(p_ni->node_guid),
197219820Sjeff	       cl_ntoh64(p_ni->port_guid),
198219820Sjeff	       cl_ntoh16(p_ni->partition_cap),
199219820Sjeff	       cl_ntoh16(p_ni->device_id),
200219820Sjeff	       cl_ntoh32(p_ni->revision),
201219820Sjeff	       ib_node_info_get_local_port_num(p_ni),
202219820Sjeff	       cl_ntoh32(ib_node_info_get_vendor_id(p_ni)),
203219820Sjeff	       clean_nodedesc((char *)node_record->node_desc.description)
204219820Sjeff	    );
205219820Sjeff}
206219820Sjeff
207219820Sjeffstatic void dump_path_record(void *data)
208219820Sjeff{
209219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
210219820Sjeff	char gid_str2[INET6_ADDRSTRLEN];
211219820Sjeff	ib_path_rec_t *p_pr = data;
212219820Sjeff	printf("PathRecord dump:\n"
213219820Sjeff	       "\t\tservice_id..............0x%016" PRIx64 "\n"
214219820Sjeff	       "\t\tdgid....................%s\n"
215219820Sjeff	       "\t\tsgid....................%s\n"
216219820Sjeff	       "\t\tdlid....................0x%X\n"
217219820Sjeff	       "\t\tslid....................0x%X\n"
218219820Sjeff	       "\t\thop_flow_raw............0x%X\n"
219219820Sjeff	       "\t\ttclass..................0x%X\n"
220219820Sjeff	       "\t\tnum_path_revers.........0x%X\n"
221219820Sjeff	       "\t\tpkey....................0x%X\n"
222219820Sjeff	       "\t\tqos_class...............0x%X\n"
223219820Sjeff	       "\t\tsl......................0x%X\n"
224219820Sjeff	       "\t\tmtu.....................0x%X\n"
225219820Sjeff	       "\t\trate....................0x%X\n"
226219820Sjeff	       "\t\tpkt_life................0x%X\n"
227219820Sjeff	       "\t\tpreference..............0x%X\n"
228219820Sjeff	       "\t\tresv2...................0x%X\n"
229219820Sjeff	       "\t\tresv3...................0x%X\n"
230219820Sjeff	       "",
231219820Sjeff	       cl_ntoh64(p_pr->service_id),
232219820Sjeff	       inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),
233219820Sjeff	       inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),
234219820Sjeff	       cl_ntoh16(p_pr->dlid),
235219820Sjeff	       cl_ntoh16(p_pr->slid),
236219820Sjeff	       cl_ntoh32(p_pr->hop_flow_raw),
237219820Sjeff	       p_pr->tclass,
238219820Sjeff	       p_pr->num_path,
239219820Sjeff	       cl_ntoh16(p_pr->pkey),
240219820Sjeff	       ib_path_rec_qos_class(p_pr),
241219820Sjeff	       ib_path_rec_sl(p_pr),
242219820Sjeff	       p_pr->mtu,
243219820Sjeff	       p_pr->rate,
244219820Sjeff	       p_pr->pkt_life,
245219820Sjeff	       p_pr->preference,
246219820Sjeff	       *(uint32_t *) & p_pr->resv2, *((uint16_t *) & p_pr->resv2 + 2)
247219820Sjeff	    );
248219820Sjeff}
249219820Sjeff
250219820Sjeffstatic void dump_class_port_info(void *data)
251219820Sjeff{
252219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
253219820Sjeff	char gid_str2[INET6_ADDRSTRLEN];
254219820Sjeff	ib_class_port_info_t *class_port_info = data;
255219820Sjeff
256219820Sjeff	printf("SA ClassPortInfo:\n"
257219820Sjeff	       "\t\tBase version.............%d\n"
258219820Sjeff	       "\t\tClass version............%d\n"
259219820Sjeff	       "\t\tCapability mask..........0x%04X\n"
260219820Sjeff	       "\t\tCapability mask 2........0x%08X\n"
261219820Sjeff	       "\t\tResponse time value......0x%02X\n"
262219820Sjeff	       "\t\tRedirect GID.............%s\n"
263219820Sjeff	       "\t\tRedirect TC/SL/FL........0x%08X\n"
264219820Sjeff	       "\t\tRedirect LID.............0x%04X\n"
265219820Sjeff	       "\t\tRedirect PKey............0x%04X\n"
266219820Sjeff	       "\t\tRedirect QP..............0x%08X\n"
267219820Sjeff	       "\t\tRedirect QKey............0x%08X\n"
268219820Sjeff	       "\t\tTrap GID.................%s\n"
269219820Sjeff	       "\t\tTrap TC/SL/FL............0x%08X\n"
270219820Sjeff	       "\t\tTrap LID.................0x%04X\n"
271219820Sjeff	       "\t\tTrap PKey................0x%04X\n"
272219820Sjeff	       "\t\tTrap HL/QP...............0x%08X\n"
273219820Sjeff	       "\t\tTrap QKey................0x%08X\n"
274219820Sjeff	       "",
275219820Sjeff	       class_port_info->base_ver,
276219820Sjeff	       class_port_info->class_ver,
277219820Sjeff	       cl_ntoh16(class_port_info->cap_mask),
278219820Sjeff	       ib_class_cap_mask2(class_port_info),
279219820Sjeff	       ib_class_resp_time_val(class_port_info),
280219820Sjeff	       inet_ntop(AF_INET6, &(class_port_info->redir_gid), gid_str,
281219820Sjeff			 sizeof gid_str),
282219820Sjeff	       cl_ntoh32(class_port_info->redir_tc_sl_fl),
283219820Sjeff	       cl_ntoh16(class_port_info->redir_lid),
284219820Sjeff	       cl_ntoh16(class_port_info->redir_pkey),
285219820Sjeff	       cl_ntoh32(class_port_info->redir_qp),
286219820Sjeff	       cl_ntoh32(class_port_info->redir_qkey),
287219820Sjeff	       inet_ntop(AF_INET6, &(class_port_info->trap_gid), gid_str2,
288219820Sjeff			 sizeof gid_str2),
289219820Sjeff	       cl_ntoh32(class_port_info->trap_tc_sl_fl),
290219820Sjeff	       cl_ntoh16(class_port_info->trap_lid),
291219820Sjeff	       cl_ntoh16(class_port_info->trap_pkey),
292219820Sjeff	       cl_ntoh32(class_port_info->trap_hop_qp),
293219820Sjeff	       cl_ntoh32(class_port_info->trap_qkey)
294219820Sjeff	    );
295219820Sjeff}
296219820Sjeff
297219820Sjeffstatic void dump_portinfo_record(void *data)
298219820Sjeff{
299219820Sjeff	ib_portinfo_record_t *p_pir = data;
300219820Sjeff	const ib_port_info_t *const p_pi = &p_pir->port_info;
301219820Sjeff
302219820Sjeff	printf("PortInfoRecord dump:\n"
303219820Sjeff	       "\t\tEndPortLid..............0x%X\n"
304219820Sjeff	       "\t\tPortNum.................0x%X\n"
305219820Sjeff	       "\t\tbase_lid................0x%X\n"
306219820Sjeff	       "\t\tmaster_sm_base_lid......0x%X\n"
307219820Sjeff	       "\t\tcapability_mask.........0x%X\n"
308219820Sjeff	       "",
309219820Sjeff	       cl_ntoh16(p_pir->lid),
310219820Sjeff	       p_pir->port_num,
311219820Sjeff	       cl_ntoh16(p_pi->base_lid),
312219820Sjeff	       cl_ntoh16(p_pi->master_sm_base_lid),
313219820Sjeff	       cl_ntoh32(p_pi->capability_mask)
314219820Sjeff	    );
315219820Sjeff}
316219820Sjeff
317219820Sjeffstatic void dump_one_portinfo_record(void *data)
318219820Sjeff{
319219820Sjeff	char buf[2048], buf2[4096];
320219820Sjeff	ib_portinfo_record_t *pir = data;
321219820Sjeff	ib_port_info_t *pi = &pir->port_info;
322219820Sjeff
323219820Sjeff	mad_dump_portinfo(buf, sizeof(buf), pi, sizeof(*pi));
324219820Sjeff
325219820Sjeff	format_buf(buf, buf2, sizeof(buf2));
326219820Sjeff
327219820Sjeff	printf("PortInfoRecord dump:\n"
328219820Sjeff		"\tRID:\n"
329219820Sjeff		"\t\tEndPortLid..............%u\n"
330219820Sjeff		"\t\tPortNum.................0x%x\n"
331219820Sjeff		"\t\tReserved................0x%x\n"
332219820Sjeff		"\tPortInfo dump:\n\t\t%s",
333219820Sjeff		cl_ntoh16(pir->lid), pir->port_num, pir->resv, buf2);
334219820Sjeff}
335219820Sjeff
336219820Sjeffstatic void dump_multicast_group_record(void *data)
337219820Sjeff{
338219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
339219820Sjeff	ib_member_rec_t *p_mcmr = data;
340219820Sjeff	uint8_t sl;
341219820Sjeff	ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &sl, NULL, NULL);
342219820Sjeff	printf("MCMemberRecord group dump:\n"
343219820Sjeff	       "\t\tMGID....................%s\n"
344219820Sjeff	       "\t\tMlid....................0x%X\n"
345219820Sjeff	       "\t\tMtu.....................0x%X\n"
346219820Sjeff	       "\t\tpkey....................0x%X\n"
347219820Sjeff	       "\t\tRate....................0x%X\n"
348219820Sjeff	       "\t\tSL......................0x%X\n"
349219820Sjeff	       "",
350219820Sjeff	       inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str),
351219820Sjeff	       cl_ntoh16(p_mcmr->mlid),
352219820Sjeff	       p_mcmr->mtu, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, sl);
353219820Sjeff}
354219820Sjeff
355219820Sjeffstatic void dump_multicast_member_record(void *data)
356219820Sjeff{
357219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
358219820Sjeff	char gid_str2[INET6_ADDRSTRLEN];
359219820Sjeff	ib_member_rec_t *p_mcmr = data;
360219820Sjeff	uint16_t mlid = cl_ntoh16(p_mcmr->mlid);
361219820Sjeff	int i = 0;
362219820Sjeff	char *node_name = "<unknown>";
363219820Sjeff
364219820Sjeff	/* go through the node records searching for a port guid which matches
365219820Sjeff	 * this port gid interface id.
366219820Sjeff	 * This gives us a node name to print, if available.
367219820Sjeff	 */
368219820Sjeff	for (i = 0; i < result.result_cnt; i++) {
369219820Sjeff		ib_node_record_t *nr =
370219820Sjeff		    osmv_get_query_node_rec(result.p_result_madw, i);
371219820Sjeff		if (nr->node_info.port_guid ==
372219820Sjeff		    p_mcmr->port_gid.unicast.interface_id) {
373219820Sjeff			node_name =
374219820Sjeff			    clean_nodedesc((char *)nr->node_desc.description);
375219820Sjeff			break;
376219820Sjeff		}
377219820Sjeff	}
378219820Sjeff
379219820Sjeff	if (requested_name) {
380219820Sjeff		if (strtol(requested_name, NULL, 0) == mlid) {
381219820Sjeff			printf("\t\tPortGid.................%s (%s)\n",
382219820Sjeff			       inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
383219820Sjeff					 gid_str, sizeof gid_str), node_name);
384219820Sjeff		}
385219820Sjeff	} else {
386219820Sjeff		printf("MCMemberRecord member dump:\n"
387219820Sjeff		       "\t\tMGID....................%s\n"
388219820Sjeff		       "\t\tMlid....................0x%X\n"
389219820Sjeff		       "\t\tPortGid.................%s\n"
390219820Sjeff		       "\t\tScopeState..............0x%X\n"
391219820Sjeff		       "\t\tProxyJoin...............0x%X\n"
392219820Sjeff		       "\t\tNodeDescription.........%s\n"
393219820Sjeff		       "",
394219820Sjeff		       inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,
395219820Sjeff				 sizeof gid_str),
396219820Sjeff		       cl_ntoh16(p_mcmr->mlid),
397219820Sjeff		       inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
398219820Sjeff				 gid_str2, sizeof gid_str2),
399219820Sjeff		       p_mcmr->scope_state, p_mcmr->proxy_join, node_name);
400219820Sjeff	}
401219820Sjeff}
402219820Sjeff
403219820Sjeffstatic void dump_service_record(void *data)
404219820Sjeff{
405219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
406219820Sjeff	char buf_service_key[35];
407219820Sjeff	char buf_service_name[65];
408219820Sjeff	ib_service_record_t *p_sr = data;
409219820Sjeff
410219820Sjeff	sprintf(buf_service_key,
411219820Sjeff		"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
412219820Sjeff		p_sr->service_key[0], p_sr->service_key[1],
413219820Sjeff		p_sr->service_key[2], p_sr->service_key[3],
414219820Sjeff		p_sr->service_key[4], p_sr->service_key[5],
415219820Sjeff		p_sr->service_key[6], p_sr->service_key[7],
416219820Sjeff		p_sr->service_key[8], p_sr->service_key[9],
417219820Sjeff		p_sr->service_key[10], p_sr->service_key[11],
418219820Sjeff		p_sr->service_key[12], p_sr->service_key[13],
419219820Sjeff		p_sr->service_key[14], p_sr->service_key[15]);
420219820Sjeff	strncpy(buf_service_name, (char *)p_sr->service_name, 64);
421219820Sjeff	buf_service_name[64] = '\0';
422219820Sjeff
423219820Sjeff	printf("ServiceRecord dump:\n"
424219820Sjeff	       "\t\tServiceID...............0x%016" PRIx64 "\n"
425219820Sjeff	       "\t\tServiceGID..............%s\n"
426219820Sjeff	       "\t\tServiceP_Key............0x%X\n"
427219820Sjeff	       "\t\tServiceLease............0x%X\n"
428219820Sjeff	       "\t\tServiceKey..............%s\n"
429219820Sjeff	       "\t\tServiceName.............%s\n"
430219820Sjeff	       "\t\tServiceData8.1..........0x%X\n"
431219820Sjeff	       "\t\tServiceData8.2..........0x%X\n"
432219820Sjeff	       "\t\tServiceData8.3..........0x%X\n"
433219820Sjeff	       "\t\tServiceData8.4..........0x%X\n"
434219820Sjeff	       "\t\tServiceData8.5..........0x%X\n"
435219820Sjeff	       "\t\tServiceData8.6..........0x%X\n"
436219820Sjeff	       "\t\tServiceData8.7..........0x%X\n"
437219820Sjeff	       "\t\tServiceData8.8..........0x%X\n"
438219820Sjeff	       "\t\tServiceData8.9..........0x%X\n"
439219820Sjeff	       "\t\tServiceData8.10.........0x%X\n"
440219820Sjeff	       "\t\tServiceData8.11.........0x%X\n"
441219820Sjeff	       "\t\tServiceData8.12.........0x%X\n"
442219820Sjeff	       "\t\tServiceData8.13.........0x%X\n"
443219820Sjeff	       "\t\tServiceData8.14.........0x%X\n"
444219820Sjeff	       "\t\tServiceData8.15.........0x%X\n"
445219820Sjeff	       "\t\tServiceData8.16.........0x%X\n"
446219820Sjeff	       "\t\tServiceData16.1.........0x%X\n"
447219820Sjeff	       "\t\tServiceData16.2.........0x%X\n"
448219820Sjeff	       "\t\tServiceData16.3.........0x%X\n"
449219820Sjeff	       "\t\tServiceData16.4.........0x%X\n"
450219820Sjeff	       "\t\tServiceData16.5.........0x%X\n"
451219820Sjeff	       "\t\tServiceData16.6.........0x%X\n"
452219820Sjeff	       "\t\tServiceData16.7.........0x%X\n"
453219820Sjeff	       "\t\tServiceData16.8.........0x%X\n"
454219820Sjeff	       "\t\tServiceData32.1.........0x%X\n"
455219820Sjeff	       "\t\tServiceData32.2.........0x%X\n"
456219820Sjeff	       "\t\tServiceData32.3.........0x%X\n"
457219820Sjeff	       "\t\tServiceData32.4.........0x%X\n"
458219820Sjeff	       "\t\tServiceData64.1.........0x%016" PRIx64 "\n"
459219820Sjeff	       "\t\tServiceData64.2.........0x%016" PRIx64 "\n"
460219820Sjeff	       "",
461219820Sjeff	       cl_ntoh64(p_sr->service_id),
462219820Sjeff	       inet_ntop(AF_INET6, p_sr->service_gid.raw, gid_str,
463219820Sjeff			 sizeof gid_str),
464219820Sjeff	       cl_ntoh16(p_sr->service_pkey),
465219820Sjeff	       cl_ntoh32(p_sr->service_lease),
466219820Sjeff	       buf_service_key,
467219820Sjeff	       buf_service_name,
468219820Sjeff	       p_sr->service_data8[0], p_sr->service_data8[1],
469219820Sjeff	       p_sr->service_data8[2], p_sr->service_data8[3],
470219820Sjeff	       p_sr->service_data8[4], p_sr->service_data8[5],
471219820Sjeff	       p_sr->service_data8[6], p_sr->service_data8[7],
472219820Sjeff	       p_sr->service_data8[8], p_sr->service_data8[9],
473219820Sjeff	       p_sr->service_data8[10], p_sr->service_data8[11],
474219820Sjeff	       p_sr->service_data8[12], p_sr->service_data8[13],
475219820Sjeff	       p_sr->service_data8[14], p_sr->service_data8[15],
476219820Sjeff	       cl_ntoh16(p_sr->service_data16[0]),
477219820Sjeff	       cl_ntoh16(p_sr->service_data16[1]),
478219820Sjeff	       cl_ntoh16(p_sr->service_data16[2]),
479219820Sjeff	       cl_ntoh16(p_sr->service_data16[3]),
480219820Sjeff	       cl_ntoh16(p_sr->service_data16[4]),
481219820Sjeff	       cl_ntoh16(p_sr->service_data16[5]),
482219820Sjeff	       cl_ntoh16(p_sr->service_data16[6]),
483219820Sjeff	       cl_ntoh16(p_sr->service_data16[7]),
484219820Sjeff	       cl_ntoh32(p_sr->service_data32[0]),
485219820Sjeff	       cl_ntoh32(p_sr->service_data32[1]),
486219820Sjeff	       cl_ntoh32(p_sr->service_data32[2]),
487219820Sjeff	       cl_ntoh32(p_sr->service_data32[3]),
488219820Sjeff	       cl_ntoh64(p_sr->service_data64[0]),
489219820Sjeff	       cl_ntoh64(p_sr->service_data64[1])
490219820Sjeff	    );
491219820Sjeff}
492219820Sjeff
493219820Sjeffstatic void dump_inform_info_record(void *data)
494219820Sjeff{
495219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
496219820Sjeff	char gid_str2[INET6_ADDRSTRLEN];
497219820Sjeff	ib_inform_info_record_t *p_iir = data;
498219820Sjeff	uint32_t qpn;
499219820Sjeff	uint8_t resp_time_val;
500219820Sjeff
501219820Sjeff	ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.
502219820Sjeff					 qpn_resp_time_val, &qpn,
503219820Sjeff					 &resp_time_val);
504219820Sjeff
505219820Sjeff	if (p_iir->inform_info.is_generic) {
506219820Sjeff		printf("InformInfoRecord dump:\n"
507219820Sjeff		       "\t\tRID\n"
508219820Sjeff		       "\t\tSubscriberGID...........%s\n"
509219820Sjeff		       "\t\tSubscriberEnum..........0x%X\n"
510219820Sjeff		       "\t\tInformInfo dump:\n"
511219820Sjeff		       "\t\tgid.....................%s\n"
512219820Sjeff		       "\t\tlid_range_begin.........0x%X\n"
513219820Sjeff		       "\t\tlid_range_end...........0x%X\n"
514219820Sjeff		       "\t\tis_generic..............0x%X\n"
515219820Sjeff		       "\t\tsubscribe...............0x%X\n"
516219820Sjeff		       "\t\ttrap_type...............0x%X\n"
517219820Sjeff		       "\t\ttrap_num................%u\n"
518219820Sjeff		       "\t\tqpn.....................0x%06X\n"
519219820Sjeff		       "\t\tresp_time_val...........0x%X\n"
520219820Sjeff		       "\t\tnode_type...............0x%06X\n"
521219820Sjeff		       "",
522219820Sjeff		       inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
523219820Sjeff				 sizeof gid_str),
524219820Sjeff		       cl_ntoh16(p_iir->subscriber_enum),
525219820Sjeff		       inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2,
526219820Sjeff				 sizeof gid_str2),
527219820Sjeff		       cl_ntoh16(p_iir->inform_info.lid_range_begin),
528219820Sjeff		       cl_ntoh16(p_iir->inform_info.lid_range_end),
529219820Sjeff		       p_iir->inform_info.is_generic,
530219820Sjeff		       p_iir->inform_info.subscribe,
531219820Sjeff		       cl_ntoh16(p_iir->inform_info.trap_type),
532219820Sjeff		       cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
533219820Sjeff		       cl_ntoh32(qpn),
534219820Sjeff		       resp_time_val,
535219820Sjeff		       cl_ntoh32(ib_inform_info_get_prod_type
536219820Sjeff				 (&p_iir->inform_info))
537219820Sjeff		    );
538219820Sjeff	} else {
539219820Sjeff		printf("InformInfoRecord dump:\n"
540219820Sjeff		       "\t\tRID\n"
541219820Sjeff		       "\t\tSubscriberGID...........%s\n"
542219820Sjeff		       "\t\tSubscriberEnum..........0x%X\n"
543219820Sjeff		       "\t\tInformInfo dump:\n"
544219820Sjeff		       "\t\tgid.....................%s\n"
545219820Sjeff		       "\t\tlid_range_begin.........0x%X\n"
546219820Sjeff		       "\t\tlid_range_end...........0x%X\n"
547219820Sjeff		       "\t\tis_generic..............0x%X\n"
548219820Sjeff		       "\t\tsubscribe...............0x%X\n"
549219820Sjeff		       "\t\ttrap_type...............0x%X\n"
550219820Sjeff		       "\t\tdev_id..................0x%X\n"
551219820Sjeff		       "\t\tqpn.....................0x%06X\n"
552219820Sjeff		       "\t\tresp_time_val...........0x%X\n"
553219820Sjeff		       "\t\tvendor_id...............0x%06X\n"
554219820Sjeff		       "",
555219820Sjeff		       inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
556219820Sjeff				 sizeof gid_str),
557219820Sjeff		       cl_ntoh16(p_iir->subscriber_enum),
558219820Sjeff		       inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
559219820Sjeff				 gid_str2, sizeof gid_str2),
560219820Sjeff		       cl_ntoh16(p_iir->inform_info.lid_range_begin),
561219820Sjeff		       cl_ntoh16(p_iir->inform_info.lid_range_end),
562219820Sjeff		       p_iir->inform_info.is_generic,
563219820Sjeff		       p_iir->inform_info.subscribe,
564219820Sjeff		       cl_ntoh16(p_iir->inform_info.trap_type),
565219820Sjeff		       cl_ntoh16(p_iir->inform_info.g_or_v.vend.dev_id),
566219820Sjeff		       cl_ntoh32(qpn),
567219820Sjeff		       resp_time_val,
568219820Sjeff		       cl_ntoh32(ib_inform_info_get_prod_type
569219820Sjeff				 (&p_iir->inform_info))
570219820Sjeff		    );
571219820Sjeff	}
572219820Sjeff}
573219820Sjeff
574219820Sjeffstatic void dump_one_link_record(void *data)
575219820Sjeff{
576219820Sjeff	ib_link_record_t *lr = data;
577219820Sjeff	printf("LinkRecord dump:\n"
578219820Sjeff	       "\t\tFromLID....................%u\n"
579219820Sjeff	       "\t\tFromPort...................%u\n"
580219820Sjeff	       "\t\tToPort.....................%u\n"
581219820Sjeff	       "\t\tToLID......................%u\n",
582219820Sjeff	       cl_ntoh16(lr->from_lid), lr->from_port_num,
583219820Sjeff	       lr->to_port_num, cl_ntoh16(lr->to_lid));
584219820Sjeff}
585219820Sjeff
586219820Sjeffstatic void dump_one_slvl_record(void *data)
587219820Sjeff{
588219820Sjeff	ib_slvl_table_record_t *slvl = data;
589219820Sjeff	ib_slvl_table_t *t = &slvl->slvl_tbl;
590219820Sjeff	printf("SL2VLTableRecord dump:\n"
591219820Sjeff	       "\t\tLID........................%u\n"
592219820Sjeff	       "\t\tInPort.....................%u\n"
593219820Sjeff	       "\t\tOutPort....................%u\n"
594219820Sjeff	       "\t\tSL: 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|\n"
595219820Sjeff	       "\t\tVL:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u"
596219820Sjeff	       "|%2u|%2u|%2u|\n",
597219820Sjeff	       cl_ntoh16(slvl->lid), slvl->in_port_num, slvl->out_port_num,
598219820Sjeff	       ib_slvl_table_get(t, 0), ib_slvl_table_get(t, 1),
599219820Sjeff	       ib_slvl_table_get(t, 2), ib_slvl_table_get(t, 3),
600219820Sjeff	       ib_slvl_table_get(t, 4), ib_slvl_table_get(t, 5),
601219820Sjeff	       ib_slvl_table_get(t, 6), ib_slvl_table_get(t, 7),
602219820Sjeff	       ib_slvl_table_get(t, 8), ib_slvl_table_get(t, 9),
603219820Sjeff	       ib_slvl_table_get(t, 10), ib_slvl_table_get(t, 11),
604219820Sjeff	       ib_slvl_table_get(t, 12), ib_slvl_table_get(t, 13),
605219820Sjeff	       ib_slvl_table_get(t, 14), ib_slvl_table_get(t, 15));
606219820Sjeff}
607219820Sjeff
608219820Sjeffstatic void dump_one_vlarb_record(void *data)
609219820Sjeff{
610219820Sjeff	ib_vl_arb_table_record_t *vlarb = data;
611219820Sjeff	ib_vl_arb_element_t *e = vlarb->vl_arb_tbl.vl_entry;
612219820Sjeff	int i;
613219820Sjeff	printf("VLArbTableRecord dump:\n"
614219820Sjeff	       "\t\tLID........................%u\n"
615219820Sjeff	       "\t\tPort.......................%u\n"
616219820Sjeff	       "\t\tBlock......................%u\n",
617219820Sjeff	       cl_ntoh16(vlarb->lid), vlarb->port_num, vlarb->block_num);
618219820Sjeff	for (i = 0; i < 32; i += 16) {
619219820Sjeff		printf("\t\tVL    :%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
620219820Sjeff		       "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",
621219820Sjeff		       e[i + 0].vl, e[i + 1].vl, e[i + 2].vl, e[i + 3].vl,
622219820Sjeff		       e[i + 4].vl, e[i + 5].vl, e[i + 6].vl, e[i + 7].vl,
623219820Sjeff		       e[i + 8].vl, e[i + 9].vl, e[i + 10].vl, e[i + 11].vl,
624219820Sjeff		       e[i + 12].vl, e[i + 13].vl, e[i + 14].vl, e[i + 15].vl);
625219820Sjeff		printf("\n\t\tWeight:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
626219820Sjeff		       "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",
627219820Sjeff		       e[i + 0].weight, e[i + 1].weight, e[i + 2].weight,
628219820Sjeff		       e[i + 3].weight, e[i + 4].weight, e[i + 5].weight,
629219820Sjeff		       e[i + 6].weight, e[i + 7].weight, e[i + 8].weight,
630219820Sjeff		       e[i + 9].weight, e[i + 10].weight, e[i + 11].weight,
631219820Sjeff		       e[i + 12].weight, e[i + 13].weight, e[i + 14].weight,
632219820Sjeff		       e[i + 15].weight);
633219820Sjeff		printf("\n");
634219820Sjeff	}
635219820Sjeff}
636219820Sjeff
637219820Sjeffstatic void dump_one_pkey_tbl_record(void *data)
638219820Sjeff{
639219820Sjeff	ib_pkey_table_record_t *pktr = data;
640219820Sjeff	ib_net16_t *p = pktr->pkey_tbl.pkey_entry;
641219820Sjeff	int i;
642219820Sjeff	printf("PKeyTableRecord dump:\n"
643219820Sjeff	       "\t\tLID........................%u\n"
644219820Sjeff	       "\t\tPort.......................%u\n"
645219820Sjeff	       "\t\tBlock......................%u\n"
646219820Sjeff	       "\t\tPKey Table:\n",
647219820Sjeff	       cl_ntoh16(pktr->lid), pktr->port_num, pktr->block_num);
648219820Sjeff	for (i = 0; i < 32; i += 8)
649219820Sjeff		printf("\t\t0x%04x 0x%04x 0x%04x 0x%04x"
650219820Sjeff		       " 0x%04x 0x%04x 0x%04x 0x%04x\n",
651219820Sjeff		       cl_ntoh16(p[i + 0]), cl_ntoh16(p[i + 1]),
652219820Sjeff		       cl_ntoh16(p[i + 2]), cl_ntoh16(p[i + 3]),
653219820Sjeff		       cl_ntoh16(p[i + 4]), cl_ntoh16(p[i + 5]),
654219820Sjeff		       cl_ntoh16(p[i + 6]), cl_ntoh16(p[i + 7]));
655219820Sjeff	printf("\n");
656219820Sjeff}
657219820Sjeff
658219820Sjeffstatic void dump_one_lft_record(void *data)
659219820Sjeff{
660219820Sjeff	ib_lft_record_t *lftr = data;
661219820Sjeff	unsigned block = cl_ntoh16(lftr->block_num);
662219820Sjeff	int i;
663219820Sjeff	printf("LFT Record dump:\n"
664219820Sjeff	       "\t\tLID........................%u\n"
665219820Sjeff	       "\t\tBlock......................%u\n"
666219820Sjeff	       "\t\tLFT:\n\t\tLID\tPort Number\n", cl_ntoh16(lftr->lid), block);
667219820Sjeff	for (i = 0; i < 64; i++)
668219820Sjeff		printf("\t\t%u\t%u\n", block * 64 + i, lftr->lft[i]);
669219820Sjeff	printf("\n");
670219820Sjeff}
671219820Sjeff
672219820Sjeffstatic void dump_one_mft_record(void *data)
673219820Sjeff{
674219820Sjeff	ib_mft_record_t *mftr = data;
675219820Sjeff	unsigned position = cl_ntoh16(mftr->position_block_num) >> 12;
676219820Sjeff	unsigned block = cl_ntoh16(mftr->position_block_num) &
677219820Sjeff	    IB_MCAST_BLOCK_ID_MASK_HO;
678219820Sjeff	int i;
679219820Sjeff	printf("MFT Record dump:\n"
680219820Sjeff	       "\t\tLID........................%u\n"
681219820Sjeff	       "\t\tPosition...................%u\n"
682219820Sjeff	       "\t\tBlock......................%u\n"
683219820Sjeff	       "\t\tMFT:\n\t\tMLID\tPort Mask\n",
684219820Sjeff	       cl_ntoh16(mftr->lid), position, block);
685219820Sjeff	for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
686219820Sjeff		printf("\t\t0x%x\t0x%x\n",
687219820Sjeff		       IB_LID_MCAST_START_HO + block * 64 + i,
688219820Sjeff		       cl_ntoh16(mftr->mft[i]));
689219820Sjeff	printf("\n");
690219820Sjeff}
691219820Sjeffstatic void dump_results(osmv_query_res_t * r, void (*dump_func) (void *))
692219820Sjeff{
693219820Sjeff	int i;
694219820Sjeff	for (i = 0; i < r->result_cnt; i++) {
695219820Sjeff		void *data = osmv_get_query_result(r->p_result_madw, i);
696219820Sjeff		dump_func(data);
697219820Sjeff	}
698219820Sjeff}
699219820Sjeff
700219820Sjeffstatic void return_mad(void)
701219820Sjeff{
702219820Sjeff	/*
703219820Sjeff	 * Return the IB query MAD to the pool as necessary.
704219820Sjeff	 */
705219820Sjeff	if (result.p_result_madw != NULL) {
706219820Sjeff		osm_mad_pool_put(&mad_pool, result.p_result_madw);
707219820Sjeff		result.p_result_madw = NULL;
708219820Sjeff	}
709219820Sjeff}
710219820Sjeff
711219820Sjeff/**
712219820Sjeff * Get any record(s)
713219820Sjeff */
714219820Sjeffstatic ib_api_status_t
715219820Sjeffget_any_records(osm_bind_handle_t h,
716219820Sjeff		ib_net16_t attr_id, ib_net32_t attr_mod, ib_net64_t comp_mask,
717219820Sjeff		void *attr, ib_net16_t attr_offset, ib_net64_t sm_key)
718219820Sjeff{
719219820Sjeff	ib_api_status_t status;
720219820Sjeff	osmv_query_req_t req;
721219820Sjeff	osmv_user_query_t user;
722219820Sjeff
723219820Sjeff	memset(&req, 0, sizeof(req));
724219820Sjeff	memset(&user, 0, sizeof(user));
725219820Sjeff
726219820Sjeff	user.attr_id = attr_id;
727219820Sjeff	user.attr_offset = attr_offset;
728219820Sjeff	user.attr_mod = attr_mod;
729219820Sjeff	user.comp_mask = comp_mask;
730219820Sjeff	user.p_attr = attr;
731219820Sjeff
732219820Sjeff	req.query_type = OSMV_QUERY_USER_DEFINED;
733219820Sjeff	req.timeout_ms = sa_timeout_ms;
734219820Sjeff	req.retry_cnt = 1;
735219820Sjeff	req.flags = OSM_SA_FLAGS_SYNC;
736219820Sjeff	req.query_context = NULL;
737219820Sjeff	req.pfn_query_cb = query_res_cb;
738219820Sjeff	req.p_query_input = &user;
739219820Sjeff	req.sm_key = sm_key;
740219820Sjeff
741219820Sjeff	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
742219820Sjeff		fprintf(stderr, "Query SA failed: %s\n",
743219820Sjeff			ib_get_err_str(status));
744219820Sjeff		return status;
745219820Sjeff	}
746219820Sjeff
747219820Sjeff	if (result.status != IB_SUCCESS) {
748219820Sjeff		fprintf(stderr, "Query result returned: %s\n",
749219820Sjeff			ib_get_err_str(result.status));
750219820Sjeff		return result.status;
751219820Sjeff	}
752219820Sjeff
753219820Sjeff	return status;
754219820Sjeff}
755219820Sjeff
756219820Sjeff/**
757219820Sjeff * Get all the records available for requested query type.
758219820Sjeff */
759219820Sjeffstatic ib_api_status_t
760219820Sjeffget_all_records(osm_bind_handle_t h,
761219820Sjeff		ib_net16_t query_id, ib_net16_t attr_offset, int trusted)
762219820Sjeff{
763219820Sjeff	return get_any_records(h, query_id, 0, 0, NULL, attr_offset,
764219820Sjeff			       trusted ? smkey : 0);
765219820Sjeff}
766219820Sjeff
767219820Sjeff/**
768219820Sjeff * return the lid from the node descriptor (name) supplied
769219820Sjeff */
770219820Sjeffstatic ib_api_status_t
771219820Sjeffget_lid_from_name(osm_bind_handle_t h, const char *name, ib_net16_t * lid)
772219820Sjeff{
773219820Sjeff	int i = 0;
774219820Sjeff	ib_node_record_t *node_record = NULL;
775219820Sjeff	ib_node_info_t *p_ni = NULL;
776219820Sjeff	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(*node_record));
777219820Sjeff	ib_api_status_t status;
778219820Sjeff
779219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);
780219820Sjeff	if (status != IB_SUCCESS)
781219820Sjeff		return (status);
782219820Sjeff
783219820Sjeff	for (i = 0; i < result.result_cnt; i++) {
784219820Sjeff		node_record = osmv_get_query_node_rec(result.p_result_madw, i);
785219820Sjeff		p_ni = &(node_record->node_info);
786219820Sjeff		if (name
787219820Sjeff		    && strncmp(name, (char *)node_record->node_desc.description,
788219820Sjeff			       sizeof(node_record->node_desc.description)) ==
789219820Sjeff		    0) {
790219820Sjeff			*lid = cl_ntoh16(node_record->lid);
791219820Sjeff			break;
792219820Sjeff		}
793219820Sjeff	}
794219820Sjeff	return_mad();
795219820Sjeff	return (status);
796219820Sjeff}
797219820Sjeff
798219820Sjeffstatic ib_net16_t get_lid(osm_bind_handle_t h, const char *name)
799219820Sjeff{
800219820Sjeff	ib_net16_t rc_lid = 0;
801219820Sjeff
802219820Sjeff	if (!name)
803219820Sjeff		return (0);
804219820Sjeff	if (isalpha(name[0]))
805219820Sjeff		assert(get_lid_from_name(h, name, &rc_lid) == IB_SUCCESS);
806219820Sjeff	else
807219820Sjeff		rc_lid = atoi(name);
808219820Sjeff	if (rc_lid == 0)
809219820Sjeff		fprintf(stderr, "Failed to find lid for \"%s\"\n", name);
810219820Sjeff	return (rc_lid);
811219820Sjeff}
812219820Sjeff
813219820Sjeffstatic int parse_lid_and_ports(osm_bind_handle_t h,
814219820Sjeff			       char *str, int *lid, int *port1, int *port2)
815219820Sjeff{
816219820Sjeff	char *p, *e;
817219820Sjeff
818219820Sjeff	if (port1)
819219820Sjeff		*port1 = -1;
820219820Sjeff	if (port2)
821219820Sjeff		*port2 = -1;
822219820Sjeff
823219820Sjeff	p = strchr(str, '/');
824219820Sjeff	if (p)
825219820Sjeff		*p = '\0';
826219820Sjeff	if (lid)
827219820Sjeff		*lid = get_lid(h, str);
828219820Sjeff
829219820Sjeff	if (!p)
830219820Sjeff		return 0;
831219820Sjeff	str = p + 1;
832219820Sjeff	p = strchr(str, '/');
833219820Sjeff	if (p)
834219820Sjeff		*p = '\0';
835219820Sjeff	if (port1) {
836219820Sjeff		*port1 = strtoul(str, &e, 0);
837219820Sjeff		if (e == str)
838219820Sjeff			*port1 = -1;
839219820Sjeff	}
840219820Sjeff
841219820Sjeff	if (!p)
842219820Sjeff		return 0;
843219820Sjeff	str = p + 1;
844219820Sjeff	if (port2) {
845219820Sjeff		*port2 = strtoul(str, &e, 0);
846219820Sjeff		if (e == str)
847219820Sjeff			*port2 = -1;
848219820Sjeff	}
849219820Sjeff
850219820Sjeff	return 0;
851219820Sjeff}
852219820Sjeff
853219820Sjeff/*
854219820Sjeff * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.
855219820Sjeff */
856219820Sjeffstatic ib_api_status_t
857219820Sjeffget_issm_records(osm_bind_handle_t h, ib_net32_t capability_mask)
858219820Sjeff{
859219820Sjeff	ib_portinfo_record_t attr;
860219820Sjeff
861219820Sjeff	memset(&attr, 0, sizeof(attr));
862219820Sjeff	attr.port_info.capability_mask = capability_mask;
863219820Sjeff
864219820Sjeff	return get_any_records(h, IB_MAD_ATTR_PORTINFO_RECORD,
865219820Sjeff			       cl_hton32(1 << 31), IB_PIR_COMPMASK_CAPMASK,
866219820Sjeff			       &attr,
867219820Sjeff			       ib_get_attr_offset(sizeof(ib_portinfo_record_t)),
868219820Sjeff			       0);
869219820Sjeff}
870219820Sjeff
871219820Sjeffstatic ib_api_status_t print_node_records(osm_bind_handle_t h)
872219820Sjeff{
873219820Sjeff	int i = 0;
874219820Sjeff	ib_node_record_t *node_record = NULL;
875219820Sjeff	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(*node_record));
876219820Sjeff	ib_api_status_t status;
877219820Sjeff
878219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);
879219820Sjeff	if (status != IB_SUCCESS)
880219820Sjeff		return (status);
881219820Sjeff
882219820Sjeff	if (node_print_desc == ALL_DESC) {
883219820Sjeff		printf("   LID \"name\"\n");
884219820Sjeff		printf("================\n");
885219820Sjeff	}
886219820Sjeff	for (i = 0; i < result.result_cnt; i++) {
887219820Sjeff		node_record = osmv_get_query_node_rec(result.p_result_madw, i);
888219820Sjeff		if (node_print_desc == ALL_DESC) {
889219820Sjeff			print_node_desc(node_record);
890219820Sjeff		} else if (node_print_desc == NAME_OF_LID) {
891219820Sjeff			if (requested_lid == cl_ntoh16(node_record->lid)) {
892219820Sjeff				print_node_record(node_record);
893219820Sjeff			}
894219820Sjeff		} else if (node_print_desc == NAME_OF_GUID) {
895219820Sjeff			ib_node_info_t *p_ni = &(node_record->node_info);
896219820Sjeff
897219820Sjeff			if (requested_guid == cl_ntoh64(p_ni->port_guid)) {
898219820Sjeff				print_node_record(node_record);
899219820Sjeff			}
900219820Sjeff		} else {
901219820Sjeff			if (!requested_name ||
902219820Sjeff			    (strncmp(requested_name,
903219820Sjeff				     (char *)node_record->node_desc.description,
904219820Sjeff				     sizeof(node_record->node_desc.
905219820Sjeff					    description)) == 0)) {
906219820Sjeff				print_node_record(node_record);
907219820Sjeff				if (node_print_desc == UNIQUE_LID_ONLY) {
908219820Sjeff					return_mad();
909219820Sjeff					exit(0);
910219820Sjeff				}
911219820Sjeff			}
912219820Sjeff		}
913219820Sjeff	}
914219820Sjeff	return_mad();
915219820Sjeff	return (status);
916219820Sjeff}
917219820Sjeff
918219820Sjeffstatic ib_api_status_t
919219820Sjeffget_print_path_rec_lid(osm_bind_handle_t h,
920219820Sjeff		       ib_net16_t src_lid, ib_net16_t dst_lid)
921219820Sjeff{
922219820Sjeff	osmv_query_req_t req;
923219820Sjeff	osmv_lid_pair_t lid_pair;
924219820Sjeff	ib_api_status_t status;
925219820Sjeff
926219820Sjeff	lid_pair.src_lid = cl_hton16(src_lid);
927219820Sjeff	lid_pair.dest_lid = cl_hton16(dst_lid);
928219820Sjeff
929219820Sjeff	memset(&req, 0, sizeof(req));
930219820Sjeff
931219820Sjeff	req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;
932219820Sjeff	req.timeout_ms = sa_timeout_ms;
933219820Sjeff	req.retry_cnt = 1;
934219820Sjeff	req.flags = OSM_SA_FLAGS_SYNC;
935219820Sjeff	req.query_context = NULL;
936219820Sjeff	req.pfn_query_cb = query_res_cb;
937219820Sjeff	req.p_query_input = (void *)&lid_pair;
938219820Sjeff	req.sm_key = 0;
939219820Sjeff
940219820Sjeff	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
941219820Sjeff		fprintf(stderr, "ERROR: Query SA failed: %s\n",
942219820Sjeff			ib_get_err_str(status));
943219820Sjeff		return (status);
944219820Sjeff	}
945219820Sjeff	if (result.status != IB_SUCCESS) {
946219820Sjeff		fprintf(stderr, "ERROR: Query result returned: %s\n",
947219820Sjeff			ib_get_err_str(result.status));
948219820Sjeff		return (result.status);
949219820Sjeff	}
950219820Sjeff	status = result.status;
951219820Sjeff	dump_results(&result, dump_path_record);
952219820Sjeff	return_mad();
953219820Sjeff	return (status);
954219820Sjeff}
955219820Sjeff
956219820Sjeffstatic ib_api_status_t
957219820Sjeffget_print_path_rec_gid(osm_bind_handle_t h,
958219820Sjeff		       const ib_gid_t * src_gid, const ib_gid_t * dst_gid)
959219820Sjeff{
960219820Sjeff	osmv_query_req_t req;
961219820Sjeff	osmv_gid_pair_t gid_pair;
962219820Sjeff	ib_api_status_t status;
963219820Sjeff
964219820Sjeff	gid_pair.src_gid = *src_gid;
965219820Sjeff	gid_pair.dest_gid = *dst_gid;
966219820Sjeff
967219820Sjeff	memset(&req, 0, sizeof(req));
968219820Sjeff
969219820Sjeff	req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;
970219820Sjeff	req.timeout_ms = sa_timeout_ms;
971219820Sjeff	req.retry_cnt = 1;
972219820Sjeff	req.flags = OSM_SA_FLAGS_SYNC;
973219820Sjeff	req.query_context = NULL;
974219820Sjeff	req.pfn_query_cb = query_res_cb;
975219820Sjeff	req.p_query_input = (void *)&gid_pair;
976219820Sjeff	req.sm_key = 0;
977219820Sjeff
978219820Sjeff	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
979219820Sjeff		fprintf(stderr, "ERROR: Query SA failed: %s\n",
980219820Sjeff			ib_get_err_str(status));
981219820Sjeff		return (status);
982219820Sjeff	}
983219820Sjeff	if (result.status != IB_SUCCESS) {
984219820Sjeff		fprintf(stderr, "ERROR: Query result returned: %s\n",
985219820Sjeff			ib_get_err_str(result.status));
986219820Sjeff		return (result.status);
987219820Sjeff	}
988219820Sjeff	status = result.status;
989219820Sjeff	dump_results(&result, dump_path_record);
990219820Sjeff	return_mad();
991219820Sjeff	return (status);
992219820Sjeff}
993219820Sjeff
994219820Sjeffstatic ib_api_status_t get_print_class_port_info(osm_bind_handle_t h)
995219820Sjeff{
996219820Sjeff	osmv_query_req_t req;
997219820Sjeff	ib_api_status_t status;
998219820Sjeff
999219820Sjeff	memset(&req, 0, sizeof(req));
1000219820Sjeff
1001219820Sjeff	req.query_type = OSMV_QUERY_CLASS_PORT_INFO;
1002219820Sjeff	req.timeout_ms = sa_timeout_ms;
1003219820Sjeff	req.retry_cnt = 1;
1004219820Sjeff	req.flags = OSM_SA_FLAGS_SYNC;
1005219820Sjeff	req.query_context = NULL;
1006219820Sjeff	req.pfn_query_cb = query_res_cb;
1007219820Sjeff	req.p_query_input = NULL;
1008219820Sjeff	req.sm_key = 0;
1009219820Sjeff
1010219820Sjeff	if ((status = osmv_query_sa(h, &req)) != IB_SUCCESS) {
1011219820Sjeff		fprintf(stderr, "ERROR: Query SA failed: %s\n",
1012219820Sjeff			ib_get_err_str(status));
1013219820Sjeff		return (status);
1014219820Sjeff	}
1015219820Sjeff	if (result.status != IB_SUCCESS) {
1016219820Sjeff		fprintf(stderr, "ERROR: Query result returned: %s\n",
1017219820Sjeff			ib_get_err_str(result.status));
1018219820Sjeff		return (result.status);
1019219820Sjeff	}
1020219820Sjeff	status = result.status;
1021219820Sjeff	dump_results(&result, dump_class_port_info);
1022219820Sjeff	return_mad();
1023219820Sjeff	return (status);
1024219820Sjeff}
1025219820Sjeff
1026219820Sjeffstatic int query_path_records(const struct query_cmd *q,
1027219820Sjeff			      osm_bind_handle_t h, int argc, char *argv[])
1028219820Sjeff{
1029219820Sjeff	ib_net16_t attr_offset = ib_get_attr_offset(sizeof(ib_path_rec_t));
1030219820Sjeff	ib_api_status_t status;
1031219820Sjeff
1032219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_PATH_RECORD, attr_offset, 0);
1033219820Sjeff	if (status != IB_SUCCESS)
1034219820Sjeff		return (status);
1035219820Sjeff
1036219820Sjeff	dump_results(&result, dump_path_record);
1037219820Sjeff	return_mad();
1038219820Sjeff	return (status);
1039219820Sjeff}
1040219820Sjeff
1041219820Sjeffstatic ib_api_status_t print_issm_records(osm_bind_handle_t h)
1042219820Sjeff{
1043219820Sjeff	ib_api_status_t status;
1044219820Sjeff
1045219820Sjeff	/* First, get IsSM records */
1046219820Sjeff	status = get_issm_records(h, IB_PORT_CAP_IS_SM);
1047219820Sjeff	if (status != IB_SUCCESS)
1048219820Sjeff		return (status);
1049219820Sjeff
1050219820Sjeff	printf("IsSM ports\n");
1051219820Sjeff	dump_results(&result, dump_portinfo_record);
1052219820Sjeff	return_mad();
1053219820Sjeff
1054219820Sjeff	/* Now, get IsSMdisabled records */
1055219820Sjeff	status = get_issm_records(h, IB_PORT_CAP_SM_DISAB);
1056219820Sjeff	if (status != IB_SUCCESS)
1057219820Sjeff		return (status);
1058219820Sjeff
1059219820Sjeff	printf("\nIsSMdisabled ports\n");
1060219820Sjeff	dump_results(&result, dump_portinfo_record);
1061219820Sjeff	return_mad();
1062219820Sjeff
1063219820Sjeff	return (status);
1064219820Sjeff}
1065219820Sjeff
1066219820Sjeffstatic ib_api_status_t print_multicast_member_records(osm_bind_handle_t h)
1067219820Sjeff{
1068219820Sjeff	osmv_query_res_t mc_group_result;
1069219820Sjeff	ib_api_status_t status;
1070219820Sjeff
1071219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_MCMEMBER_RECORD,
1072219820Sjeff				 ib_get_attr_offset(sizeof(ib_member_rec_t)),
1073219820Sjeff				 1);
1074219820Sjeff	if (status != IB_SUCCESS)
1075219820Sjeff		return (status);
1076219820Sjeff
1077219820Sjeff	mc_group_result = result;
1078219820Sjeff
1079219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_NODE_RECORD,
1080219820Sjeff				 ib_get_attr_offset(sizeof(ib_node_record_t)),
1081219820Sjeff				 0);
1082219820Sjeff	if (status != IB_SUCCESS)
1083219820Sjeff		goto return_mc;
1084219820Sjeff
1085219820Sjeff	dump_results(&mc_group_result, dump_multicast_member_record);
1086219820Sjeff	return_mad();
1087219820Sjeff
1088219820Sjeffreturn_mc:
1089219820Sjeff	/* return_mad for the mc_group_result */
1090219820Sjeff	if (mc_group_result.p_result_madw != NULL) {
1091219820Sjeff		osm_mad_pool_put(&mad_pool, mc_group_result.p_result_madw);
1092219820Sjeff		mc_group_result.p_result_madw = NULL;
1093219820Sjeff	}
1094219820Sjeff
1095219820Sjeff	return (status);
1096219820Sjeff}
1097219820Sjeff
1098219820Sjeffstatic ib_api_status_t print_multicast_group_records(osm_bind_handle_t h)
1099219820Sjeff{
1100219820Sjeff	ib_api_status_t status;
1101219820Sjeff
1102219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_MCMEMBER_RECORD,
1103219820Sjeff				 ib_get_attr_offset(sizeof(ib_member_rec_t)),
1104219820Sjeff				 0);
1105219820Sjeff	if (status != IB_SUCCESS)
1106219820Sjeff		return (status);
1107219820Sjeff
1108219820Sjeff	dump_results(&result, dump_multicast_group_record);
1109219820Sjeff	return_mad();
1110219820Sjeff	return (status);
1111219820Sjeff}
1112219820Sjeff
1113219820Sjeffstatic int query_class_port_info(const struct query_cmd *q,
1114219820Sjeff				 osm_bind_handle_t h, int argc, char *argv[])
1115219820Sjeff{
1116219820Sjeff	return get_print_class_port_info(h);
1117219820Sjeff}
1118219820Sjeff
1119219820Sjeffstatic int query_node_records(const struct query_cmd *q,
1120219820Sjeff			      osm_bind_handle_t h, int argc, char *argv[])
1121219820Sjeff{
1122219820Sjeff	return print_node_records(h);
1123219820Sjeff}
1124219820Sjeff
1125219820Sjeffstatic int query_portinfo_records(const struct query_cmd *q,
1126219820Sjeff				  osm_bind_handle_t h, int argc, char *argv[])
1127219820Sjeff{
1128219820Sjeff	ib_portinfo_record_t pir;
1129219820Sjeff	ib_net64_t comp_mask = 0;
1130219820Sjeff	int lid = 0, port = -1;
1131219820Sjeff	ib_api_status_t status;
1132219820Sjeff
1133219820Sjeff	if (argc > 0)
1134219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &port, NULL);
1135219820Sjeff
1136219820Sjeff	memset(&pir, 0, sizeof(pir));
1137219820Sjeff
1138219820Sjeff	if (lid > 0) {
1139219820Sjeff		pir.lid = cl_hton16(lid);
1140219820Sjeff		comp_mask |= IB_PIR_COMPMASK_LID;
1141219820Sjeff	}
1142219820Sjeff	if (port >= 0) {
1143219820Sjeff		pir.port_num = cl_hton16(port);
1144219820Sjeff		comp_mask |= IB_PIR_COMPMASK_PORTNUM;
1145219820Sjeff	}
1146219820Sjeff
1147219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_PORTINFO_RECORD, 0,
1148219820Sjeff				 comp_mask, &pir,
1149219820Sjeff				 ib_get_attr_offset(sizeof(pir)), 0);
1150219820Sjeff
1151219820Sjeff	if (status != IB_SUCCESS)
1152219820Sjeff		return status;
1153219820Sjeff
1154219820Sjeff	dump_results(&result, dump_one_portinfo_record);
1155219820Sjeff	return_mad();
1156219820Sjeff
1157219820Sjeff	return 0;
1158219820Sjeff}
1159219820Sjeff
1160219820Sjeffstatic int query_mcmember_records(const struct query_cmd *q,
1161219820Sjeff				   osm_bind_handle_t h, int argc, char *argv[])
1162219820Sjeff{
1163219820Sjeff	return print_multicast_member_records(h);
1164219820Sjeff}
1165219820Sjeff
1166219820Sjeffstatic int query_service_records(const struct query_cmd *q,
1167219820Sjeff				 osm_bind_handle_t h, int argc, char *argv[])
1168219820Sjeff{
1169219820Sjeff	ib_net16_t attr_offset =
1170219820Sjeff	    ib_get_attr_offset(sizeof(ib_service_record_t));
1171219820Sjeff	ib_api_status_t status;
1172219820Sjeff
1173219820Sjeff	status = get_all_records(h, IB_MAD_ATTR_SERVICE_RECORD, attr_offset, 0);
1174219820Sjeff	if (status != IB_SUCCESS)
1175219820Sjeff		return (status);
1176219820Sjeff
1177219820Sjeff	dump_results(&result, dump_service_record);
1178219820Sjeff	return_mad();
1179219820Sjeff	return (status);
1180219820Sjeff}
1181219820Sjeff
1182219820Sjeffstatic int query_informinfo_records(const struct query_cmd *q,
1183219820Sjeff				    osm_bind_handle_t h, int argc, char *argv[])
1184219820Sjeff{
1185219820Sjeff	ib_net16_t attr_offset =
1186219820Sjeff	    ib_get_attr_offset(sizeof(ib_inform_info_record_t));
1187219820Sjeff	ib_api_status_t status;
1188219820Sjeff
1189219820Sjeff	status =
1190219820Sjeff	    get_all_records(h, IB_MAD_ATTR_INFORM_INFO_RECORD, attr_offset, 0);
1191219820Sjeff	if (status != IB_SUCCESS)
1192219820Sjeff		return (status);
1193219820Sjeff
1194219820Sjeff	dump_results(&result, dump_inform_info_record);
1195219820Sjeff	return_mad();
1196219820Sjeff	return (status);
1197219820Sjeff}
1198219820Sjeff
1199219820Sjeffstatic int query_link_records(const struct query_cmd *q,
1200219820Sjeff			      osm_bind_handle_t h, int argc, char *argv[])
1201219820Sjeff{
1202219820Sjeff	ib_link_record_t lr;
1203219820Sjeff	ib_net64_t comp_mask = 0;
1204219820Sjeff	int from_lid = 0, to_lid = 0, from_port = -1, to_port = -1;
1205219820Sjeff	ib_api_status_t status;
1206219820Sjeff
1207219820Sjeff	if (argc > 0)
1208219820Sjeff		parse_lid_and_ports(h, argv[0], &from_lid, &from_port, NULL);
1209219820Sjeff
1210219820Sjeff	if (argc > 1)
1211219820Sjeff		parse_lid_and_ports(h, argv[1], &to_lid, &to_port, NULL);
1212219820Sjeff
1213219820Sjeff	memset(&lr, 0, sizeof(lr));
1214219820Sjeff
1215219820Sjeff	if (from_lid > 0) {
1216219820Sjeff		lr.from_lid = cl_hton16(from_lid);
1217219820Sjeff		comp_mask |= IB_LR_COMPMASK_FROM_LID;
1218219820Sjeff	}
1219219820Sjeff	if (from_port >= 0) {
1220219820Sjeff		lr.from_port_num = from_port;
1221219820Sjeff		comp_mask |= IB_LR_COMPMASK_FROM_PORT;
1222219820Sjeff	}
1223219820Sjeff	if (to_lid > 0) {
1224219820Sjeff		lr.to_lid = cl_hton16(to_lid);
1225219820Sjeff		comp_mask |= IB_LR_COMPMASK_TO_LID;
1226219820Sjeff	}
1227219820Sjeff	if (to_port >= 0) {
1228219820Sjeff		lr.to_port_num = to_port;
1229219820Sjeff		comp_mask |= IB_LR_COMPMASK_TO_PORT;
1230219820Sjeff	}
1231219820Sjeff
1232219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_LINK_RECORD, 0,
1233219820Sjeff				 comp_mask, &lr,
1234219820Sjeff				 ib_get_attr_offset(sizeof(lr)), 0);
1235219820Sjeff	if (status != IB_SUCCESS)
1236219820Sjeff		return status;
1237219820Sjeff
1238219820Sjeff	dump_results(&result, dump_one_link_record);
1239219820Sjeff	return_mad();
1240219820Sjeff	return status;
1241219820Sjeff}
1242219820Sjeff
1243219820Sjeffstatic int query_sl2vl_records(const struct query_cmd *q,
1244219820Sjeff			       osm_bind_handle_t h, int argc, char *argv[])
1245219820Sjeff{
1246219820Sjeff	ib_slvl_table_record_t slvl;
1247219820Sjeff	ib_net64_t comp_mask = 0;
1248219820Sjeff	int lid = 0, in_port = -1, out_port = -1;
1249219820Sjeff	ib_api_status_t status;
1250219820Sjeff
1251219820Sjeff	if (argc > 0)
1252219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &in_port, &out_port);
1253219820Sjeff
1254219820Sjeff	memset(&slvl, 0, sizeof(slvl));
1255219820Sjeff
1256219820Sjeff	if (lid > 0) {
1257219820Sjeff		slvl.lid = cl_hton16(lid);
1258219820Sjeff		comp_mask |= IB_SLVL_COMPMASK_LID;
1259219820Sjeff	}
1260219820Sjeff	if (in_port >= 0) {
1261219820Sjeff		slvl.in_port_num = in_port;
1262219820Sjeff		comp_mask |= IB_SLVL_COMPMASK_IN_PORT;
1263219820Sjeff	}
1264219820Sjeff	if (out_port >= 0) {
1265219820Sjeff		slvl.out_port_num = out_port;
1266219820Sjeff		comp_mask |= IB_SLVL_COMPMASK_OUT_PORT;
1267219820Sjeff	}
1268219820Sjeff
1269219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_SLVL_RECORD, 0,
1270219820Sjeff				 comp_mask, &slvl,
1271219820Sjeff				 ib_get_attr_offset(sizeof(slvl)), 0);
1272219820Sjeff	if (status != IB_SUCCESS)
1273219820Sjeff		return status;
1274219820Sjeff
1275219820Sjeff	dump_results(&result, dump_one_slvl_record);
1276219820Sjeff	return_mad();
1277219820Sjeff	return status;
1278219820Sjeff}
1279219820Sjeff
1280219820Sjeffstatic int query_vlarb_records(const struct query_cmd *q,
1281219820Sjeff			       osm_bind_handle_t h, int argc, char *argv[])
1282219820Sjeff{
1283219820Sjeff	ib_vl_arb_table_record_t vlarb;
1284219820Sjeff	ib_net64_t comp_mask = 0;
1285219820Sjeff	int lid = 0, port = -1, block = -1;
1286219820Sjeff	ib_api_status_t status;
1287219820Sjeff
1288219820Sjeff	if (argc > 0)
1289219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1290219820Sjeff
1291219820Sjeff	memset(&vlarb, 0, sizeof(vlarb));
1292219820Sjeff
1293219820Sjeff	if (lid > 0) {
1294219820Sjeff		vlarb.lid = cl_hton16(lid);
1295219820Sjeff		comp_mask |= IB_VLA_COMPMASK_LID;
1296219820Sjeff	}
1297219820Sjeff	if (port >= 0) {
1298219820Sjeff		vlarb.port_num = port;
1299219820Sjeff		comp_mask |= IB_VLA_COMPMASK_OUT_PORT;
1300219820Sjeff	}
1301219820Sjeff	if (block >= 0) {
1302219820Sjeff		vlarb.block_num = block;
1303219820Sjeff		comp_mask |= IB_VLA_COMPMASK_BLOCK;
1304219820Sjeff	}
1305219820Sjeff
1306219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_VLARB_RECORD, 0,
1307219820Sjeff				 comp_mask, &vlarb,
1308219820Sjeff				 ib_get_attr_offset(sizeof(vlarb)), 0);
1309219820Sjeff	if (status != IB_SUCCESS)
1310219820Sjeff		return status;
1311219820Sjeff
1312219820Sjeff	dump_results(&result, dump_one_vlarb_record);
1313219820Sjeff	return_mad();
1314219820Sjeff	return status;
1315219820Sjeff}
1316219820Sjeff
1317219820Sjeffstatic int query_pkey_tbl_records(const struct query_cmd *q,
1318219820Sjeff				  osm_bind_handle_t h, int argc, char *argv[])
1319219820Sjeff{
1320219820Sjeff	ib_pkey_table_record_t pktr;
1321219820Sjeff	ib_net64_t comp_mask = 0;
1322219820Sjeff	int lid = 0, port = -1, block = -1;
1323219820Sjeff	ib_api_status_t status;
1324219820Sjeff
1325219820Sjeff	if (argc > 0)
1326219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1327219820Sjeff
1328219820Sjeff	memset(&pktr, 0, sizeof(pktr));
1329219820Sjeff
1330219820Sjeff	if (lid > 0) {
1331219820Sjeff		pktr.lid = cl_hton16(lid);
1332219820Sjeff		comp_mask |= IB_PKEY_COMPMASK_LID;
1333219820Sjeff	}
1334219820Sjeff	if (port >= 0) {
1335219820Sjeff		pktr.port_num = port;
1336219820Sjeff		comp_mask |= IB_PKEY_COMPMASK_PORT;
1337219820Sjeff	}
1338219820Sjeff	if (block >= 0) {
1339219820Sjeff		pktr.block_num = block;
1340219820Sjeff		comp_mask |= IB_PKEY_COMPMASK_BLOCK;
1341219820Sjeff	}
1342219820Sjeff
1343219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_PKEY_TBL_RECORD, 0,
1344219820Sjeff				 comp_mask, &pktr,
1345219820Sjeff				 ib_get_attr_offset(sizeof(pktr)), smkey);
1346219820Sjeff	if (status != IB_SUCCESS)
1347219820Sjeff		return status;
1348219820Sjeff
1349219820Sjeff	dump_results(&result, dump_one_pkey_tbl_record);
1350219820Sjeff	return_mad();
1351219820Sjeff	return status;
1352219820Sjeff}
1353219820Sjeff
1354219820Sjeffstatic int query_lft_records(const struct query_cmd *q,
1355219820Sjeff			     osm_bind_handle_t h, int argc, char *argv[])
1356219820Sjeff{
1357219820Sjeff	ib_lft_record_t lftr;
1358219820Sjeff	ib_net64_t comp_mask = 0;
1359219820Sjeff	int lid = 0, block = -1;
1360219820Sjeff	ib_api_status_t status;
1361219820Sjeff
1362219820Sjeff	if (argc > 0)
1363219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
1364219820Sjeff
1365219820Sjeff	memset(&lftr, 0, sizeof(lftr));
1366219820Sjeff
1367219820Sjeff	if (lid > 0) {
1368219820Sjeff		lftr.lid = cl_hton16(lid);
1369219820Sjeff		comp_mask |= IB_LFTR_COMPMASK_LID;
1370219820Sjeff	}
1371219820Sjeff	if (block >= 0) {
1372219820Sjeff		lftr.block_num = cl_hton16(block);
1373219820Sjeff		comp_mask |= IB_LFTR_COMPMASK_BLOCK;
1374219820Sjeff	}
1375219820Sjeff
1376219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_LFT_RECORD, 0,
1377219820Sjeff				 comp_mask, &lftr,
1378219820Sjeff				 ib_get_attr_offset(sizeof(lftr)), 0);
1379219820Sjeff	if (status != IB_SUCCESS)
1380219820Sjeff		return status;
1381219820Sjeff
1382219820Sjeff	dump_results(&result, dump_one_lft_record);
1383219820Sjeff	return_mad();
1384219820Sjeff	return status;
1385219820Sjeff}
1386219820Sjeff
1387219820Sjeffstatic int query_mft_records(const struct query_cmd *q,
1388219820Sjeff			     osm_bind_handle_t h, int argc, char *argv[])
1389219820Sjeff{
1390219820Sjeff	ib_mft_record_t mftr;
1391219820Sjeff	ib_net64_t comp_mask = 0;
1392219820Sjeff	int lid = 0, block = -1, position = -1;
1393219820Sjeff	ib_api_status_t status;
1394219820Sjeff
1395219820Sjeff	if (argc > 0)
1396219820Sjeff		parse_lid_and_ports(h, argv[0], &lid, &position, &block);
1397219820Sjeff
1398219820Sjeff	memset(&mftr, 0, sizeof(mftr));
1399219820Sjeff
1400219820Sjeff	if (lid > 0) {
1401219820Sjeff		mftr.lid = cl_hton16(lid);
1402219820Sjeff		comp_mask |= IB_MFTR_COMPMASK_LID;
1403219820Sjeff	}
1404219820Sjeff	if (position >= 0) {
1405219820Sjeff		mftr.position_block_num = cl_hton16(position << 12);
1406219820Sjeff		comp_mask |= IB_MFTR_COMPMASK_POSITION;
1407219820Sjeff	}
1408219820Sjeff	if (block >= 0) {
1409219820Sjeff		mftr.position_block_num |=
1410219820Sjeff		    cl_hton16(block & IB_MCAST_BLOCK_ID_MASK_HO);
1411219820Sjeff		comp_mask |= IB_MFTR_COMPMASK_BLOCK;
1412219820Sjeff	}
1413219820Sjeff
1414219820Sjeff	status = get_any_records(h, IB_MAD_ATTR_MFT_RECORD, 0,
1415219820Sjeff				 comp_mask, &mftr,
1416219820Sjeff				 ib_get_attr_offset(sizeof(mftr)), 0);
1417219820Sjeff	if (status != IB_SUCCESS)
1418219820Sjeff		return status;
1419219820Sjeff
1420219820Sjeff	dump_results(&result, dump_one_mft_record);
1421219820Sjeff	return_mad();
1422219820Sjeff	return status;
1423219820Sjeff}
1424219820Sjeff
1425219820Sjeffstatic osm_bind_handle_t get_bind_handle(void)
1426219820Sjeff{
1427219820Sjeff	uint32_t i = 0;
1428219820Sjeff	uint64_t port_guid = (uint64_t) - 1;
1429219820Sjeff	osm_bind_handle_t h;
1430219820Sjeff	ib_api_status_t status;
1431219820Sjeff	ib_port_attr_t attr_array[MAX_PORTS];
1432219820Sjeff	uint32_t num_ports = MAX_PORTS;
1433219820Sjeff	uint32_t ca_name_index = 0;
1434219820Sjeff
1435219820Sjeff	complib_init();
1436219820Sjeff
1437219820Sjeff	osm_log_construct(&log_osm);
1438219820Sjeff	if ((status = osm_log_init_v2(&log_osm, TRUE, 0x0001, NULL,
1439219820Sjeff				      0, TRUE)) != IB_SUCCESS) {
1440219820Sjeff		fprintf(stderr, "Failed to init osm_log: %s\n",
1441219820Sjeff			ib_get_err_str(status));
1442219820Sjeff		exit(-1);
1443219820Sjeff	}
1444219820Sjeff	osm_log_set_level(&log_osm, OSM_LOG_NONE);
1445219820Sjeff	if (osm_debug)
1446219820Sjeff		osm_log_set_level(&log_osm, OSM_LOG_DEFAULT_LEVEL);
1447219820Sjeff
1448219820Sjeff	vendor = osm_vendor_new(&log_osm, sa_timeout_ms);
1449219820Sjeff	osm_mad_pool_construct(&mad_pool);
1450219820Sjeff	if ((status = osm_mad_pool_init(&mad_pool)) != IB_SUCCESS) {
1451219820Sjeff		fprintf(stderr, "Failed to init mad pool: %s\n",
1452219820Sjeff			ib_get_err_str(status));
1453219820Sjeff		exit(-1);
1454219820Sjeff	}
1455219820Sjeff
1456219820Sjeff	if ((status =
1457219820Sjeff	     osm_vendor_get_all_port_attr(vendor, attr_array,
1458219820Sjeff					  &num_ports)) != IB_SUCCESS) {
1459219820Sjeff		fprintf(stderr, "Failed to get port attributes: %s\n",
1460219820Sjeff			ib_get_err_str(status));
1461219820Sjeff		exit(-1);
1462219820Sjeff	}
1463219820Sjeff
1464219820Sjeff	for (i = 0; i < num_ports; i++) {
1465219820Sjeff		if (i > 1 && cl_ntoh64(attr_array[i].port_guid)
1466219820Sjeff		    != (cl_ntoh64(attr_array[i - 1].port_guid) + 1))
1467219820Sjeff			ca_name_index++;
1468219820Sjeff		if (sa_port_num && sa_port_num != attr_array[i].port_num)
1469219820Sjeff			continue;
1470219820Sjeff		if (sa_hca_name
1471219820Sjeff		    && strcmp(sa_hca_name,
1472219820Sjeff			      vendor->ca_names[ca_name_index]) != 0)
1473219820Sjeff			continue;
1474219820Sjeff		if (attr_array[i].link_state == IB_LINK_ACTIVE) {
1475219820Sjeff			port_guid = attr_array[i].port_guid;
1476219820Sjeff			break;
1477219820Sjeff		}
1478219820Sjeff	}
1479219820Sjeff
1480219820Sjeff	if (port_guid == (uint64_t) - 1) {
1481219820Sjeff		fprintf(stderr,
1482219820Sjeff			"Failed to find active port, check port status with \"ibstat\"\n");
1483219820Sjeff		exit(-1);
1484219820Sjeff	}
1485219820Sjeff
1486219820Sjeff	h = osmv_bind_sa(vendor, &mad_pool, port_guid);
1487219820Sjeff
1488219820Sjeff	if (h == OSM_BIND_INVALID_HANDLE) {
1489219820Sjeff		fprintf(stderr, "Failed to bind to SA\n");
1490219820Sjeff		exit(-1);
1491219820Sjeff	}
1492219820Sjeff	return h;
1493219820Sjeff}
1494219820Sjeff
1495219820Sjeffstatic void clean_up(void)
1496219820Sjeff{
1497219820Sjeff	osm_mad_pool_destroy(&mad_pool);
1498219820Sjeff	osm_vendor_delete(&vendor);
1499219820Sjeff}
1500219820Sjeff
1501219820Sjeffstatic const struct query_cmd query_cmds[] = {
1502219820Sjeff	{"ClassPortInfo", "CPI", IB_MAD_ATTR_CLASS_PORT_INFO,
1503219820Sjeff	 NULL, query_class_port_info},
1504219820Sjeff	{"NodeRecord", "NR", IB_MAD_ATTR_NODE_RECORD,
1505219820Sjeff	 NULL, query_node_records},
1506219820Sjeff	{"PortInfoRecord", "PIR", IB_MAD_ATTR_PORTINFO_RECORD,
1507219820Sjeff	 "[[lid]/[port]]", query_portinfo_records},
1508219820Sjeff	{"SL2VLTableRecord", "SL2VL", IB_MAD_ATTR_SLVL_RECORD,
1509219820Sjeff	 "[[lid]/[in_port]/[out_port]]", query_sl2vl_records},
1510219820Sjeff	{"PKeyTableRecord", "PKTR", IB_MAD_ATTR_PKEY_TBL_RECORD,
1511219820Sjeff	 "[[lid]/[port]/[block]]", query_pkey_tbl_records},
1512219820Sjeff	{"VLArbitrationTableRecord", "VLAR", IB_MAD_ATTR_VLARB_RECORD,
1513219820Sjeff	 "[[lid]/[port]/[block]]", query_vlarb_records},
1514219820Sjeff	{"InformInfoRecord", "IIR", IB_MAD_ATTR_INFORM_INFO_RECORD,
1515219820Sjeff	 NULL, query_informinfo_records},
1516219820Sjeff	{"LinkRecord", "LR", IB_MAD_ATTR_LINK_RECORD,
1517219820Sjeff	 "[[from_lid]/[from_port]] [[to_lid]/[to_port]]", query_link_records},
1518219820Sjeff	{"ServiceRecord", "SR", IB_MAD_ATTR_SERVICE_RECORD,
1519219820Sjeff	 NULL, query_service_records},
1520219820Sjeff	{"PathRecord", "PR", IB_MAD_ATTR_PATH_RECORD,
1521219820Sjeff	 NULL, query_path_records},
1522219820Sjeff	{"MCMemberRecord", "MCMR", IB_MAD_ATTR_MCMEMBER_RECORD,
1523219820Sjeff	 NULL, query_mcmember_records},
1524219820Sjeff	{"LFTRecord", "LFTR", IB_MAD_ATTR_LFT_RECORD,
1525219820Sjeff	 "[[lid]/[block]]", query_lft_records},
1526219820Sjeff	{"MFTRecord", "MFTR", IB_MAD_ATTR_MFT_RECORD,
1527219820Sjeff	 "[[mlid]/[position]/[block]]", query_mft_records},
1528219820Sjeff	{0}
1529219820Sjeff};
1530219820Sjeff
1531219820Sjeffstatic const struct query_cmd *find_query(const char *name)
1532219820Sjeff{
1533219820Sjeff	const struct query_cmd *q;
1534219820Sjeff	unsigned len = strlen(name);
1535219820Sjeff
1536219820Sjeff	for (q = query_cmds; q->name; q++)
1537219820Sjeff		if (!strncasecmp(name, q->name, len) ||
1538219820Sjeff		    (q->alias && !strncasecmp(name, q->alias, len)))
1539219820Sjeff			return q;
1540219820Sjeff
1541219820Sjeff	return NULL;
1542219820Sjeff}
1543219820Sjeff
1544219820Sjeffstatic const struct query_cmd *find_query_by_type(ib_net16_t type)
1545219820Sjeff{
1546219820Sjeff	const struct query_cmd *q;
1547219820Sjeff
1548219820Sjeff	for (q = query_cmds; q->name; q++)
1549219820Sjeff		if (q->query_type == type)
1550219820Sjeff			return q;
1551219820Sjeff
1552219820Sjeff	return NULL;
1553219820Sjeff}
1554219820Sjeff
1555219820Sjeffstatic void usage(void)
1556219820Sjeff{
1557219820Sjeff	const struct query_cmd *q;
1558219820Sjeff
1559219820Sjeff	fprintf(stderr, "Usage: %s [-h -d -p -N] [--list | -D] [-S -I -L -l -G"
1560219820Sjeff		" -O -U -c -s -g -m --src-to-dst <src:dst> --sgid-to-dgid <src-dst> "
1561219820Sjeff		"-C <ca_name> -P <ca_port> -t(imeout) <msec>] [query-name] [<name> | <lid> | <guid>]\n",
1562219820Sjeff		argv0);
1563219820Sjeff	fprintf(stderr, "   Queries node records by default\n");
1564219820Sjeff	fprintf(stderr, "   -d enable debugging\n");
1565219820Sjeff	fprintf(stderr, "   -p get PathRecord info\n");
1566219820Sjeff	fprintf(stderr, "   -N get NodeRecord info\n");
1567219820Sjeff	fprintf(stderr, "   --list | -D the node desc of the CA's\n");
1568219820Sjeff	fprintf(stderr, "   -S get ServiceRecord info\n");
1569219820Sjeff	fprintf(stderr, "   -I get InformInfoRecord (subscription) info\n");
1570219820Sjeff	fprintf(stderr, "   -L return the Lids of the name specified\n");
1571219820Sjeff	fprintf(stderr, "   -l return the unique Lid of the name specified\n");
1572219820Sjeff	fprintf(stderr, "   -G return the Guids of the name specified\n");
1573219820Sjeff	fprintf(stderr, "   -O return name for the Lid specified\n");
1574219820Sjeff	fprintf(stderr, "   -U return name for the Guid specified\n");
1575219820Sjeff	fprintf(stderr, "   -c get the SA's class port info\n");
1576219820Sjeff	fprintf(stderr, "   -s return the PortInfoRecords with isSM or "
1577219820Sjeff		"isSMdisabled capability mask bit on\n");
1578219820Sjeff	fprintf(stderr, "   -g get multicast group info\n");
1579219820Sjeff	fprintf(stderr, "   -m get multicast member info\n");
1580219820Sjeff	fprintf(stderr, "      (if multicast group specified, list member GIDs"
1581219820Sjeff		" only for group specified\n");
1582219820Sjeff	fprintf(stderr, "      specified, for example 'saquery -m 0xC000')\n");
1583219820Sjeff	fprintf(stderr, "   -x get LinkRecord info\n");
1584219820Sjeff	fprintf(stderr, "   --src-to-dst get a PathRecord for <src:dst>\n"
1585219820Sjeff		"                where src and dst are either node "
1586219820Sjeff		"names or LIDs\n");
1587219820Sjeff	fprintf(stderr, "   --sgid-to-dgid get a PathRecord for <sgid-dgid>\n"
1588219820Sjeff		"                where sgid and dgid are addresses in "
1589219820Sjeff		"IPv6 format\n");
1590219820Sjeff	fprintf(stderr, "   -C <ca_name> specify the SA query HCA\n");
1591219820Sjeff	fprintf(stderr, "   -P <ca_port> specify the SA query port\n");
1592219820Sjeff	fprintf(stderr, "   --smkey <val> specify SM_Key value for the query."
1593219820Sjeff		" If non-numeric value \n"
1594219820Sjeff		"                 (like 'x') is specified then "
1595219820Sjeff		"saquery will prompt for a value\n");
1596219820Sjeff	fprintf(stderr, "   -t | --timeout <msec> specify the SA query "
1597219820Sjeff		"response timeout (default %u msec)\n", DEFAULT_SA_TIMEOUT_MS);
1598219820Sjeff	fprintf(stderr,
1599219820Sjeff		"   --node-name-map <node-name-map> specify a node name map\n");
1600219820Sjeff	fprintf(stderr, "\n   Supported query names (and aliases):\n");
1601219820Sjeff	for (q = query_cmds; q->name; q++)
1602219820Sjeff		fprintf(stderr, "      %s (%s) %s\n", q->name,
1603219820Sjeff			q->alias ? q->alias : "", q->usage ? q->usage : "");
1604219820Sjeff	fprintf(stderr, "\n");
1605219820Sjeff
1606219820Sjeff	exit(-1);
1607219820Sjeff}
1608219820Sjeff
1609219820Sjeffenum saquery_command {
1610219820Sjeff	SAQUERY_CMD_QUERY,
1611219820Sjeff	SAQUERY_CMD_NODE_RECORD,
1612219820Sjeff	SAQUERY_CMD_PATH_RECORD,
1613219820Sjeff	SAQUERY_CMD_CLASS_PORT_INFO,
1614219820Sjeff	SAQUERY_CMD_ISSM,
1615219820Sjeff	SAQUERY_CMD_MCGROUPS,
1616219820Sjeff	SAQUERY_CMD_MCMEMBERS,
1617219820Sjeff};
1618219820Sjeff
1619219820Sjeffint main(int argc, char **argv)
1620219820Sjeff{
1621219820Sjeff	int ch = 0;
1622219820Sjeff	osm_bind_handle_t h;
1623219820Sjeff	enum saquery_command command = SAQUERY_CMD_QUERY;
1624219820Sjeff	const struct query_cmd *q = NULL;
1625219820Sjeff	char *src = NULL, *dst = NULL;
1626219820Sjeff	char *sgid = NULL, *dgid = NULL;
1627219820Sjeff	ib_net16_t query_type = 0;
1628219820Sjeff	ib_net16_t src_lid, dst_lid;
1629219820Sjeff	ib_api_status_t status;
1630219820Sjeff
1631219820Sjeff	static char const str_opts[] = "pVNDLlGOUcSIsgmxdhP:C:t:";
1632219820Sjeff	static const struct option long_opts[] = {
1633219820Sjeff		{"p", 0, 0, 'p'},
1634219820Sjeff		{"Version", 0, 0, 'V'},
1635219820Sjeff		{"N", 0, 0, 'N'},
1636219820Sjeff		{"L", 0, 0, 'L'},
1637219820Sjeff		{"l", 0, 0, 'l'},
1638219820Sjeff		{"G", 0, 0, 'G'},
1639219820Sjeff		{"O", 0, 0, 'O'},
1640219820Sjeff		{"U", 0, 0, 'U'},
1641219820Sjeff		{"s", 0, 0, 's'},
1642219820Sjeff		{"g", 0, 0, 'g'},
1643219820Sjeff		{"m", 0, 0, 'm'},
1644219820Sjeff		{"x", 0, 0, 'x'},
1645219820Sjeff		{"d", 0, 0, 'd'},
1646219820Sjeff		{"c", 0, 0, 'c'},
1647219820Sjeff		{"S", 0, 0, 'S'},
1648219820Sjeff		{"I", 0, 0, 'I'},
1649219820Sjeff		{"P", 1, 0, 'P'},
1650219820Sjeff		{"C", 1, 0, 'C'},
1651219820Sjeff		{"help", 0, 0, 'h'},
1652219820Sjeff		{"list", 0, 0, 'D'},
1653219820Sjeff		{"src-to-dst", 1, 0, 1},
1654219820Sjeff		{"sgid-to-dgid", 1, 0, 2},
1655219820Sjeff		{"timeout", 1, 0, 't'},
1656219820Sjeff		{"node-name-map", 1, 0, 3},
1657219820Sjeff		{"smkey", 1, 0, 4},
1658219820Sjeff		{}
1659219820Sjeff	};
1660219820Sjeff
1661219820Sjeff	argv0 = argv[0];
1662219820Sjeff
1663219820Sjeff	while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL)) != -1) {
1664219820Sjeff		switch (ch) {
1665219820Sjeff		case 1:
1666219820Sjeff			{
1667219820Sjeff				char *opt = strdup(optarg);
1668219820Sjeff				char *ch = strchr(opt, ':');
1669219820Sjeff				if (!ch) {
1670219820Sjeff					fprintf(stderr,
1671219820Sjeff						"ERROR: --src-to-dst <node>:<node>\n");
1672219820Sjeff					usage();
1673219820Sjeff				}
1674219820Sjeff				*ch++ = '\0';
1675219820Sjeff				if (*opt)
1676219820Sjeff					src = strdup(opt);
1677219820Sjeff				if (*ch)
1678219820Sjeff					dst = strdup(ch);
1679219820Sjeff				free(opt);
1680219820Sjeff				command = SAQUERY_CMD_PATH_RECORD;
1681219820Sjeff				break;
1682219820Sjeff			}
1683219820Sjeff		case 2:
1684219820Sjeff			{
1685219820Sjeff				char *opt = strdup(optarg);
1686219820Sjeff				char *tok1 = strtok(opt, "-");
1687219820Sjeff				char *tok2 = strtok(NULL, "\0");
1688219820Sjeff
1689219820Sjeff				if (tok1 && tok2) {
1690219820Sjeff					sgid = strdup(tok1);
1691219820Sjeff					dgid = strdup(tok2);
1692219820Sjeff				} else {
1693219820Sjeff					fprintf(stderr,
1694219820Sjeff						"ERROR: --sgid-to-dgid <GID>-<GID>\n");
1695219820Sjeff					usage();
1696219820Sjeff				}
1697219820Sjeff				free(opt);
1698219820Sjeff				command = SAQUERY_CMD_PATH_RECORD;
1699219820Sjeff				break;
1700219820Sjeff			}
1701219820Sjeff		case 3:
1702219820Sjeff			node_name_map_file = strdup(optarg);
1703219820Sjeff			break;
1704219820Sjeff		case 4:
1705219820Sjeff			if (!isxdigit(*optarg) &&
1706219820Sjeff			    !(optarg = getpass("SM_Key: "))) {
1707219820Sjeff				fprintf(stderr, "cannot get SM_Key\n");
1708219820Sjeff				usage();
1709219820Sjeff			}
1710219820Sjeff			smkey = cl_hton64(strtoull(optarg, NULL, 0));
1711219820Sjeff			break;
1712219820Sjeff		case 'p':
1713219820Sjeff			command = SAQUERY_CMD_PATH_RECORD;
1714219820Sjeff			break;
1715219820Sjeff		case 'V':
1716219820Sjeff			fprintf(stderr, "%s %s\n", argv0, get_build_version());
1717219820Sjeff			exit(-1);
1718219820Sjeff		case 'D':
1719219820Sjeff			node_print_desc = ALL_DESC;
1720219820Sjeff			break;
1721219820Sjeff		case 'c':
1722219820Sjeff			command = SAQUERY_CMD_CLASS_PORT_INFO;
1723219820Sjeff			break;
1724219820Sjeff		case 'S':
1725219820Sjeff			query_type = IB_MAD_ATTR_SERVICE_RECORD;
1726219820Sjeff			break;
1727219820Sjeff		case 'I':
1728219820Sjeff			query_type = IB_MAD_ATTR_INFORM_INFO_RECORD;
1729219820Sjeff			break;
1730219820Sjeff		case 'N':
1731219820Sjeff			command = SAQUERY_CMD_NODE_RECORD;
1732219820Sjeff			break;
1733219820Sjeff		case 'L':
1734219820Sjeff			node_print_desc = LID_ONLY;
1735219820Sjeff			break;
1736219820Sjeff		case 'l':
1737219820Sjeff			node_print_desc = UNIQUE_LID_ONLY;
1738219820Sjeff			break;
1739219820Sjeff		case 'G':
1740219820Sjeff			node_print_desc = GUID_ONLY;
1741219820Sjeff			break;
1742219820Sjeff		case 'O':
1743219820Sjeff			node_print_desc = NAME_OF_LID;
1744219820Sjeff			break;
1745219820Sjeff		case 'U':
1746219820Sjeff			node_print_desc = NAME_OF_GUID;
1747219820Sjeff			break;
1748219820Sjeff		case 's':
1749219820Sjeff			command = SAQUERY_CMD_ISSM;
1750219820Sjeff			break;
1751219820Sjeff		case 'g':
1752219820Sjeff			command = SAQUERY_CMD_MCGROUPS;
1753219820Sjeff			break;
1754219820Sjeff		case 'm':
1755219820Sjeff			command = SAQUERY_CMD_MCMEMBERS;
1756219820Sjeff			break;
1757219820Sjeff		case 'x':
1758219820Sjeff			query_type = IB_MAD_ATTR_LINK_RECORD;
1759219820Sjeff			break;
1760219820Sjeff		case 'd':
1761219820Sjeff			osm_debug = 1;
1762219820Sjeff			break;
1763219820Sjeff		case 'C':
1764219820Sjeff			sa_hca_name = optarg;
1765219820Sjeff			break;
1766219820Sjeff		case 'P':
1767219820Sjeff			sa_port_num = strtoul(optarg, NULL, 0);
1768219820Sjeff			break;
1769219820Sjeff		case 't':
1770219820Sjeff			sa_timeout_ms = strtoul(optarg, NULL, 0);
1771219820Sjeff			break;
1772219820Sjeff		case 'h':
1773219820Sjeff		default:
1774219820Sjeff			usage();
1775219820Sjeff		}
1776219820Sjeff	}
1777219820Sjeff	argc -= optind;
1778219820Sjeff	argv += optind;
1779219820Sjeff
1780219820Sjeff	if (!query_type) {
1781219820Sjeff		if (!argc || !(q = find_query(argv[0])))
1782219820Sjeff			query_type = IB_MAD_ATTR_NODE_RECORD;
1783219820Sjeff		else {
1784219820Sjeff			query_type = q->query_type;
1785219820Sjeff			argc--;
1786219820Sjeff			argv++;
1787219820Sjeff		}
1788219820Sjeff	}
1789219820Sjeff
1790219820Sjeff	if (argc) {
1791219820Sjeff		if (node_print_desc == NAME_OF_LID) {
1792219820Sjeff			requested_lid = (ib_net16_t) strtoul(argv[0], NULL, 0);
1793219820Sjeff			requested_lid_flag++;
1794219820Sjeff		} else if (node_print_desc == NAME_OF_GUID) {
1795219820Sjeff			requested_guid = (ib_net64_t) strtoul(argv[0], NULL, 0);
1796219820Sjeff			requested_guid_flag++;
1797219820Sjeff		} else {
1798219820Sjeff			requested_name = argv[0];
1799219820Sjeff		}
1800219820Sjeff	}
1801219820Sjeff
1802219820Sjeff	if ((node_print_desc == LID_ONLY ||
1803219820Sjeff	     node_print_desc == UNIQUE_LID_ONLY ||
1804219820Sjeff	     node_print_desc == GUID_ONLY) && !requested_name) {
1805219820Sjeff		fprintf(stderr, "ERROR: name not specified\n");
1806219820Sjeff		usage();
1807219820Sjeff	}
1808219820Sjeff
1809219820Sjeff	if (node_print_desc == NAME_OF_LID && !requested_lid_flag) {
1810219820Sjeff		fprintf(stderr, "ERROR: lid not specified\n");
1811219820Sjeff		usage();
1812219820Sjeff	}
1813219820Sjeff
1814219820Sjeff	if (node_print_desc == NAME_OF_GUID && !requested_guid_flag) {
1815219820Sjeff		fprintf(stderr, "ERROR: guid not specified\n");
1816219820Sjeff		usage();
1817219820Sjeff	}
1818219820Sjeff
1819219820Sjeff	/* Note: lid cannot be 0; see infiniband spec 4.1.3 */
1820219820Sjeff	if (node_print_desc == NAME_OF_LID && !requested_lid) {
1821219820Sjeff		fprintf(stderr, "ERROR: lid invalid\n");
1822219820Sjeff		usage();
1823219820Sjeff	}
1824219820Sjeff
1825219820Sjeff	h = get_bind_handle();
1826219820Sjeff	node_name_map = open_node_name_map(node_name_map_file);
1827219820Sjeff
1828219820Sjeff	switch (command) {
1829219820Sjeff	case SAQUERY_CMD_NODE_RECORD:
1830219820Sjeff		status = print_node_records(h);
1831219820Sjeff		break;
1832219820Sjeff	case SAQUERY_CMD_PATH_RECORD:
1833219820Sjeff		if (src && dst) {
1834219820Sjeff			src_lid = get_lid(h, src);
1835219820Sjeff			dst_lid = get_lid(h, dst);
1836219820Sjeff			printf("Path record for %s -> %s\n", src, dst);
1837219820Sjeff			if (src_lid == 0 || dst_lid == 0) {
1838219820Sjeff				status = IB_UNKNOWN_ERROR;
1839219820Sjeff			} else {
1840219820Sjeff				status =
1841219820Sjeff				    get_print_path_rec_lid(h, src_lid, dst_lid);
1842219820Sjeff			}
1843219820Sjeff		} else if (sgid && dgid) {
1844219820Sjeff			struct in6_addr src_addr, dst_addr;
1845219820Sjeff
1846219820Sjeff			if (inet_pton(AF_INET6, sgid, &src_addr) <= 0) {
1847219820Sjeff				fprintf(stderr, "invalid src gid: %s\n", sgid);
1848219820Sjeff				exit(-1);
1849219820Sjeff			}
1850219820Sjeff			if (inet_pton(AF_INET6, dgid, &dst_addr) <= 0) {
1851219820Sjeff				fprintf(stderr, "invalid dst gid: %s\n", dgid);
1852219820Sjeff				exit(-1);
1853219820Sjeff			}
1854219820Sjeff			status = get_print_path_rec_gid(h,
1855219820Sjeff					(ib_gid_t *) & src_addr.s6_addr,
1856219820Sjeff					(ib_gid_t *) & dst_addr.s6_addr);
1857219820Sjeff		} else {
1858219820Sjeff			status = query_path_records(q, h, 0, NULL);
1859219820Sjeff		}
1860219820Sjeff		break;
1861219820Sjeff	case SAQUERY_CMD_CLASS_PORT_INFO:
1862219820Sjeff		status = get_print_class_port_info(h);
1863219820Sjeff		break;
1864219820Sjeff	case SAQUERY_CMD_ISSM:
1865219820Sjeff		status = print_issm_records(h);
1866219820Sjeff		break;
1867219820Sjeff	case SAQUERY_CMD_MCGROUPS:
1868219820Sjeff		status = print_multicast_group_records(h);
1869219820Sjeff		break;
1870219820Sjeff	case SAQUERY_CMD_MCMEMBERS:
1871219820Sjeff		status = print_multicast_member_records(h);
1872219820Sjeff		break;
1873219820Sjeff	default:
1874219820Sjeff		if ((!q && !(q = find_query_by_type(query_type)))
1875219820Sjeff		    || !q->handler) {
1876219820Sjeff			fprintf(stderr, "Unknown query type %d\n",
1877219820Sjeff				ntohs(query_type));
1878219820Sjeff			status = IB_UNKNOWN_ERROR;
1879219820Sjeff		} else
1880219820Sjeff			status = q->handler(q, h, argc, argv);
1881219820Sjeff		break;
1882219820Sjeff	}
1883219820Sjeff
1884219820Sjeff	if (src)
1885219820Sjeff		free(src);
1886219820Sjeff	if (dst)
1887219820Sjeff		free(dst);
1888219820Sjeff	clean_up();
1889219820Sjeff	close_node_name_map(node_name_map);
1890219820Sjeff	return (status);
1891219820Sjeff}
1892