ib-mgmt: update to 518083dc46963eb5fb48855acbe2b351ce7361f8
[mirror/winof/.git] / tools / 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 #if HAVE_CONFIG_H
41 #  include <config.h>
42 #endif /* HAVE_CONFIG_H */
43
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <arpa/inet.h>
47 #include <ctype.h>
48 #include <string.h>
49 #include <errno.h>
50 #include <assert.h>
51
52 #define _GNU_SOURCE
53 #include <getopt.h>
54
55 #include <infiniband/umad.h>
56 #include <infiniband/mad.h>
57 #include <iba/ib_types.h>
58 #include <complib/cl_nodenamemap.h>
59
60 #include "ibdiag_common.h"
61
62 struct bind_handle {
63         int fd, agent;
64         ib_portid_t dport;
65 };
66
67 struct query_res {
68         int status;
69         unsigned result_cnt;
70         void *p_result_madw;
71 };
72
73 typedef struct bind_handle * bind_handle_t;
74
75 struct query_params {
76         ib_gid_t sgid, dgid, gid, mgid;
77         uint16_t slid, dlid, mlid;
78         uint32_t flow_label;
79         int hop_limit;
80         uint8_t tclass;
81         int reversible, numb_path;
82         uint16_t pkey;
83         int qos_class, sl;
84         uint8_t mtu, rate, pkt_life;
85         uint32_t qkey;
86         uint8_t scope;
87         uint8_t join_state;
88         int proxy_join;
89 };
90
91 struct query_cmd {
92         const char *name, *alias;
93         uint16_t query_type;
94         const char *usage;
95         int (*handler) (const struct query_cmd * q, bind_handle_t h,
96                         struct query_params *p, int argc, char *argv[]);
97 };
98
99 static char *node_name_map_file = NULL;
100 static nn_map_t *node_name_map = NULL;
101 static uint64_t smkey = 1;
102
103 /**
104  * Declare some globals because I don't want this to be too complex.
105  */
106 #define MAX_PORTS (8)
107 #define DEFAULT_SA_TIMEOUT_MS (1000)
108 static struct query_res result;
109
110 enum {
111         ALL,
112         LID_ONLY,
113         UNIQUE_LID_ONLY,
114         GUID_ONLY,
115         ALL_DESC,
116         NAME_OF_LID,
117         NAME_OF_GUID,
118 } node_print_desc = ALL;
119
120 char *requested_name = NULL;
121 uint16_t requested_lid = 0;
122 int requested_lid_flag = 0;
123 uint64_t requested_guid = 0;
124 int requested_guid_flag = 0;
125
126 static int sa_query(struct bind_handle *h, uint8_t method,
127                     uint16_t attr, uint32_t mod, uint64_t comp_mask,
128                     uint64_t sm_key, void *data)
129 {
130         ib_rpc_t rpc;
131         void *umad, *mad;
132         int ret, offset, len = 256;
133
134         memset(&rpc, 0, sizeof(rpc));
135         rpc.mgtclass = IB_SA_CLASS;
136         rpc.method = method;
137         rpc.attr.id = attr;
138         rpc.attr.mod = mod;
139         rpc.mask = comp_mask;
140         rpc.datasz = IB_SA_DATA_SIZE;
141         rpc.dataoffs = IB_SA_DATA_OFFS;
142
143         umad = calloc(1, len + umad_size());
144         if (!umad)
145                 IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
146
147         mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
148
149         mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
150
151         if (ibdebug > 1)
152                 xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
153
154         ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
155         if (ret < 0)
156                 IBPANIC("umad_send failed: attr %u: %s\n",
157                         attr, strerror(errno));
158
159 recv_mad:
160         ret = umad_recv(h->fd, umad, &len, ibd_timeout);
161         if (ret < 0) {
162                 if (errno == ENOSPC) {
163                         umad = realloc(umad, umad_size() + len);
164                         goto recv_mad;
165                 }
166                 IBPANIC("umad_recv failed: attr 0x%x: %s\n", attr,
167                         strerror(errno));
168         }
169
170         if ((ret = umad_status(umad)))
171                 return ret;
172
173         mad = umad_get_mad(umad);
174
175         if (ibdebug > 1)
176                 xdump(stdout, "SA Response:\n", mad, len);
177
178         method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
179         offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
180         result.status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
181         result.p_result_madw = mad;
182         if (result.status)
183                 result.result_cnt = 0;
184         else if (method != IB_MAD_METHOD_GET_TABLE)
185                 result.result_cnt = 1;
186         else if (!offset)
187                 result.result_cnt = 0;
188         else
189                 result.result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
190
191         return 0;
192 }
193
194 static void *get_query_rec(void *mad, unsigned i)
195 {
196         int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
197         return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
198 }
199
200 static unsigned valid_gid(ib_gid_t *gid)
201 {
202         ib_gid_t zero_gid;
203         memset(&zero_gid, 0, sizeof zero_gid);
204         return memcmp(&zero_gid, gid, sizeof(*gid));
205 }
206
207 static void format_buf(char *in, char *out, unsigned size)
208 {
209         unsigned i;
210
211         for (i = 0; i < size - 3 && *in; i++) {
212                 *out++ = *in;
213                 if (*in++ == '\n' && *in) {
214                         *out++ = '\t';
215                         *out++ = '\t';
216                 }
217         }
218         *out = '\0';
219 }
220
221 static void print_node_desc(ib_node_record_t * node_record)
222 {
223         ib_node_info_t *p_ni = &(node_record->node_info);
224         ib_node_desc_t *p_nd = &(node_record->node_desc);
225
226         if (p_ni->node_type == IB_NODE_TYPE_CA)
227                 printf("%6d  \"%s\"\n", cl_ntoh16(node_record->lid),
228                        clean_nodedesc((char *)p_nd->description));
229 }
230
231 static void dump_node_record(void *data)
232 {
233         ib_node_record_t *nr = data;
234         ib_node_info_t *ni = &nr->node_info;
235
236         printf("NodeRecord dump:\n"
237                "\t\tlid.....................0x%X\n"
238                "\t\treserved................0x%X\n"
239                "\t\tbase_version............0x%X\n"
240                "\t\tclass_version...........0x%X\n"
241                "\t\tnode_type...............%s\n"
242                "\t\tnum_ports...............0x%X\n"
243                "\t\tsys_guid................0x%016" PRIx64 "\n"
244                "\t\tnode_guid...............0x%016" PRIx64 "\n"
245                "\t\tport_guid...............0x%016" PRIx64 "\n"
246                "\t\tpartition_cap...........0x%X\n"
247                "\t\tdevice_id...............0x%X\n"
248                "\t\trevision................0x%X\n"
249                "\t\tport_num................0x%X\n"
250                "\t\tvendor_id...............0x%X\n"
251                "\t\tNodeDescription.........%s\n",
252                cl_ntoh16(nr->lid), cl_ntoh16(nr->resv),
253                ni->base_version, ni->class_version,
254                ib_get_node_type_str(ni->node_type), ni->num_ports,
255                cl_ntoh64(ni->sys_guid), cl_ntoh64(ni->node_guid),
256                cl_ntoh64(ni->port_guid), cl_ntoh16(ni->partition_cap),
257                cl_ntoh16(ni->device_id), cl_ntoh32(ni->revision),
258                ib_node_info_get_local_port_num(ni),
259                cl_ntoh32(ib_node_info_get_vendor_id(ni)),
260                clean_nodedesc((char *)nr->node_desc.description));
261 }
262
263 static void print_node_record(ib_node_record_t * node_record)
264 {
265         ib_node_info_t *p_ni = &node_record->node_info;
266         ib_node_desc_t *p_nd = &node_record->node_desc;
267         char *name;
268
269         switch (node_print_desc) {
270         case LID_ONLY:
271         case UNIQUE_LID_ONLY:
272                 printf("%d\n", cl_ntoh16(node_record->lid));
273                 return;
274         case GUID_ONLY:
275                 printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
276                 return;
277         case NAME_OF_LID:
278         case NAME_OF_GUID:
279                 name = remap_node_name(node_name_map,
280                                        cl_ntoh64(p_ni->node_guid),
281                                        (char *)p_nd->description);
282                 printf("%s\n", name);
283                 free(name);
284                 return;
285         case ALL:
286         default:
287                 break;
288         }
289
290         dump_node_record(node_record);
291 }
292
293 static void dump_path_record(void *data)
294 {
295         char gid_str[INET6_ADDRSTRLEN];
296         char gid_str2[INET6_ADDRSTRLEN];
297         ib_path_rec_t *p_pr = data;
298         printf("PathRecord dump:\n"
299                "\t\tservice_id..............0x%016" PRIx64 "\n"
300                "\t\tdgid....................%s\n"
301                "\t\tsgid....................%s\n"
302                "\t\tdlid....................0x%X\n"
303                "\t\tslid....................0x%X\n"
304                "\t\thop_flow_raw............0x%X\n"
305                "\t\ttclass..................0x%X\n"
306                "\t\tnum_path_revers.........0x%X\n"
307                "\t\tpkey....................0x%X\n"
308                "\t\tqos_class...............0x%X\n"
309                "\t\tsl......................0x%X\n"
310                "\t\tmtu.....................0x%X\n"
311                "\t\trate....................0x%X\n"
312                "\t\tpkt_life................0x%X\n"
313                "\t\tpreference..............0x%X\n"
314                "\t\tresv2...................0x%X\n"
315                "\t\tresv3...................0x%X\n",
316                cl_ntoh64(p_pr->service_id),
317                inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),
318                inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),
319                cl_ntoh16(p_pr->dlid), cl_ntoh16(p_pr->slid),
320                cl_ntoh32(p_pr->hop_flow_raw), p_pr->tclass, p_pr->num_path,
321                cl_ntoh16(p_pr->pkey), ib_path_rec_qos_class(p_pr),
322                ib_path_rec_sl(p_pr), p_pr->mtu, p_pr->rate, p_pr->pkt_life,
323                p_pr->preference,
324                *(uint32_t *) & p_pr->resv2, *((uint16_t *) & p_pr->resv2 + 2));
325 }
326
327 static void dump_class_port_info(void *data)
328 {
329         char gid_str[INET6_ADDRSTRLEN];
330         char gid_str2[INET6_ADDRSTRLEN];
331         ib_class_port_info_t *cpi = data;
332
333         printf("SA ClassPortInfo:\n"
334                "\t\tBase version.............%d\n"
335                "\t\tClass version............%d\n"
336                "\t\tCapability mask..........0x%04X\n"
337                "\t\tCapability mask 2........0x%08X\n"
338                "\t\tResponse time value......0x%02X\n"
339                "\t\tRedirect GID.............%s\n"
340                "\t\tRedirect TC/SL/FL........0x%08X\n"
341                "\t\tRedirect LID.............%u\n"
342                "\t\tRedirect PKey............0x%04X\n"
343                "\t\tRedirect QP..............0x%08X\n"
344                "\t\tRedirect QKey............0x%08X\n"
345                "\t\tTrap GID.................%s\n"
346                "\t\tTrap TC/SL/FL............0x%08X\n"
347                "\t\tTrap LID.................%u\n"
348                "\t\tTrap PKey................0x%04X\n"
349                "\t\tTrap HL/QP...............0x%08X\n"
350                "\t\tTrap QKey................0x%08X\n",
351                cpi->base_ver, cpi->class_ver, cl_ntoh16(cpi->cap_mask),
352                ib_class_cap_mask2(cpi), ib_class_resp_time_val(cpi),
353                inet_ntop(AF_INET6, &(cpi->redir_gid), gid_str, sizeof gid_str),
354                cl_ntoh32(cpi->redir_tc_sl_fl), cl_ntoh16(cpi->redir_lid),
355                cl_ntoh16(cpi->redir_pkey), cl_ntoh32(cpi->redir_qp),
356                cl_ntoh32(cpi->redir_qkey),
357                inet_ntop(AF_INET6, &(cpi->trap_gid), gid_str2, sizeof gid_str2),
358                cl_ntoh32(cpi->trap_tc_sl_fl), cl_ntoh16(cpi->trap_lid),
359                cl_ntoh16(cpi->trap_pkey), cl_ntoh32(cpi->trap_hop_qp),
360                cl_ntoh32(cpi->trap_qkey));
361 }
362
363 static void dump_portinfo_record(void *data)
364 {
365         ib_portinfo_record_t *p_pir = data;
366         const ib_port_info_t *const p_pi = &p_pir->port_info;
367
368         printf("PortInfoRecord dump:\n"
369                "\t\tEndPortLid..............%u\n"
370                "\t\tPortNum.................0x%X\n"
371                "\t\tbase_lid................0x%X\n"
372                "\t\tmaster_sm_base_lid......0x%X\n"
373                "\t\tcapability_mask.........0x%X\n",
374                cl_ntoh16(p_pir->lid), p_pir->port_num,
375                cl_ntoh16(p_pi->base_lid), cl_ntoh16(p_pi->master_sm_base_lid),
376                cl_ntoh32(p_pi->capability_mask));
377 }
378
379 static void dump_one_portinfo_record(void *data)
380 {
381         char buf[2048], buf2[4096];
382         ib_portinfo_record_t *pir = data;
383         ib_port_info_t *pi = &pir->port_info;
384
385         mad_dump_portinfo(buf, sizeof(buf), pi, sizeof(*pi));
386         format_buf(buf, buf2, sizeof(buf2));
387         printf("PortInfoRecord dump:\n"
388                 "\tRID:\n"
389                 "\t\tEndPortLid..............%u\n"
390                 "\t\tPortNum.................0x%x\n"
391                 "\t\tReserved................0x%x\n"
392                 "\tPortInfo dump:\n\t\t%s",
393                 cl_ntoh16(pir->lid), pir->port_num, pir->resv, buf2);
394 }
395
396 static void dump_one_mcmember_record(void *data)
397 {
398         char mgid[INET6_ADDRSTRLEN], gid[INET6_ADDRSTRLEN];
399         ib_member_rec_t *mr = data;
400         uint32_t flow;
401         uint8_t sl, hop, scope, join;
402         ib_member_get_sl_flow_hop(mr->sl_flow_hop, &sl, &flow, &hop);
403         ib_member_get_scope_state(mr->scope_state, &scope, &join);
404         printf("MCMember Record dump:\n"
405                "\t\tMGID....................%s\n"
406                "\t\tPortGid.................%s\n"
407                "\t\tqkey....................0x%x\n"
408                "\t\tmlid....................0x%x\n"
409                "\t\tmtu.....................0x%x\n"
410                "\t\tTClass..................0x%x\n"
411                "\t\tpkey....................0x%x\n"
412                "\t\trate....................0x%x\n"
413                "\t\tpkt_life................0x%x\n"
414                "\t\tSL......................0x%x\n"
415                "\t\tFlowLabel...............0x%x\n"
416                "\t\tHopLimit................0x%x\n"
417                "\t\tScope...................0x%x\n"
418                "\t\tJoinState...............0x%x\n"
419                "\t\tProxyJoin...............0x%x\n",
420                inet_ntop(AF_INET6, mr->mgid.raw, mgid, sizeof(mgid)),
421                inet_ntop(AF_INET6, mr->port_gid.raw, gid, sizeof(gid)),
422                cl_ntoh32(mr->qkey), cl_ntoh16(mr->mlid), mr->mtu, mr->tclass,
423                cl_ntoh16(mr->pkey), mr->rate, mr->pkt_life, sl,
424                cl_ntoh32(flow), hop, scope, join, mr->proxy_join);
425 }
426
427 static void dump_multicast_group_record(void *data)
428 {
429         char gid_str[INET6_ADDRSTRLEN];
430         ib_member_rec_t *p_mcmr = data;
431         uint8_t sl;
432         ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &sl, NULL, NULL);
433         printf("MCMemberRecord group dump:\n"
434                "\t\tMGID....................%s\n"
435                "\t\tMlid....................0x%X\n"
436                "\t\tMtu.....................0x%X\n"
437                "\t\tpkey....................0x%X\n"
438                "\t\tRate....................0x%X\n"
439                "\t\tSL......................0x%X\n",
440                inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str),
441                cl_ntoh16(p_mcmr->mlid),
442                p_mcmr->mtu, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, sl);
443 }
444
445 static void dump_multicast_member_record(void *data)
446 {
447         char gid_str[INET6_ADDRSTRLEN];
448         char gid_str2[INET6_ADDRSTRLEN];
449         ib_member_rec_t *p_mcmr = data;
450         uint16_t mlid = cl_ntoh16(p_mcmr->mlid);
451         unsigned i = 0;
452         char *node_name = "<unknown>";
453
454         /* go through the node records searching for a port guid which matches
455          * this port gid interface id.
456          * This gives us a node name to print, if available.
457          */
458         for (i = 0; i < result.result_cnt; i++) {
459                 ib_node_record_t *nr =
460                     get_query_rec(result.p_result_madw, i);
461                 if (nr->node_info.port_guid ==
462                     p_mcmr->port_gid.unicast.interface_id) {
463                         node_name =
464                             clean_nodedesc((char *)nr->node_desc.description);
465                         break;
466                 }
467         }
468
469         if (requested_name) {
470                 if (strtol(requested_name, NULL, 0) == mlid)
471                         printf("\t\tPortGid.................%s (%s)\n",
472                                inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
473                                          gid_str, sizeof gid_str), node_name);
474         } else {
475                 printf("MCMemberRecord member dump:\n"
476                        "\t\tMGID....................%s\n"
477                        "\t\tMlid....................0x%X\n"
478                        "\t\tPortGid.................%s\n"
479                        "\t\tScopeState..............0x%X\n"
480                        "\t\tProxyJoin...............0x%X\n"
481                        "\t\tNodeDescription.........%s\n",
482                        inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,
483                                  sizeof gid_str),
484                        cl_ntoh16(p_mcmr->mlid),
485                        inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
486                                  gid_str2, sizeof gid_str2),
487                        p_mcmr->scope_state, p_mcmr->proxy_join, node_name);
488         }
489 }
490
491 static void dump_service_record(void *data)
492 {
493         char gid[INET6_ADDRSTRLEN];
494         char buf_service_key[35];
495         char buf_service_name[65];
496         ib_service_record_t *p_sr = data;
497
498         sprintf(buf_service_key,
499                 "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
500                 p_sr->service_key[0], p_sr->service_key[1],
501                 p_sr->service_key[2], p_sr->service_key[3],
502                 p_sr->service_key[4], p_sr->service_key[5],
503                 p_sr->service_key[6], p_sr->service_key[7],
504                 p_sr->service_key[8], p_sr->service_key[9],
505                 p_sr->service_key[10], p_sr->service_key[11],
506                 p_sr->service_key[12], p_sr->service_key[13],
507                 p_sr->service_key[14], p_sr->service_key[15]);
508         strncpy(buf_service_name, (char *)p_sr->service_name, 64);
509         buf_service_name[64] = '\0';
510
511         printf("ServiceRecord dump:\n"
512                "\t\tServiceID...............0x%016" PRIx64 "\n"
513                "\t\tServiceGID..............%s\n"
514                "\t\tServiceP_Key............0x%X\n"
515                "\t\tServiceLease............0x%X\n"
516                "\t\tServiceKey..............%s\n"
517                "\t\tServiceName.............%s\n"
518                "\t\tServiceData8.1..........0x%X\n"
519                "\t\tServiceData8.2..........0x%X\n"
520                "\t\tServiceData8.3..........0x%X\n"
521                "\t\tServiceData8.4..........0x%X\n"
522                "\t\tServiceData8.5..........0x%X\n"
523                "\t\tServiceData8.6..........0x%X\n"
524                "\t\tServiceData8.7..........0x%X\n"
525                "\t\tServiceData8.8..........0x%X\n"
526                "\t\tServiceData8.9..........0x%X\n"
527                "\t\tServiceData8.10.........0x%X\n"
528                "\t\tServiceData8.11.........0x%X\n"
529                "\t\tServiceData8.12.........0x%X\n"
530                "\t\tServiceData8.13.........0x%X\n"
531                "\t\tServiceData8.14.........0x%X\n"
532                "\t\tServiceData8.15.........0x%X\n"
533                "\t\tServiceData8.16.........0x%X\n"
534                "\t\tServiceData16.1.........0x%X\n"
535                "\t\tServiceData16.2.........0x%X\n"
536                "\t\tServiceData16.3.........0x%X\n"
537                "\t\tServiceData16.4.........0x%X\n"
538                "\t\tServiceData16.5.........0x%X\n"
539                "\t\tServiceData16.6.........0x%X\n"
540                "\t\tServiceData16.7.........0x%X\n"
541                "\t\tServiceData16.8.........0x%X\n"
542                "\t\tServiceData32.1.........0x%X\n"
543                "\t\tServiceData32.2.........0x%X\n"
544                "\t\tServiceData32.3.........0x%X\n"
545                "\t\tServiceData32.4.........0x%X\n"
546                "\t\tServiceData64.1.........0x%016" PRIx64 "\n"
547                "\t\tServiceData64.2.........0x%016" PRIx64 "\n",
548                cl_ntoh64(p_sr->service_id),
549                inet_ntop(AF_INET6, p_sr->service_gid.raw, gid, sizeof gid),
550                cl_ntoh16(p_sr->service_pkey), cl_ntoh32(p_sr->service_lease),
551                buf_service_key, buf_service_name,
552                p_sr->service_data8[0], p_sr->service_data8[1],
553                p_sr->service_data8[2], p_sr->service_data8[3],
554                p_sr->service_data8[4], p_sr->service_data8[5],
555                p_sr->service_data8[6], p_sr->service_data8[7],
556                p_sr->service_data8[8], p_sr->service_data8[9],
557                p_sr->service_data8[10], p_sr->service_data8[11],
558                p_sr->service_data8[12], p_sr->service_data8[13],
559                p_sr->service_data8[14], p_sr->service_data8[15],
560                cl_ntoh16(p_sr->service_data16[0]),
561                cl_ntoh16(p_sr->service_data16[1]),
562                cl_ntoh16(p_sr->service_data16[2]),
563                cl_ntoh16(p_sr->service_data16[3]),
564                cl_ntoh16(p_sr->service_data16[4]),
565                cl_ntoh16(p_sr->service_data16[5]),
566                cl_ntoh16(p_sr->service_data16[6]),
567                cl_ntoh16(p_sr->service_data16[7]),
568                cl_ntoh32(p_sr->service_data32[0]),
569                cl_ntoh32(p_sr->service_data32[1]),
570                cl_ntoh32(p_sr->service_data32[2]),
571                cl_ntoh32(p_sr->service_data32[3]),
572                cl_ntoh64(p_sr->service_data64[0]),
573                cl_ntoh64(p_sr->service_data64[1]));
574 }
575
576 static void dump_inform_info_record(void *data)
577 {
578         char gid_str[INET6_ADDRSTRLEN];
579         char gid_str2[INET6_ADDRSTRLEN];
580         ib_inform_info_record_t *p_iir = data;
581         uint32_t qpn;
582         uint8_t resp_time_val;
583
584         ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.
585                                          qpn_resp_time_val, &qpn,
586                                          &resp_time_val);
587         if (p_iir->inform_info.is_generic)
588                 printf("InformInfoRecord dump:\n"
589                        "\t\tRID\n"
590                        "\t\tSubscriberGID...........%s\n"
591                        "\t\tSubscriberEnum..........0x%X\n"
592                        "\t\tInformInfo dump:\n"
593                        "\t\tgid.....................%s\n"
594                        "\t\tlid_range_begin.........0x%X\n"
595                        "\t\tlid_range_end...........0x%X\n"
596                        "\t\tis_generic..............0x%X\n"
597                        "\t\tsubscribe...............0x%X\n"
598                        "\t\ttrap_type...............0x%X\n"
599                        "\t\ttrap_num................%u\n"
600                        "\t\tqpn.....................0x%06X\n"
601                        "\t\tresp_time_val...........0x%X\n"
602                        "\t\tnode_type...............0x%06X\n",
603                        inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
604                                  sizeof gid_str),
605                        cl_ntoh16(p_iir->subscriber_enum),
606                        inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2,
607                                  sizeof gid_str2),
608                        cl_ntoh16(p_iir->inform_info.lid_range_begin),
609                        cl_ntoh16(p_iir->inform_info.lid_range_end),
610                        p_iir->inform_info.is_generic,
611                        p_iir->inform_info.subscribe,
612                        cl_ntoh16(p_iir->inform_info.trap_type),
613                        cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num),
614                        cl_ntoh32(qpn), resp_time_val,
615                        cl_ntoh32(ib_inform_info_get_prod_type
616                                  (&p_iir->inform_info)));
617         else
618                 printf("InformInfoRecord dump:\n"
619                        "\t\tRID\n"
620                        "\t\tSubscriberGID...........%s\n"
621                        "\t\tSubscriberEnum..........0x%X\n"
622                        "\t\tInformInfo dump:\n"
623                        "\t\tgid.....................%s\n"
624                        "\t\tlid_range_begin.........0x%X\n"
625                        "\t\tlid_range_end...........0x%X\n"
626                        "\t\tis_generic..............0x%X\n"
627                        "\t\tsubscribe...............0x%X\n"
628                        "\t\ttrap_type...............0x%X\n"
629                        "\t\tdev_id..................0x%X\n"
630                        "\t\tqpn.....................0x%06X\n"
631                        "\t\tresp_time_val...........0x%X\n"
632                        "\t\tvendor_id...............0x%06X\n",
633                        inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
634                                  sizeof gid_str),
635                        cl_ntoh16(p_iir->subscriber_enum),
636                        inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
637                                  gid_str2, sizeof gid_str2),
638                        cl_ntoh16(p_iir->inform_info.lid_range_begin),
639                        cl_ntoh16(p_iir->inform_info.lid_range_end),
640                        p_iir->inform_info.is_generic,
641                        p_iir->inform_info.subscribe,
642                        cl_ntoh16(p_iir->inform_info.trap_type),
643                        cl_ntoh16(p_iir->inform_info.g_or_v.vend.dev_id),
644                        cl_ntoh32(qpn), resp_time_val,
645                        cl_ntoh32(ib_inform_info_get_prod_type
646                                  (&p_iir->inform_info)));
647 }
648
649 static void dump_one_link_record(void *data)
650 {
651         ib_link_record_t *lr = data;
652         printf("LinkRecord dump:\n"
653                "\t\tFromLID....................%u\n"
654                "\t\tFromPort...................%u\n"
655                "\t\tToPort.....................%u\n"
656                "\t\tToLID......................%u\n",
657                cl_ntoh16(lr->from_lid), lr->from_port_num,
658                lr->to_port_num, cl_ntoh16(lr->to_lid));
659 }
660
661 static void dump_one_slvl_record(void *data)
662 {
663         ib_slvl_table_record_t *slvl = data;
664         ib_slvl_table_t *t = &slvl->slvl_tbl;
665         printf("SL2VLTableRecord dump:\n"
666                "\t\tLID........................%u\n"
667                "\t\tInPort.....................%u\n"
668                "\t\tOutPort....................%u\n"
669                "\t\tSL: 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|\n"
670                "\t\tVL:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u"
671                "|%2u|%2u|%2u|\n",
672                cl_ntoh16(slvl->lid), slvl->in_port_num, slvl->out_port_num,
673                ib_slvl_table_get(t, 0), ib_slvl_table_get(t, 1),
674                ib_slvl_table_get(t, 2), ib_slvl_table_get(t, 3),
675                ib_slvl_table_get(t, 4), ib_slvl_table_get(t, 5),
676                ib_slvl_table_get(t, 6), ib_slvl_table_get(t, 7),
677                ib_slvl_table_get(t, 8), ib_slvl_table_get(t, 9),
678                ib_slvl_table_get(t, 10), ib_slvl_table_get(t, 11),
679                ib_slvl_table_get(t, 12), ib_slvl_table_get(t, 13),
680                ib_slvl_table_get(t, 14), ib_slvl_table_get(t, 15));
681 }
682
683 static void dump_one_vlarb_record(void *data)
684 {
685         ib_vl_arb_table_record_t *vlarb = data;
686         ib_vl_arb_element_t *e = vlarb->vl_arb_tbl.vl_entry;
687         int i;
688         printf("VLArbTableRecord dump:\n"
689                "\t\tLID........................%u\n"
690                "\t\tPort.......................%u\n"
691                "\t\tBlock......................%u\n",
692                cl_ntoh16(vlarb->lid), vlarb->port_num, vlarb->block_num);
693         for (i = 0; i < 32; i += 16)
694                 printf("\t\tVL    :%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
695                        "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|\n"
696                        "\t\tWeight:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
697                        "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|\n",
698                        e[i + 0].vl, e[i + 1].vl, e[i + 2].vl, e[i + 3].vl,
699                        e[i + 4].vl, e[i + 5].vl, e[i + 6].vl, e[i + 7].vl,
700                        e[i + 8].vl, e[i + 9].vl, e[i + 10].vl, e[i + 11].vl,
701                        e[i + 12].vl, e[i + 13].vl, e[i + 14].vl, e[i + 15].vl,
702                        e[i + 0].weight, e[i + 1].weight, e[i + 2].weight,
703                        e[i + 3].weight, e[i + 4].weight, e[i + 5].weight,
704                        e[i + 6].weight, e[i + 7].weight, e[i + 8].weight,
705                        e[i + 9].weight, e[i + 10].weight, e[i + 11].weight,
706                        e[i + 12].weight, e[i + 13].weight, e[i + 14].weight,
707                        e[i + 15].weight);
708 }
709
710 static void dump_one_pkey_tbl_record(void *data)
711 {
712         ib_pkey_table_record_t *pktr = data;
713         ib_net16_t *p = pktr->pkey_tbl.pkey_entry;
714         int i;
715         printf("PKeyTableRecord dump:\n"
716                "\t\tLID........................%u\n"
717                "\t\tPort.......................%u\n"
718                "\t\tBlock......................%u\n"
719                "\t\tPKey Table:\n",
720                cl_ntoh16(pktr->lid), pktr->port_num, pktr->block_num);
721         for (i = 0; i < 32; i += 8)
722                 printf("\t\t0x%04x 0x%04x 0x%04x 0x%04x"
723                        " 0x%04x 0x%04x 0x%04x 0x%04x\n",
724                        cl_ntoh16(p[i + 0]), cl_ntoh16(p[i + 1]),
725                        cl_ntoh16(p[i + 2]), cl_ntoh16(p[i + 3]),
726                        cl_ntoh16(p[i + 4]), cl_ntoh16(p[i + 5]),
727                        cl_ntoh16(p[i + 6]), cl_ntoh16(p[i + 7]));
728         printf("\n");
729 }
730
731 static void dump_one_lft_record(void *data)
732 {
733         ib_lft_record_t *lftr = data;
734         unsigned block = cl_ntoh16(lftr->block_num);
735         int i;
736         printf("LFT Record dump:\n"
737                "\t\tLID........................%u\n"
738                "\t\tBlock......................%u\n"
739                "\t\tLFT:\n\t\tLID\tPort Number\n", cl_ntoh16(lftr->lid), block);
740         for (i = 0; i < 64; i++)
741                 printf("\t\t%u\t%u\n", block * 64 + i, lftr->lft[i]);
742         printf("\n");
743 }
744
745 static void dump_one_mft_record(void *data)
746 {
747         ib_mft_record_t *mftr = data;
748         unsigned position = cl_ntoh16(mftr->position_block_num) >> 12;
749         unsigned block = cl_ntoh16(mftr->position_block_num) &
750             IB_MCAST_BLOCK_ID_MASK_HO;
751         int i;
752         printf("MFT Record dump:\n"
753                "\t\tLID........................%u\n"
754                "\t\tPosition...................%u\n"
755                "\t\tBlock......................%u\n"
756                "\t\tMFT:\n\t\tMLID\tPort Mask\n",
757                cl_ntoh16(mftr->lid), position, block);
758         for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
759                 printf("\t\t0x%x\t0x%x\n",
760                        IB_LID_MCAST_START_HO + block * 64 + i,
761                        cl_ntoh16(mftr->mft[i]));
762         printf("\n");
763 }
764
765 static void dump_results(struct query_res *r, void (*dump_func) (void *))
766 {
767         unsigned i;
768         for (i = 0; i < r->result_cnt; i++) {
769                 void *data = get_query_rec(r->p_result_madw, i);
770                 dump_func(data);
771         }
772 }
773
774 static void return_mad(void)
775 {
776         if (result.p_result_madw) {
777                 free((uint8_t *) result.p_result_madw - umad_size());
778                 result.p_result_madw = NULL;
779         }
780 }
781
782 /**
783  * Get any record(s)
784  */
785 static int get_any_records(bind_handle_t h,
786                            uint16_t attr_id, uint32_t attr_mod,
787                            ib_net64_t comp_mask, void *attr, uint64_t sm_key)
788 {
789         int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE, attr_id, attr_mod,
790                            cl_ntoh64(comp_mask), sm_key, attr);
791         if (ret) {
792                 fprintf(stderr, "Query SA failed: %s\n", ib_get_err_str(ret));
793                 return ret;
794         }
795
796         if (result.status != IB_SUCCESS) {
797                 fprintf(stderr, "Query result returned: %s\n",
798                         ib_get_err_str(result.status));
799                 return result.status;
800         }
801
802         return ret;
803 }
804
805 static int get_and_dump_any_records(bind_handle_t h, uint16_t attr_id,
806                                     uint32_t attr_mod, ib_net64_t comp_mask,
807                                     void *attr, uint64_t sm_key,
808                                     void (*dump_func) (void *))
809 {
810         int ret = get_any_records(h, attr_id, attr_mod, comp_mask, attr,
811                                   sm_key);
812         if (ret)
813                 return ret;
814
815         dump_results(&result, dump_func);
816
817         return 0;
818 }
819
820 /**
821  * Get all the records available for requested query type.
822  */
823 static int get_all_records(bind_handle_t h, uint16_t attr_id, int trusted)
824 {
825         return get_any_records(h, attr_id, 0, 0, NULL, trusted ? smkey : 0);
826 }
827
828 static int get_and_dump_all_records(bind_handle_t h, uint16_t attr_id,
829                                     int trusted, void (*dump_func) (void *))
830 {
831         int ret = get_all_records(h, attr_id, 0);
832         if (ret)
833                 return ret;
834
835         dump_results(&result, dump_func);
836         return_mad();
837         return ret;
838 }
839
840 /**
841  * return the lid from the node descriptor (name) supplied
842  */
843 static int
844 get_lid_from_name(bind_handle_t h, const char *name, uint16_t* lid)
845 {
846         ib_node_record_t *node_record = NULL;
847         ib_node_info_t *p_ni = NULL;
848         unsigned i;
849         int ret;
850
851         ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
852         if (ret)
853                 return ret;
854
855         for (i = 0; i < result.result_cnt; i++) {
856                 node_record = get_query_rec(result.p_result_madw, i);
857                 p_ni = &(node_record->node_info);
858                 if (name
859                     && strncmp(name, (char *)node_record->node_desc.description,
860                                sizeof(node_record->node_desc.description)) ==
861                     0) {
862                         *lid = cl_ntoh16(node_record->lid);
863                         break;
864                 }
865         }
866         return_mad();
867         return 0;
868 }
869
870 static uint16_t get_lid(bind_handle_t h, const char *name)
871 {
872         uint16_t rc_lid = 0;
873
874         if (!name)
875                 return 0;
876         if (isalpha(name[0]))
877                 assert(get_lid_from_name(h, name, &rc_lid) == IB_SUCCESS);
878         else
879                 rc_lid = (uint16_t) atoi(name);
880         if (rc_lid == 0)
881                 fprintf(stderr, "Failed to find lid for \"%s\"\n", name);
882         return rc_lid;
883 }
884
885 static int parse_lid_and_ports(bind_handle_t h,
886                                char *str, int *lid, int *port1, int *port2)
887 {
888         char *p, *e;
889
890         if (port1)
891                 *port1 = -1;
892         if (port2)
893                 *port2 = -1;
894
895         p = strchr(str, '/');
896         if (p)
897                 *p = '\0';
898         if (lid)
899                 *lid = get_lid(h, str);
900
901         if (!p)
902                 return 0;
903         str = p + 1;
904         p = strchr(str, '/');
905         if (p)
906                 *p = '\0';
907         if (port1) {
908                 *port1 = strtoul(str, &e, 0);
909                 if (e == str)
910                         *port1 = -1;
911         }
912
913         if (!p)
914                 return 0;
915         str = p + 1;
916         if (port2) {
917                 *port2 = strtoul(str, &e, 0);
918                 if (e == str)
919                         *port2 = -1;
920         }
921
922         return 0;
923 }
924
925 #define cl_hton8(x) (x)
926 #define CHECK_AND_SET_VAL(val, size, comp_with, target, name, mask) \
927         if ((int##size##_t) val > (int##size##_t) comp_with) { \
928                 target = cl_hton##size((uint##size##_t) val); \
929                 comp_mask |= IB_##name##_COMPMASK_##mask; \
930         }
931
932 #define CHECK_AND_SET_GID(val, target, name, mask) \
933         if (valid_gid(&(val))) { \
934                 memcpy(&(target), &(val), sizeof(val)); \
935                 comp_mask |= IB_##name##_COMPMASK_##mask; \
936         }
937
938 #define CHECK_AND_SET_VAL_AND_SEL(val, target, name, mask, sel) \
939         if (val) { \
940                 target = val; \
941                 comp_mask |= IB_##name##_COMPMASK_##mask##sel; \
942                 comp_mask |= IB_##name##_COMPMASK_##mask; \
943         }
944
945 /*
946  * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.
947  */
948 static int get_issm_records(bind_handle_t h, ib_net32_t capability_mask)
949 {
950         ib_portinfo_record_t attr;
951
952         memset(&attr, 0, sizeof(attr));
953         attr.port_info.capability_mask = capability_mask;
954
955         return get_any_records(h, IB_SA_ATTR_PORTINFORECORD, 1 << 31,
956                                IB_PIR_COMPMASK_CAPMASK, &attr, 0);
957 }
958
959 static int print_node_records(bind_handle_t h)
960 {
961         unsigned i;
962         int ret;
963
964         ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
965         if (ret)
966                 return ret;
967
968         if (node_print_desc == ALL_DESC) {
969                 printf("   LID \"name\"\n");
970                 printf("================\n");
971         }
972         for (i = 0; i < result.result_cnt; i++) {
973                 ib_node_record_t *node_record;
974                 node_record = get_query_rec(result.p_result_madw, i);
975                 if (node_print_desc == ALL_DESC) {
976                         print_node_desc(node_record);
977                 } else if (node_print_desc == NAME_OF_LID) {
978                         if (requested_lid == cl_ntoh16(node_record->lid))
979                                 print_node_record(node_record);
980                 } else if (node_print_desc == NAME_OF_GUID) {
981                         ib_node_info_t *p_ni = &(node_record->node_info);
982
983                         if (requested_guid == cl_ntoh64(p_ni->port_guid))
984                                 print_node_record(node_record);
985                 } else {
986                         if (!requested_name ||
987                             (strncmp(requested_name,
988                                      (char *)node_record->node_desc.description,
989                                      sizeof(node_record->node_desc.
990                                             description)) == 0)) {
991                                 print_node_record(node_record);
992                                 if (node_print_desc == UNIQUE_LID_ONLY) {
993                                         return_mad();
994                                         exit(0);
995                                 }
996                         }
997                 }
998         }
999         return_mad();
1000         return ret;
1001 }
1002
1003 static int get_print_class_port_info(bind_handle_t h)
1004 {
1005         int ret = sa_query(h, IB_MAD_METHOD_GET, CLASS_PORT_INFO, 0, 0,
1006                            0, NULL);
1007         if (ret) {
1008                 fprintf(stderr, "ERROR: Query SA failed: %s\n",
1009                         ib_get_err_str(ret));
1010                 return ret;
1011         }
1012         if (result.status != IB_SUCCESS) {
1013                 fprintf(stderr, "ERROR: Query result returned: %s\n",
1014                         ib_get_err_str(result.status));
1015                 return (result.status);
1016         }
1017         dump_results(&result, dump_class_port_info);
1018         return_mad();
1019         return ret;
1020 }
1021
1022 static int query_path_records(const struct query_cmd *q, bind_handle_t h,
1023                               struct query_params *p, int argc, char *argv[])
1024 {
1025         ib_path_rec_t pr;
1026         ib_net64_t comp_mask = 0;
1027         uint32_t flow = 0;
1028         uint16_t qos_class = 0;
1029         uint8_t reversible = 0;
1030
1031         memset(&pr, 0, sizeof(pr));
1032         CHECK_AND_SET_GID(p->sgid, pr.sgid, PR, SGID);
1033         CHECK_AND_SET_GID(p->dgid, pr.dgid, PR, DGID);
1034         CHECK_AND_SET_VAL(p->slid, 16, 0, pr.slid, PR, SLID);
1035         CHECK_AND_SET_VAL(p->dlid, 16, 0, pr.dlid, PR, DLID);
1036         CHECK_AND_SET_VAL(p->hop_limit, 32, -1, pr.hop_flow_raw, PR, HOPLIMIT);
1037         CHECK_AND_SET_VAL(p->flow_label, 8, 0, flow, PR, FLOWLABEL);
1038         pr.hop_flow_raw |= cl_hton32(flow << 8);
1039         CHECK_AND_SET_VAL(p->tclass, 8, 0, pr.tclass, PR, TCLASS);
1040         CHECK_AND_SET_VAL(p->reversible, 8, -1, reversible, PR, REVERSIBLE);
1041         CHECK_AND_SET_VAL(p->numb_path, 8, -1, pr.num_path, PR, NUMBPATH);
1042         pr.num_path |= reversible << 7;
1043         CHECK_AND_SET_VAL(p->pkey, 16, 0, pr.pkey, PR, PKEY);
1044         CHECK_AND_SET_VAL(p->sl, 16, -1, pr.qos_class_sl, PR, SL);
1045         CHECK_AND_SET_VAL(p->qos_class, 16, -1, qos_class, PR, QOS_CLASS);
1046         ib_path_rec_set_qos_class(&pr, qos_class);
1047         CHECK_AND_SET_VAL_AND_SEL(p->mtu, pr.mtu, PR, MTU, SELEC);
1048         CHECK_AND_SET_VAL_AND_SEL(p->rate, pr.rate, PR, RATE, SELEC);
1049         CHECK_AND_SET_VAL_AND_SEL(p->pkt_life, pr.pkt_life, PR, PKTLIFETIME, SELEC);
1050
1051         return get_and_dump_any_records(h, IB_SA_ATTR_PATHRECORD, 0, comp_mask,
1052                                         &pr, 0, dump_path_record);
1053 }
1054
1055 static ib_api_status_t print_issm_records(bind_handle_t h)
1056 {
1057         ib_api_status_t status;
1058
1059         /* First, get IsSM records */
1060         status = get_issm_records(h, IB_PORT_CAP_IS_SM);
1061         if (status != IB_SUCCESS)
1062                 return (status);
1063
1064         printf("IsSM ports\n");
1065         dump_results(&result, dump_portinfo_record);
1066         return_mad();
1067
1068         /* Now, get IsSMdisabled records */
1069         status = get_issm_records(h, IB_PORT_CAP_SM_DISAB);
1070         if (status != IB_SUCCESS)
1071                 return (status);
1072
1073         printf("\nIsSMdisabled ports\n");
1074         dump_results(&result, dump_portinfo_record);
1075         return_mad();
1076
1077         return (status);
1078 }
1079
1080 static int print_multicast_member_records(bind_handle_t h)
1081 {
1082         struct query_res mc_group_result;
1083         int ret;
1084
1085         ret = get_all_records(h, IB_SA_ATTR_MCRECORD, 1);
1086         if (ret)
1087                 return ret;
1088
1089         mc_group_result = result;
1090
1091         ret = get_all_records(h, IB_SA_ATTR_NODERECORD, 0);
1092         if (ret)
1093                 goto return_mc;
1094
1095         dump_results(&mc_group_result, dump_multicast_member_record);
1096         return_mad();
1097
1098 return_mc:
1099         if (mc_group_result.p_result_madw)
1100                 free((uint8_t *) mc_group_result.p_result_madw - umad_size());
1101
1102         return ret;
1103 }
1104
1105 static int print_multicast_group_records(bind_handle_t h)
1106 {
1107         return get_and_dump_all_records(h, IB_SA_ATTR_MCRECORD, 0,
1108                                         dump_multicast_group_record);
1109 }
1110
1111 static int query_class_port_info(const struct query_cmd *q, bind_handle_t h,
1112                                  struct query_params *p, int argc, char *argv[])
1113 {
1114         return get_print_class_port_info(h);
1115 }
1116
1117 static int query_node_records(const struct query_cmd *q, bind_handle_t h,
1118                               struct query_params *p, int argc, char *argv[])
1119 {
1120         ib_node_record_t nr;
1121         ib_net64_t comp_mask = 0;
1122         int lid = 0;
1123
1124         if (argc > 0)
1125                 parse_lid_and_ports(h, argv[0], &lid, NULL, NULL);
1126
1127         memset(&nr, 0, sizeof(nr));
1128         CHECK_AND_SET_VAL(lid, 16, 0, nr.lid, NR, LID);
1129
1130         return get_and_dump_any_records(h, IB_SA_ATTR_NODERECORD, 0, comp_mask,
1131                                         &nr, 0, dump_node_record);
1132 }
1133
1134 static int query_portinfo_records(const struct query_cmd *q,
1135                                   bind_handle_t h, struct query_params *p,
1136                                   int argc, char *argv[])
1137 {
1138         ib_portinfo_record_t pir;
1139         ib_net64_t comp_mask = 0;
1140         int lid = 0, port = -1;
1141
1142         if (argc > 0)
1143                 parse_lid_and_ports(h, argv[0], &lid, &port, NULL);
1144
1145         memset(&pir, 0, sizeof(pir));
1146         CHECK_AND_SET_VAL(lid, 16, 0, pir.lid, PIR, LID);
1147         CHECK_AND_SET_VAL(port, 8, -1, pir.port_num, PIR, PORTNUM);
1148
1149         return get_and_dump_any_records(h, IB_SA_ATTR_PORTINFORECORD, 0,
1150                                         comp_mask, &pir, 0,
1151                                         dump_one_portinfo_record);
1152 }
1153
1154 static int query_mcmember_records(const struct query_cmd *q,
1155                                   bind_handle_t h, struct query_params *p,
1156                                   int argc, char *argv[])
1157 {
1158         ib_member_rec_t mr;
1159         ib_net64_t comp_mask = 0;
1160         uint32_t flow = 0;
1161         uint8_t sl = 0, hop = 0, scope = 0;
1162
1163         memset(&mr, 0, sizeof(mr));
1164         CHECK_AND_SET_GID(p->mgid, mr.mgid, MCR, MGID);
1165         CHECK_AND_SET_GID(p->gid, mr.port_gid, MCR, PORT_GID);
1166         CHECK_AND_SET_VAL(p->mlid, 16, 0, mr.mlid, MCR, MLID);
1167         CHECK_AND_SET_VAL(p->qkey, 32, 0, mr.qkey, MCR, QKEY);
1168         CHECK_AND_SET_VAL_AND_SEL(p->mtu, mr.mtu, MCR, MTU, _SEL);
1169         CHECK_AND_SET_VAL_AND_SEL(p->rate, mr.rate, MCR, RATE, _SEL);
1170         CHECK_AND_SET_VAL_AND_SEL(p->pkt_life, mr.pkt_life, MCR, LIFE, _SEL);
1171         CHECK_AND_SET_VAL(p->tclass, 8, 0, mr.tclass, MCR, TCLASS);
1172         CHECK_AND_SET_VAL(p->pkey, 16, 0, mr.pkey, MCR, PKEY);
1173         CHECK_AND_SET_VAL(p->sl, 8, -1, sl, MCR, SL);
1174         CHECK_AND_SET_VAL(p->flow_label, 8, 0, flow, MCR, FLOW);
1175         CHECK_AND_SET_VAL(p->hop_limit, 8, -1, hop, MCR, HOP);
1176         mr.sl_flow_hop = ib_member_set_sl_flow_hop(sl, flow, hop);
1177         CHECK_AND_SET_VAL(p->scope, 8, 0, scope, MCR, SCOPE);
1178         CHECK_AND_SET_VAL(p->join_state, 8, 0, mr.scope_state, MCR, JOIN_STATE);
1179         mr.scope_state |= scope << 4;
1180         CHECK_AND_SET_VAL(p->proxy_join, 8, -1, mr.proxy_join, MCR, PROXY);
1181
1182         return get_and_dump_any_records(h, IB_SA_ATTR_MCRECORD, 0, comp_mask,
1183                                         &mr, smkey, dump_one_mcmember_record);
1184 }
1185
1186 static int query_service_records(const struct query_cmd *q, bind_handle_t h,
1187                                  struct query_params *p, int argc, char *argv[])
1188 {
1189         return get_and_dump_all_records(h, IB_SA_ATTR_SERVICERECORD, 0,
1190                                         dump_service_record);
1191 }
1192
1193 static int query_informinfo_records(const struct query_cmd *q,
1194                                     bind_handle_t h, struct query_params *p,
1195                                     int argc, char *argv[])
1196 {
1197         return get_and_dump_all_records(h, IB_SA_ATTR_INFORMINFORECORD, 0,
1198                                         dump_inform_info_record);
1199 }
1200
1201 static int query_link_records(const struct query_cmd *q, bind_handle_t h,
1202                               struct query_params *p, int argc, char *argv[])
1203 {
1204         ib_link_record_t lr;
1205         ib_net64_t comp_mask = 0;
1206         int from_lid = 0, to_lid = 0, from_port = -1, to_port = -1;
1207
1208         if (argc > 0)
1209                 parse_lid_and_ports(h, argv[0], &from_lid, &from_port, NULL);
1210
1211         if (argc > 1)
1212                 parse_lid_and_ports(h, argv[1], &to_lid, &to_port, NULL);
1213
1214         memset(&lr, 0, sizeof(lr));
1215         CHECK_AND_SET_VAL(from_lid, 16, 0, lr.from_lid, LR, FROM_LID);
1216         CHECK_AND_SET_VAL(from_port, 8, -1, lr.from_port_num, LR, FROM_PORT);
1217         CHECK_AND_SET_VAL(to_lid, 16, 0, lr.to_lid, LR, TO_LID);
1218         CHECK_AND_SET_VAL(to_port, 8, -1, lr.to_port_num, LR, TO_PORT);
1219
1220         return get_and_dump_any_records(h, IB_SA_ATTR_LINKRECORD, 0, comp_mask,
1221                                         &lr, 0, dump_one_link_record);
1222 }
1223
1224 static int query_sl2vl_records(const struct query_cmd *q, bind_handle_t h,
1225                                struct query_params *p, int argc, char *argv[])
1226 {
1227         ib_slvl_table_record_t slvl;
1228         ib_net64_t comp_mask = 0;
1229         int lid = 0, in_port = -1, out_port = -1;
1230
1231         if (argc > 0)
1232                 parse_lid_and_ports(h, argv[0], &lid, &in_port, &out_port);
1233
1234         memset(&slvl, 0, sizeof(slvl));
1235         CHECK_AND_SET_VAL(lid, 16, 0, slvl.lid, SLVL, LID);
1236         CHECK_AND_SET_VAL(in_port, 8, -1, slvl.in_port_num, SLVL, IN_PORT);
1237         CHECK_AND_SET_VAL(out_port, 8, -1, slvl.out_port_num, SLVL, OUT_PORT);
1238
1239         return get_and_dump_any_records(h, IB_SA_ATTR_SL2VLTABLERECORD, 0,
1240                                         comp_mask, &slvl, 0,
1241                                         dump_one_slvl_record);
1242 }
1243
1244 static int query_vlarb_records(const struct query_cmd *q, bind_handle_t h,
1245                                struct query_params *p, int argc, char *argv[])
1246 {
1247         ib_vl_arb_table_record_t vlarb;
1248         ib_net64_t comp_mask = 0;
1249         int lid = 0, port = -1, block = -1;
1250
1251         if (argc > 0)
1252                 parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1253
1254         memset(&vlarb, 0, sizeof(vlarb));
1255         CHECK_AND_SET_VAL(lid, 16, 0, vlarb.lid, VLA, LID);
1256         CHECK_AND_SET_VAL(port, 8, -1, vlarb.port_num, VLA, OUT_PORT);
1257         CHECK_AND_SET_VAL(block, 8, -1, vlarb.block_num, VLA, BLOCK);
1258
1259         return get_and_dump_any_records(h, IB_SA_ATTR_VLARBTABLERECORD, 0,
1260                                         comp_mask, &vlarb, 0,
1261                                         dump_one_vlarb_record);
1262 }
1263
1264 static int query_pkey_tbl_records(const struct query_cmd *q,
1265                                   bind_handle_t h, struct query_params *p,
1266                                   int argc, char *argv[])
1267 {
1268         ib_pkey_table_record_t pktr;
1269         ib_net64_t comp_mask = 0;
1270         int lid = 0, port = -1, block = -1;
1271
1272         if (argc > 0)
1273                 parse_lid_and_ports(h, argv[0], &lid, &port, &block);
1274
1275         memset(&pktr, 0, sizeof(pktr));
1276         CHECK_AND_SET_VAL(lid, 16, 0, pktr.lid, PKEY, LID);
1277         CHECK_AND_SET_VAL(port, 8, -1, pktr.port_num, PKEY, PORT);
1278         CHECK_AND_SET_VAL(block, 16, -1, pktr.block_num, PKEY, BLOCK);
1279
1280         return get_and_dump_any_records(h, IB_SA_ATTR_PKEYTABLERECORD, 0,
1281                                         comp_mask, &pktr, smkey,
1282                                         dump_one_pkey_tbl_record);
1283 }
1284
1285 static int query_lft_records(const struct query_cmd *q, bind_handle_t h,
1286                              struct query_params *p, int argc, char *argv[])
1287 {
1288         ib_lft_record_t lftr;
1289         ib_net64_t comp_mask = 0;
1290         int lid = 0, block = -1;
1291
1292         if (argc > 0)
1293                 parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
1294
1295         memset(&lftr, 0, sizeof(lftr));
1296         CHECK_AND_SET_VAL(lid, 16, 0, lftr.lid, LFTR, LID);
1297         CHECK_AND_SET_VAL(block, 16, -1, lftr.block_num, LFTR, BLOCK);
1298
1299         return get_and_dump_any_records(h, IB_SA_ATTR_LFTRECORD, 0, comp_mask,
1300                                         &lftr, 0, dump_one_lft_record);
1301 }
1302
1303 static int query_mft_records(const struct query_cmd *q, bind_handle_t h,
1304                              struct query_params *p, int argc, char *argv[])
1305 {
1306         ib_mft_record_t mftr;
1307         ib_net64_t comp_mask = 0;
1308         int lid = 0, block = -1, position = -1;
1309         uint16_t pos = 0;
1310
1311         if (argc > 0)
1312                 parse_lid_and_ports(h, argv[0], &lid, &position, &block);
1313
1314         memset(&mftr, 0, sizeof(mftr));
1315         CHECK_AND_SET_VAL(lid, 16, 0, mftr.lid, MFTR, LID);
1316         CHECK_AND_SET_VAL(block, 16, -1, mftr.position_block_num, MFTR, BLOCK);
1317         mftr.position_block_num &= cl_hton16(IB_MCAST_BLOCK_ID_MASK_HO);
1318         CHECK_AND_SET_VAL(position, 8, -1, pos, MFTR, POSITION);
1319         mftr.position_block_num |= cl_hton16(pos << 12);
1320
1321         return get_and_dump_any_records(h, IB_SA_ATTR_MFTRECORD, 0, comp_mask,
1322                                         &mftr, 0, dump_one_mft_record);
1323 }
1324
1325 static bind_handle_t get_bind_handle(void)
1326 {
1327         static struct ibmad_port *srcport;
1328         static struct bind_handle handle;
1329         int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
1330
1331         srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
1332         if (!srcport)
1333                 IBERROR("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
1334
1335         ib_resolve_smlid_via(&handle.dport, ibd_timeout, srcport);
1336         if (!handle.dport.lid)
1337                 IBPANIC("No SM found.");
1338
1339         handle.dport.qp = 1;
1340         if (!handle.dport.qkey)
1341                 handle.dport.qkey = IB_DEFAULT_QP1_QKEY;
1342
1343         handle.fd = mad_rpc_portid(srcport);
1344         handle.agent = umad_register(handle.fd, IB_SA_CLASS, 2, 1, NULL);
1345
1346         return &handle;
1347 }
1348
1349 static void clean_up(struct bind_handle *h)
1350 {
1351         umad_unregister(h->fd, h->agent);
1352         umad_close_port(h->fd);
1353         umad_done();
1354 }
1355
1356 static const struct query_cmd query_cmds[] = {
1357         {"ClassPortInfo", "CPI", CLASS_PORT_INFO,
1358          NULL, query_class_port_info},
1359         {"NodeRecord", "NR", IB_SA_ATTR_NODERECORD,
1360          "[lid]", query_node_records},
1361         {"PortInfoRecord", "PIR", IB_SA_ATTR_PORTINFORECORD,
1362          "[[lid]/[port]]", query_portinfo_records},
1363         {"SL2VLTableRecord", "SL2VL", IB_SA_ATTR_SL2VLTABLERECORD,
1364          "[[lid]/[in_port]/[out_port]]", query_sl2vl_records},
1365         {"PKeyTableRecord", "PKTR", IB_SA_ATTR_PKEYTABLERECORD,
1366          "[[lid]/[port]/[block]]", query_pkey_tbl_records},
1367         {"VLArbitrationTableRecord", "VLAR", IB_SA_ATTR_VLARBTABLERECORD,
1368          "[[lid]/[port]/[block]]", query_vlarb_records},
1369         {"InformInfoRecord", "IIR", IB_SA_ATTR_INFORMINFORECORD,
1370          NULL, query_informinfo_records},
1371         {"LinkRecord", "LR", IB_SA_ATTR_LINKRECORD,
1372          "[[from_lid]/[from_port]] [[to_lid]/[to_port]]", query_link_records},
1373         {"ServiceRecord", "SR", IB_SA_ATTR_SERVICERECORD,
1374          NULL, query_service_records},
1375         {"PathRecord", "PR", IB_SA_ATTR_PATHRECORD,
1376          NULL, query_path_records},
1377         {"MCMemberRecord", "MCMR", IB_SA_ATTR_MCRECORD,
1378          NULL, query_mcmember_records},
1379         {"LFTRecord", "LFTR", IB_SA_ATTR_LFTRECORD,
1380          "[[lid]/[block]]", query_lft_records},
1381         {"MFTRecord", "MFTR", IB_SA_ATTR_MFTRECORD,
1382          "[[mlid]/[position]/[block]]", query_mft_records},
1383         {0}
1384 };
1385
1386 static const struct query_cmd *find_query(const char *name)
1387 {
1388         const struct query_cmd *q;
1389         unsigned len = strlen(name);
1390
1391         for (q = query_cmds; q->name; q++)
1392                 if (!strncasecmp(name, q->name, len) ||
1393                     (q->alias && !strncasecmp(name, q->alias, len)))
1394                         return q;
1395
1396         return NULL;
1397 }
1398
1399 static const struct query_cmd *find_query_by_type(uint16_t type)
1400 {
1401         const struct query_cmd *q;
1402
1403         for (q = query_cmds; q->name; q++)
1404                 if (q->query_type == type)
1405                         return q;
1406
1407         return NULL;
1408 }
1409
1410 enum saquery_command {
1411         SAQUERY_CMD_QUERY,
1412         SAQUERY_CMD_NODE_RECORD,
1413         SAQUERY_CMD_CLASS_PORT_INFO,
1414         SAQUERY_CMD_ISSM,
1415         SAQUERY_CMD_MCGROUPS,
1416         SAQUERY_CMD_MCMEMBERS,
1417 };
1418
1419 static enum saquery_command command = SAQUERY_CMD_QUERY;
1420 static uint16_t query_type;
1421 static char *src_lid, *dst_lid;
1422
1423 static int process_opt(void *context, int ch, char *optarg)
1424 {
1425         struct query_params *p = context;
1426
1427         switch (ch) {
1428         case 1:
1429                 {
1430                         src_lid = strdup(optarg);
1431                         dst_lid = strchr(src_lid, ':');
1432                         if (!dst_lid)
1433                                 ibdiag_show_usage();
1434                         *dst_lid++ = '\0';
1435                 }
1436                 p->numb_path = 0x7f;
1437                 query_type = IB_SA_ATTR_PATHRECORD;
1438                 break;
1439         case 2:
1440                 {
1441                         char *src_addr = strdup(optarg);
1442                         char *dst_addr = strchr(src_addr, '-');
1443                         if (!dst_addr)
1444                                 ibdiag_show_usage();
1445                         *dst_addr++ = '\0';
1446                         if (inet_pton(AF_INET6, src_addr, &p->sgid) <= 0)
1447                                 ibdiag_show_usage();
1448                         if (inet_pton(AF_INET6, dst_addr, &p->dgid) <= 0)
1449                                 ibdiag_show_usage();
1450                         free(src_addr);
1451                 }
1452                 p->numb_path = 0x7f;
1453                 query_type = IB_SA_ATTR_PATHRECORD;
1454                 break;
1455         case 3:
1456                 node_name_map_file = strdup(optarg);
1457                 break;
1458         case 4:
1459                 if (!isxdigit(*optarg) &&
1460                     !(optarg = getpass("SM_Key: "))) {
1461                         fprintf(stderr, "cannot get SM_Key\n");
1462                         ibdiag_show_usage();
1463                 }
1464                 smkey = strtoull(optarg, NULL, 0);
1465                 break;
1466         case 'p':
1467                 query_type = IB_SA_ATTR_PATHRECORD;
1468                 break;
1469         case 'D':
1470                 node_print_desc = ALL_DESC;
1471                 break;
1472         case 'c':
1473                 command = SAQUERY_CMD_CLASS_PORT_INFO;
1474                 break;
1475         case 'S':
1476                 query_type = IB_SA_ATTR_SERVICERECORD;
1477                 break;
1478         case 'I':
1479                 query_type = IB_SA_ATTR_INFORMINFORECORD;
1480                 break;
1481         case 'N':
1482                 command = SAQUERY_CMD_NODE_RECORD;
1483                 break;
1484         case 'L':
1485                 node_print_desc = LID_ONLY;
1486                 command = SAQUERY_CMD_NODE_RECORD;
1487                 break;
1488         case 'l':
1489                 node_print_desc = UNIQUE_LID_ONLY;
1490                 command = SAQUERY_CMD_NODE_RECORD;
1491                 break;
1492         case 'G':
1493                 node_print_desc = GUID_ONLY;
1494                 command = SAQUERY_CMD_NODE_RECORD;
1495                 break;
1496         case 'O':
1497                 node_print_desc = NAME_OF_LID;
1498                 command = SAQUERY_CMD_NODE_RECORD;
1499                 break;
1500         case 'U':
1501                 node_print_desc = NAME_OF_GUID;
1502                 command = SAQUERY_CMD_NODE_RECORD;
1503                 break;
1504         case 's':
1505                 command = SAQUERY_CMD_ISSM;
1506                 break;
1507         case 'g':
1508                 command = SAQUERY_CMD_MCGROUPS;
1509                 break;
1510         case 'm':
1511                 command = SAQUERY_CMD_MCMEMBERS;
1512                 break;
1513         case 'x':
1514                 query_type = IB_SA_ATTR_LINKRECORD;
1515                 break;
1516         case 5:
1517                 p->slid = (uint16_t) strtoul(optarg, NULL, 0);
1518                 break;
1519         case 6:
1520                 p->dlid = (uint16_t) strtoul(optarg, NULL, 0);
1521                 break;
1522         case 7:
1523                 p->mlid = (uint16_t) strtoul(optarg, NULL, 0);
1524                 break;
1525         case 14:
1526                 if (inet_pton(AF_INET6, optarg, &p->sgid) <= 0)
1527                         ibdiag_show_usage();
1528                 break;
1529         case 15:
1530                 if (inet_pton(AF_INET6, optarg, &p->dgid) <= 0)
1531                         ibdiag_show_usage();
1532                 break;
1533         case 16:
1534                 if (inet_pton(AF_INET6, optarg, &p->gid) <= 0)
1535                         ibdiag_show_usage();
1536                 break;
1537         case 17:
1538                 if (inet_pton(AF_INET6, optarg, &p->mgid) <= 0)
1539                         ibdiag_show_usage();
1540                 break;
1541         case 'r':
1542                 p->reversible = strtoul(optarg, NULL, 0);
1543                 break;
1544         case 'n':
1545                 p->numb_path = strtoul(optarg, NULL, 0);
1546                 break;
1547         case 18:
1548                 p->pkey = (uint16_t) strtoul(optarg, NULL, 0);
1549                 break;
1550         case 'Q':
1551                 p->qos_class = strtoul(optarg, NULL, 0);
1552                 break;
1553         case 19:
1554                 p->sl = strtoul(optarg, NULL, 0);
1555                 break;
1556         case 'M':
1557                 p->mtu = (uint8_t) strtoul(optarg, NULL, 0);
1558                 break;
1559         case 'R':
1560                 p->rate = (uint8_t) strtoul(optarg, NULL, 0);
1561                 break;
1562         case 20:
1563                 p->pkt_life = (uint8_t) strtoul(optarg, NULL, 0);
1564                 break;
1565         case 'q':
1566                 p->qkey = strtoul(optarg, NULL, 0);
1567                 break;
1568         case 'T':
1569                 p->tclass = (uint8_t) strtoul(optarg, NULL, 0);
1570                 break;
1571         case 'F':
1572                 p->flow_label = strtoul(optarg, NULL, 0);
1573                 break;
1574         case 'H':
1575                 p->hop_limit = strtoul(optarg, NULL, 0);
1576                 break;
1577         case 21:
1578                 p->scope = (uint8_t) strtoul(optarg, NULL, 0);
1579                 break;
1580         case 'J':
1581                 p->join_state = (uint8_t) strtoul(optarg, NULL, 0);
1582                 break;
1583         case 'X':
1584                 p->proxy_join = strtoul(optarg, NULL, 0);
1585                 break;
1586         default:
1587                 return -1;
1588         }
1589         return 0;
1590 }
1591
1592 int main(int argc, char **argv)
1593 {
1594         char usage_args[1024];
1595         bind_handle_t h;
1596         struct query_params params;
1597         const struct query_cmd *q;
1598         ib_api_status_t status;
1599         int n;
1600
1601         const struct ibdiag_opt opts[] = {
1602                 {"p", 'p', 0, NULL, "get PathRecord info"},
1603                 {"N", 'N', 0, NULL, "get NodeRecord info"},
1604                 {"L", 'L', 0, NULL, "return the Lids of the name specified"},
1605                 {"l", 'l', 0, NULL, "return the unique Lid of the name specified"},
1606                 {"G", 'G', 0, NULL, "return the Guids of the name specified"},
1607                 {"O", 'O', 0, NULL, "return name for the Lid specified"},
1608                 {"U", 'U', 0, NULL, "return name for the Guid specified"},
1609                 {"s", 's', 0, NULL, "return the PortInfoRecords with isSM or"
1610                  " isSMdisabled capability mask bit on"},
1611                 {"g", 'g', 0, NULL, "get multicast group info"},
1612                 {"m", 'm', 0, NULL, "get multicast member info (if multicast"
1613                  " group specified, list member GIDs only for group specified,"
1614                  " for example 'saquery -m 0xC000')"},
1615                 {"x", 'x', 0, NULL, "get LinkRecord info"},
1616                 {"c", 'c', 0, NULL, "get the SA's class port info"},
1617                 {"S", 'S', 0, NULL, "get ServiceRecord info"},
1618                 {"I", 'I', 0, NULL, "get InformInfoRecord (subscription) info"},
1619                 {"list", 'D', 0, NULL, "the node desc of the CA's"},
1620                 {"src-to-dst", 1, 1, "<src:dst>", "get a PathRecord for"
1621                  " <src:dst> where src and dst are either node names or LIDs"},
1622                 {"sgid-to-dgid", 2, 1, "<sgid-dgid>", "get a PathRecord for"
1623                  " <sgid-dgid> where sgid and dgid are addresses in IPv6 format"},
1624                 {"node-name-map", 3, 1, "<file>", "specify a node name map file"},
1625                 {"smkey", 4, 1, "<val>", "SA SM_Key value for the query."
1626                  " If non-numeric value (like 'x') is specified then"
1627                  " saquery will prompt for a value"},
1628                 { "slid", 5, 1, "<lid>", "Source LID (PathRecord)" },
1629                 { "dlid", 6, 1, "<lid>", "Destination LID (PathRecord)" },
1630                 { "mlid", 7, 1, "<lid>", "Multicast LID (MCMemberRecord)" },
1631                 { "sgid", 14, 1, "<gid>", "Source GID (IPv6 format) (PathRecord)" },
1632                 { "dgid", 15, 1, "<gid>", "Destination GID (IPv6 format) (PathRecord)" },
1633                 { "gid", 16, 1, "<gid>", "Port GID (MCMemberRecord)" },
1634                 { "mgid", 17, 1, "<gid>", "Multicast GID (MCMemberRecord)" },
1635                 { "reversible", 'r', 1, NULL, "Reversible path (PathRecord)" },
1636                 { "numb_path", 'n', 1, NULL, "Number of paths (PathRecord)" },
1637                 { "pkey", 18, 1, NULL, "P_Key (PathRecord, MCMemberRecord)" },
1638                 { "qos_calss", 'Q', 1, NULL, "QoS Class (PathRecord)"},
1639                 { "sl", 19, 1, NULL, "Service level (PathRecord, MCMemberRecord)" },
1640                 { "mtu", 'M', 1, NULL, "MTU and selector (PathRecord, MCMemberRecord)" },
1641                 { "rate", 'R', 1, NULL, "Rate and selector (PathRecord, MCMemberRecord)" },
1642                 { "pkt_lifetime", 20, 1, NULL, "Packet lifetime and selector (PathRecord, MCMemberRecord)" },
1643                 { "qkey", 'q', 1, NULL, "Q_Key (MCMemberRecord)" },
1644                 { "tclass", 'T', 1, NULL, "Traffic Class (PathRecord, MCMemberRecord)" },
1645                 { "flow_label", 'F', 1, NULL, "Flow Label (PathRecord, MCMemberRecord)" },
1646                 { "hop_limit", 'H', 1, NULL, "Hop limit (PathRecord, MCMemberRecord)" },
1647                 { "scope", 21, 1, NULL, "Scope (MCMemberRecord)" },
1648                 { "join_state", 'J', 1, NULL, "Join state (MCMemberRecord)" },
1649                 { "proxy_join", 'X', 1, NULL, "Proxy join (MCMemberRecord)" },
1650                 { 0 }
1651         };
1652
1653         memset(&params, 0, sizeof params);
1654         params.hop_limit = -1;
1655         params.reversible = -1;
1656         params.numb_path = -1;
1657         params.qos_class = -1;
1658         params.sl = -1;
1659         params.proxy_join = -1;
1660
1661         n = sprintf(usage_args, "[query-name] [<name> | <lid> | <guid>]\n"
1662                     "\nSupported query names (and aliases):\n");
1663         for (q = query_cmds; q->name; q++) {
1664                 n += snprintf(usage_args + n, sizeof(usage_args) - n,
1665                               "  %s (%s) %s\n", q->name,
1666                               q->alias ? q->alias : "",
1667                               q->usage ? q->usage : "");
1668                 if (n >= sizeof(usage_args))
1669                         exit(-1);
1670         }
1671         snprintf(usage_args + n, sizeof(usage_args) - n,
1672                  "\n  Queries node records by default.");
1673
1674         q = NULL;
1675         ibd_timeout = DEFAULT_SA_TIMEOUT_MS;
1676
1677         ibdiag_process_opts(argc, argv, &params, "DLGs", opts, process_opt,
1678                             usage_args, NULL);
1679
1680         argc -= optind;
1681         argv += optind;
1682
1683         if (!query_type && command == SAQUERY_CMD_QUERY) {
1684                 if (!argc || !(q = find_query(argv[0])))
1685                         query_type = IB_SA_ATTR_NODERECORD;
1686                 else {
1687                         query_type = q->query_type;
1688                         argc--;
1689                         argv++;
1690                 }
1691         }
1692
1693         if (argc) {
1694                 if (node_print_desc == NAME_OF_LID) {
1695                         requested_lid = (uint16_t) strtoul(argv[0], NULL, 0);
1696                         requested_lid_flag++;
1697                 } else if (node_print_desc == NAME_OF_GUID) {
1698                         requested_guid = strtoul(argv[0], NULL, 0);
1699                         requested_guid_flag++;
1700                 } else
1701                         requested_name = argv[0];
1702         }
1703
1704         if ((node_print_desc == LID_ONLY ||
1705              node_print_desc == UNIQUE_LID_ONLY ||
1706              node_print_desc == GUID_ONLY) && !requested_name) {
1707                 fprintf(stderr, "ERROR: name not specified\n");
1708                 ibdiag_show_usage();
1709         }
1710
1711         if (node_print_desc == NAME_OF_LID && !requested_lid_flag) {
1712                 fprintf(stderr, "ERROR: lid not specified\n");
1713                 ibdiag_show_usage();
1714         }
1715
1716         if (node_print_desc == NAME_OF_GUID && !requested_guid_flag) {
1717                 fprintf(stderr, "ERROR: guid not specified\n");
1718                 ibdiag_show_usage();
1719         }
1720
1721         /* Note: lid cannot be 0; see infiniband spec 4.1.3 */
1722         if (node_print_desc == NAME_OF_LID && !requested_lid) {
1723                 fprintf(stderr, "ERROR: lid invalid\n");
1724                 ibdiag_show_usage();
1725         }
1726
1727         h = get_bind_handle();
1728         node_name_map = open_node_name_map(node_name_map_file);
1729
1730         if (src_lid && *src_lid)
1731                 params.slid = get_lid(h, src_lid);
1732         if (dst_lid && *dst_lid)
1733                 params.dlid = get_lid(h, dst_lid);
1734
1735         switch (command) {
1736         case SAQUERY_CMD_NODE_RECORD:
1737                 status = print_node_records(h);
1738                 break;
1739         case SAQUERY_CMD_CLASS_PORT_INFO:
1740                 status = get_print_class_port_info(h);
1741                 break;
1742         case SAQUERY_CMD_ISSM:
1743                 status = print_issm_records(h);
1744                 break;
1745         case SAQUERY_CMD_MCGROUPS:
1746                 status = print_multicast_group_records(h);
1747                 break;
1748         case SAQUERY_CMD_MCMEMBERS:
1749                 status = print_multicast_member_records(h);
1750                 break;
1751         default:
1752                 if ((!q && !(q = find_query_by_type(query_type)))
1753                     || !q->handler) {
1754                         fprintf(stderr, "Unknown query type %d\n",
1755                                 ntohs(query_type));
1756                         status = IB_UNKNOWN_ERROR;
1757                 } else
1758                         status = q->handler(q, h, &params, argc, argv);
1759                 break;
1760         }
1761
1762         if (src_lid)
1763                 free(src_lid);
1764         clean_up(h);
1765         close_node_name_map(node_name_map);
1766         return (status);
1767 }