1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky * Copyright (c) 2006-2007 The Regents of the University of California.
3d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
4d6b92ffaSHans Petter Selasky * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
5d6b92ffaSHans Petter Selasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6d6b92ffaSHans Petter Selasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
7d6b92ffaSHans Petter Selasky * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
8d6b92ffaSHans Petter Selasky *
9d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two
10d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU
11d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file
12d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the
13d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below:
14d6b92ffaSHans Petter Selasky *
15d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or
16d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following
17d6b92ffaSHans Petter Selasky * conditions are met:
18d6b92ffaSHans Petter Selasky *
19d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above
20d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
21d6b92ffaSHans Petter Selasky * disclaimer.
22d6b92ffaSHans Petter Selasky *
23d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above
24d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following
25d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials
26d6b92ffaSHans Petter Selasky * provided with the distribution.
27d6b92ffaSHans Petter Selasky *
28d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35d6b92ffaSHans Petter Selasky * SOFTWARE.
36d6b92ffaSHans Petter Selasky *
37d6b92ffaSHans Petter Selasky */
38d6b92ffaSHans Petter Selasky
39d6b92ffaSHans Petter Selasky
40d6b92ffaSHans Petter Selasky #include <errno.h>
41d6b92ffaSHans Petter Selasky #include <infiniband/umad.h>
42d6b92ffaSHans Petter Selasky
43d6b92ffaSHans Petter Selasky #include "ibdiag_common.h"
44d6b92ffaSHans Petter Selasky #include "ibdiag_sa.h"
45d6b92ffaSHans Petter Selasky
46d6b92ffaSHans Petter Selasky /* define a common SA query structure
47d6b92ffaSHans Petter Selasky * This is by no means optimal but it moves the saquery functionality out of
48d6b92ffaSHans Petter Selasky * the saquery tool and provides it to other utilities.
49d6b92ffaSHans Petter Selasky */
50d6b92ffaSHans Petter Selasky
sa_get_handle(void)51d6b92ffaSHans Petter Selasky struct sa_handle * sa_get_handle(void)
52d6b92ffaSHans Petter Selasky {
53d6b92ffaSHans Petter Selasky struct sa_handle * handle;
54d6b92ffaSHans Petter Selasky handle = calloc(1, sizeof(*handle));
55d6b92ffaSHans Petter Selasky if (!handle)
56d6b92ffaSHans Petter Selasky IBPANIC("calloc failed");
57d6b92ffaSHans Petter Selasky
58d6b92ffaSHans Petter Selasky resolve_sm_portid(ibd_ca, ibd_ca_port, &handle->dport);
59d6b92ffaSHans Petter Selasky if (!handle->dport.lid) {
60d6b92ffaSHans Petter Selasky IBWARN("No SM/SA found on port %s:%d",
61d6b92ffaSHans Petter Selasky ibd_ca ? "" : ibd_ca,
62d6b92ffaSHans Petter Selasky ibd_ca_port);
63d6b92ffaSHans Petter Selasky free(handle);
64d6b92ffaSHans Petter Selasky return (NULL);
65d6b92ffaSHans Petter Selasky }
66d6b92ffaSHans Petter Selasky
67d6b92ffaSHans Petter Selasky handle->dport.qp = 1;
68d6b92ffaSHans Petter Selasky if (!handle->dport.qkey)
69d6b92ffaSHans Petter Selasky handle->dport.qkey = IB_DEFAULT_QP1_QKEY;
70d6b92ffaSHans Petter Selasky
71d6b92ffaSHans Petter Selasky handle->fd = umad_open_port(ibd_ca, ibd_ca_port);
72d6b92ffaSHans Petter Selasky handle->agent = umad_register(handle->fd, IB_SA_CLASS, 2, 1, NULL);
73d6b92ffaSHans Petter Selasky
74d6b92ffaSHans Petter Selasky return handle;
75d6b92ffaSHans Petter Selasky }
76d6b92ffaSHans Petter Selasky
sa_set_handle(struct sa_handle * handle,int grh_present,ibmad_gid_t * gid)77d6b92ffaSHans Petter Selasky int sa_set_handle(struct sa_handle * handle, int grh_present, ibmad_gid_t *gid)
78d6b92ffaSHans Petter Selasky {
79d6b92ffaSHans Petter Selasky if (grh_present) {
80d6b92ffaSHans Petter Selasky if (gid == NULL) {
81d6b92ffaSHans Petter Selasky return -1;
82d6b92ffaSHans Petter Selasky } else {
83d6b92ffaSHans Petter Selasky handle->dport.grh_present = 1;
84d6b92ffaSHans Petter Selasky memcpy(handle->dport.gid, gid, 16);
85d6b92ffaSHans Petter Selasky }
86d6b92ffaSHans Petter Selasky }
87d6b92ffaSHans Petter Selasky return 0;
88d6b92ffaSHans Petter Selasky }
89d6b92ffaSHans Petter Selasky
sa_free_handle(struct sa_handle * h)90d6b92ffaSHans Petter Selasky void sa_free_handle(struct sa_handle * h)
91d6b92ffaSHans Petter Selasky {
92d6b92ffaSHans Petter Selasky umad_unregister(h->fd, h->agent);
93d6b92ffaSHans Petter Selasky umad_close_port(h->fd);
94d6b92ffaSHans Petter Selasky free(h);
95d6b92ffaSHans Petter Selasky }
96d6b92ffaSHans Petter Selasky
sa_query(struct sa_handle * h,uint8_t method,uint16_t attr,uint32_t mod,uint64_t comp_mask,uint64_t sm_key,void * data,size_t datasz,struct sa_query_result * result)97d6b92ffaSHans Petter Selasky int sa_query(struct sa_handle * h, uint8_t method,
98d6b92ffaSHans Petter Selasky uint16_t attr, uint32_t mod, uint64_t comp_mask,
99d6b92ffaSHans Petter Selasky uint64_t sm_key, void *data, size_t datasz,
100d6b92ffaSHans Petter Selasky struct sa_query_result *result)
101d6b92ffaSHans Petter Selasky {
102d6b92ffaSHans Petter Selasky ib_rpc_t rpc;
103d6b92ffaSHans Petter Selasky void *umad, *mad;
104d6b92ffaSHans Petter Selasky int ret, offset, len = 256;
105d6b92ffaSHans Petter Selasky
106d6b92ffaSHans Petter Selasky memset(&rpc, 0, sizeof(rpc));
107d6b92ffaSHans Petter Selasky rpc.mgtclass = IB_SA_CLASS;
108d6b92ffaSHans Petter Selasky rpc.method = method;
109d6b92ffaSHans Petter Selasky rpc.attr.id = attr;
110d6b92ffaSHans Petter Selasky rpc.attr.mod = mod;
111d6b92ffaSHans Petter Selasky rpc.mask = comp_mask;
112d6b92ffaSHans Petter Selasky rpc.datasz = datasz;
113d6b92ffaSHans Petter Selasky rpc.dataoffs = IB_SA_DATA_OFFS;
114d6b92ffaSHans Petter Selasky
115d6b92ffaSHans Petter Selasky umad = calloc(1, len + umad_size());
116d6b92ffaSHans Petter Selasky if (!umad)
117d6b92ffaSHans Petter Selasky IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
118d6b92ffaSHans Petter Selasky
119d6b92ffaSHans Petter Selasky mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
120d6b92ffaSHans Petter Selasky
121d6b92ffaSHans Petter Selasky mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
122d6b92ffaSHans Petter Selasky
123d6b92ffaSHans Petter Selasky if (ibdebug > 1)
124d6b92ffaSHans Petter Selasky xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
125d6b92ffaSHans Petter Selasky
126d6b92ffaSHans Petter Selasky if (h->dport.grh_present) {
127d6b92ffaSHans Petter Selasky ib_mad_addr_t *p_mad_addr = umad_get_mad_addr(umad);
128d6b92ffaSHans Petter Selasky p_mad_addr->grh_present = 1;
129d6b92ffaSHans Petter Selasky p_mad_addr->gid_index = 0;
130d6b92ffaSHans Petter Selasky p_mad_addr->hop_limit = 0;
131d6b92ffaSHans Petter Selasky p_mad_addr->traffic_class = 0;
132d6b92ffaSHans Petter Selasky memcpy(p_mad_addr->gid, h->dport.gid, 16);
133d6b92ffaSHans Petter Selasky }
134d6b92ffaSHans Petter Selasky
135d6b92ffaSHans Petter Selasky ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
136d6b92ffaSHans Petter Selasky if (ret < 0) {
137d6b92ffaSHans Petter Selasky IBWARN("umad_send failed: attr 0x%x: %s\n",
138d6b92ffaSHans Petter Selasky attr, strerror(errno));
139d6b92ffaSHans Petter Selasky free(umad);
140d6b92ffaSHans Petter Selasky return (-ret);
141d6b92ffaSHans Petter Selasky }
142d6b92ffaSHans Petter Selasky
143d6b92ffaSHans Petter Selasky recv_mad:
144d6b92ffaSHans Petter Selasky ret = umad_recv(h->fd, umad, &len, ibd_timeout);
145d6b92ffaSHans Petter Selasky if (ret < 0) {
146d6b92ffaSHans Petter Selasky if (errno == ENOSPC) {
147d6b92ffaSHans Petter Selasky umad = realloc(umad, umad_size() + len);
148d6b92ffaSHans Petter Selasky goto recv_mad;
149d6b92ffaSHans Petter Selasky }
150d6b92ffaSHans Petter Selasky IBWARN("umad_recv failed: attr 0x%x: %s\n", attr,
151d6b92ffaSHans Petter Selasky strerror(errno));
152d6b92ffaSHans Petter Selasky free(umad);
153d6b92ffaSHans Petter Selasky return (-ret);
154d6b92ffaSHans Petter Selasky }
155d6b92ffaSHans Petter Selasky
156d6b92ffaSHans Petter Selasky if ((ret = umad_status(umad)))
157d6b92ffaSHans Petter Selasky return ret;
158d6b92ffaSHans Petter Selasky
159d6b92ffaSHans Petter Selasky mad = umad_get_mad(umad);
160d6b92ffaSHans Petter Selasky
161d6b92ffaSHans Petter Selasky if (ibdebug > 1)
162d6b92ffaSHans Petter Selasky xdump(stdout, "SA Response:\n", mad, len);
163d6b92ffaSHans Petter Selasky
164d6b92ffaSHans Petter Selasky method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
165d6b92ffaSHans Petter Selasky offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
166d6b92ffaSHans Petter Selasky result->status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
167d6b92ffaSHans Petter Selasky result->p_result_madw = mad;
168d6b92ffaSHans Petter Selasky if (result->status != IB_SA_MAD_STATUS_SUCCESS)
169d6b92ffaSHans Petter Selasky result->result_cnt = 0;
170d6b92ffaSHans Petter Selasky else if (method != IB_MAD_METHOD_GET_TABLE)
171d6b92ffaSHans Petter Selasky result->result_cnt = 1;
172d6b92ffaSHans Petter Selasky else if (!offset)
173d6b92ffaSHans Petter Selasky result->result_cnt = 0;
174d6b92ffaSHans Petter Selasky else
175d6b92ffaSHans Petter Selasky result->result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
176d6b92ffaSHans Petter Selasky
177d6b92ffaSHans Petter Selasky return 0;
178d6b92ffaSHans Petter Selasky }
179d6b92ffaSHans Petter Selasky
sa_free_result_mad(struct sa_query_result * result)180d6b92ffaSHans Petter Selasky void sa_free_result_mad(struct sa_query_result *result)
181d6b92ffaSHans Petter Selasky {
182d6b92ffaSHans Petter Selasky if (result->p_result_madw) {
183d6b92ffaSHans Petter Selasky free((uint8_t *) result->p_result_madw - umad_size());
184d6b92ffaSHans Petter Selasky result->p_result_madw = NULL;
185d6b92ffaSHans Petter Selasky }
186d6b92ffaSHans Petter Selasky }
187d6b92ffaSHans Petter Selasky
sa_get_query_rec(void * mad,unsigned i)188d6b92ffaSHans Petter Selasky void *sa_get_query_rec(void *mad, unsigned i)
189d6b92ffaSHans Petter Selasky {
190d6b92ffaSHans Petter Selasky int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
191d6b92ffaSHans Petter Selasky return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
192d6b92ffaSHans Petter Selasky }
193d6b92ffaSHans Petter Selasky
194d6b92ffaSHans Petter Selasky static const char *ib_sa_error_str[] = {
195d6b92ffaSHans Petter Selasky "SA_NO_ERROR",
196d6b92ffaSHans Petter Selasky "SA_ERR_NO_RESOURCES",
197d6b92ffaSHans Petter Selasky "SA_ERR_REQ_INVALID",
198d6b92ffaSHans Petter Selasky "SA_ERR_NO_RECORDS",
199d6b92ffaSHans Petter Selasky "SA_ERR_TOO_MANY_RECORDS",
200d6b92ffaSHans Petter Selasky "SA_ERR_REQ_INVALID_GID",
201d6b92ffaSHans Petter Selasky "SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
202d6b92ffaSHans Petter Selasky "SA_ERR_REQ_DENIED",
203d6b92ffaSHans Petter Selasky "SA_ERR_STATUS_PRIO_SUGGESTED",
204d6b92ffaSHans Petter Selasky "SA_ERR_UNKNOWN"
205d6b92ffaSHans Petter Selasky };
206d6b92ffaSHans Petter Selasky
207d6b92ffaSHans Petter Selasky #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
208d6b92ffaSHans Petter Selasky #define SA_ERR_UNKNOWN (ARR_SIZE(ib_sa_error_str) - 1)
209d6b92ffaSHans Petter Selasky
ib_sa_err_str(IN uint8_t status)210d6b92ffaSHans Petter Selasky static inline const char *ib_sa_err_str(IN uint8_t status)
211d6b92ffaSHans Petter Selasky {
212d6b92ffaSHans Petter Selasky if (status > SA_ERR_UNKNOWN)
213d6b92ffaSHans Petter Selasky status = SA_ERR_UNKNOWN;
214d6b92ffaSHans Petter Selasky return (ib_sa_error_str[status]);
215d6b92ffaSHans Petter Selasky }
216d6b92ffaSHans Petter Selasky
217d6b92ffaSHans Petter Selasky static const char *ib_mad_inv_field_str[] = {
218d6b92ffaSHans Petter Selasky "MAD No invalid fields",
219d6b92ffaSHans Petter Selasky "MAD Bad version",
220d6b92ffaSHans Petter Selasky "MAD Method specified is not supported",
221d6b92ffaSHans Petter Selasky "MAD Method/Attribute combination is not supported",
222d6b92ffaSHans Petter Selasky "MAD Reserved",
223d6b92ffaSHans Petter Selasky "MAD Reserved",
224d6b92ffaSHans Petter Selasky "MAD Reserved",
225*d13def78SEric van Gyzen "MAD Invalid value in Attribute field(s) or Attribute Modifier",
226d6b92ffaSHans Petter Selasky "MAD UNKNOWN ERROR"
227d6b92ffaSHans Petter Selasky };
228d6b92ffaSHans Petter Selasky #define MAD_ERR_UNKNOWN (ARR_SIZE(ib_mad_inv_field_str) - 1)
229d6b92ffaSHans Petter Selasky
ib_mad_inv_field_err_str(IN uint8_t f)230d6b92ffaSHans Petter Selasky static inline const char *ib_mad_inv_field_err_str(IN uint8_t f)
231d6b92ffaSHans Petter Selasky {
232d6b92ffaSHans Petter Selasky if (f > MAD_ERR_UNKNOWN)
233d6b92ffaSHans Petter Selasky f = MAD_ERR_UNKNOWN;
234d6b92ffaSHans Petter Selasky return (ib_mad_inv_field_str[f]);
235d6b92ffaSHans Petter Selasky }
236d6b92ffaSHans Petter Selasky
sa_report_err(int status)237d6b92ffaSHans Petter Selasky void sa_report_err(int status)
238d6b92ffaSHans Petter Selasky {
239d6b92ffaSHans Petter Selasky int st = status & 0xff;
240d6b92ffaSHans Petter Selasky char mad_err_str[64] = { 0 };
241d6b92ffaSHans Petter Selasky char sa_err_str[64] = { 0 };
242d6b92ffaSHans Petter Selasky
243d6b92ffaSHans Petter Selasky if (st)
244d6b92ffaSHans Petter Selasky sprintf(mad_err_str, " (%s; %s; %s)",
245d6b92ffaSHans Petter Selasky (st & 0x1) ? "BUSY" : "",
246d6b92ffaSHans Petter Selasky (st & 0x2) ? "Redirection Required" : "",
247d6b92ffaSHans Petter Selasky ib_mad_inv_field_err_str(st>>2));
248d6b92ffaSHans Petter Selasky
249d6b92ffaSHans Petter Selasky
250d6b92ffaSHans Petter Selasky st = status >> 8;
251d6b92ffaSHans Petter Selasky if (st)
252d6b92ffaSHans Petter Selasky sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
253d6b92ffaSHans Petter Selasky
254d6b92ffaSHans Petter Selasky fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
255d6b92ffaSHans Petter Selasky status, mad_err_str, sa_err_str);
256d6b92ffaSHans Petter Selasky }
257