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