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-2010 Mellanox Technologies LTD. All rights reserved.
5 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
6 * Copyright (c) 2009 HNR Consulting. All rights reserved.
7 * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
9 * This software is available to you under a choice of one of two
10 * licenses. You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
23 * - Redistributions in binary form must reproduce the above
24 * copyright notice, this list of conditions and the following
25 * disclaimer in the documentation and/or other materials
26 * provided with the distribution.
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
41 #include <infiniband/umad.h>
43 #include "ibdiag_common.h"
44 #include "ibdiag_sa.h"
46 /* define a common SA query structure
47 * This is by no means optimal but it moves the saquery functionality out of
48 * the saquery tool and provides it to other utilities.
51 struct sa_handle * sa_get_handle(void)
53 struct sa_handle * handle;
54 handle = calloc(1, sizeof(*handle));
56 IBPANIC("calloc failed");
58 resolve_sm_portid(ibd_ca, ibd_ca_port, &handle->dport);
59 if (!handle->dport.lid) {
60 IBWARN("No SM/SA found on port %s:%d",
68 if (!handle->dport.qkey)
69 handle->dport.qkey = IB_DEFAULT_QP1_QKEY;
71 handle->fd = umad_open_port(ibd_ca, ibd_ca_port);
72 handle->agent = umad_register(handle->fd, IB_SA_CLASS, 2, 1, NULL);
77 int sa_set_handle(struct sa_handle * handle, int grh_present, ibmad_gid_t *gid)
83 handle->dport.grh_present = 1;
84 memcpy(handle->dport.gid, gid, 16);
90 void sa_free_handle(struct sa_handle * h)
92 umad_unregister(h->fd, h->agent);
93 umad_close_port(h->fd);
97 int sa_query(struct sa_handle * h, uint8_t method,
98 uint16_t attr, uint32_t mod, uint64_t comp_mask,
99 uint64_t sm_key, void *data, size_t datasz,
100 struct sa_query_result *result)
104 int ret, offset, len = 256;
106 memset(&rpc, 0, sizeof(rpc));
107 rpc.mgtclass = IB_SA_CLASS;
111 rpc.mask = comp_mask;
113 rpc.dataoffs = IB_SA_DATA_OFFS;
115 umad = calloc(1, len + umad_size());
117 IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
119 mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
121 mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
124 xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
126 if (h->dport.grh_present) {
127 ib_mad_addr_t *p_mad_addr = umad_get_mad_addr(umad);
128 p_mad_addr->grh_present = 1;
129 p_mad_addr->gid_index = 0;
130 p_mad_addr->hop_limit = 0;
131 p_mad_addr->traffic_class = 0;
132 memcpy(p_mad_addr->gid, h->dport.gid, 16);
135 ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
137 IBWARN("umad_send failed: attr 0x%x: %s\n",
138 attr, strerror(errno));
144 ret = umad_recv(h->fd, umad, &len, ibd_timeout);
146 if (errno == ENOSPC) {
147 umad = realloc(umad, umad_size() + len);
150 IBWARN("umad_recv failed: attr 0x%x: %s\n", attr,
156 if ((ret = umad_status(umad)))
159 mad = umad_get_mad(umad);
162 xdump(stdout, "SA Response:\n", mad, len);
164 method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
165 offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
166 result->status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
167 result->p_result_madw = mad;
168 if (result->status != IB_SA_MAD_STATUS_SUCCESS)
169 result->result_cnt = 0;
170 else if (method != IB_MAD_METHOD_GET_TABLE)
171 result->result_cnt = 1;
173 result->result_cnt = 0;
175 result->result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
180 void sa_free_result_mad(struct sa_query_result *result)
182 if (result->p_result_madw) {
183 free((uint8_t *) result->p_result_madw - umad_size());
184 result->p_result_madw = NULL;
188 void *sa_get_query_rec(void *mad, unsigned i)
190 int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
191 return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
194 static const char *ib_sa_error_str[] = {
196 "SA_ERR_NO_RESOURCES",
197 "SA_ERR_REQ_INVALID",
199 "SA_ERR_TOO_MANY_RECORDS",
200 "SA_ERR_REQ_INVALID_GID",
201 "SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
203 "SA_ERR_STATUS_PRIO_SUGGESTED",
207 #define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
208 #define SA_ERR_UNKNOWN (ARR_SIZE(ib_sa_error_str) - 1)
210 static inline const char *ib_sa_err_str(IN uint8_t status)
212 if (status > SA_ERR_UNKNOWN)
213 status = SA_ERR_UNKNOWN;
214 return (ib_sa_error_str[status]);
217 static const char *ib_mad_inv_field_str[] = {
218 "MAD No invalid fields",
220 "MAD Method specified is not supported",
221 "MAD Method/Attribute combination is not supported",
225 "MAD Invalid value in Attribute field(s) or Attribute Modifier"
228 #define MAD_ERR_UNKNOWN (ARR_SIZE(ib_mad_inv_field_str) - 1)
230 static inline const char *ib_mad_inv_field_err_str(IN uint8_t f)
232 if (f > MAD_ERR_UNKNOWN)
234 return (ib_mad_inv_field_str[f]);
237 void sa_report_err(int status)
239 int st = status & 0xff;
240 char mad_err_str[64] = { 0 };
241 char sa_err_str[64] = { 0 };
244 sprintf(mad_err_str, " (%s; %s; %s)",
245 (st & 0x1) ? "BUSY" : "",
246 (st & 0x2) ? "Redirection Required" : "",
247 ib_mad_inv_field_err_str(st>>2));
252 sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
254 fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
255 status, mad_err_str, sa_err_str);