]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/infiniband-diags/src/saquery.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / infiniband-diags / src / saquery.c
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 <infiniband/opensm/osm_log.h>
54 #include <infiniband/vendor/osm_vendor_api.h>
55 #include <infiniband/vendor/osm_vendor_sa_api.h>
56 #include <infiniband/opensm/osm_mad_pool.h>
57 #include <infiniband/complib/cl_debug.h>
58 #include <infiniband/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
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  */
125 static void query_res_cb(osmv_query_res_t * res)
126 {
127         result = *res;
128 }
129
130 static void print_node_desc(ib_node_record_t * node_record)
131 {
132         ib_node_info_t *p_ni = &(node_record->node_info);
133         ib_node_desc_t *p_nd = &(node_record->node_desc);
134
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }