2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2009 HNR Consulting. All rights reserved.
4 * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 #endif /* HAVE_CONFIG_H */
45 #include <infiniband/umad.h>
46 #include <infiniband/mad.h>
48 #include "mad_internal.h"
52 static struct ibmad_port mad_port;
53 struct ibmad_port *ibmp = &mad_port;
57 int madrpc_retries = MAD_DEF_RETRIES;
58 int madrpc_timeout = MAD_DEF_TIMEOUT_MS;
60 static void *save_mad;
61 static int save_mad_len = 256;
64 #define DEBUG if (ibdebug) IBWARN
65 #define ERRS(fmt, ...) do { \
66 if (iberrs || ibdebug) \
67 IBWARN(fmt, ## __VA_ARGS__); \
70 #define MAD_TID(mad) (*((uint64_t *)((char *)(mad) + 8)))
72 void madrpc_show_errors(int set)
77 void madrpc_save_mad(void *madbuf, int len)
83 int madrpc_set_retries(int retries)
86 madrpc_retries = retries;
87 return madrpc_retries;
90 int madrpc_set_timeout(int timeout)
92 madrpc_timeout = timeout;
96 void mad_rpc_set_retries(struct ibmad_port *port, int retries)
98 port->retries = retries;
101 void mad_rpc_set_timeout(struct ibmad_port *port, int timeout)
103 port->timeout = timeout;
106 int madrpc_def_timeout(void)
108 return madrpc_timeout;
111 int madrpc_portid(void)
113 return ibmp->port_id;
116 int mad_rpc_portid(struct ibmad_port *srcport)
118 return srcport->port_id;
121 int mad_rpc_class_agent(struct ibmad_port *port, int class)
123 if (class < 1 || class >= MAX_CLASS)
125 return port->class_agents[class];
129 _do_madrpc(int port_id, void *sndbuf, void *rcvbuf, int agentid, int len,
130 int timeout, int max_retries, int *p_error)
132 uint32_t trid; /* only low 32 bits - see mad_trid() */
137 IBWARN(">>> sending: len %d pktsz %zu", len, umad_size() + len);
138 xdump(stderr, "send buf\n", sndbuf, umad_size() + len);
142 memcpy(save_mad, umad_get_mad(sndbuf),
143 save_mad_len < len ? save_mad_len : len);
147 if (max_retries <= 0) {
150 ERRS("max_retries %d <= 0", max_retries);
155 (uint32_t) mad_get_field64(umad_get_mad(sndbuf), 0, IB_MAD_TRID_F);
157 for (retries = 0; retries < max_retries; retries++) {
159 ERRS("retry %d (timeout %d ms)", retries, timeout);
162 if (umad_send(port_id, agentid, sndbuf, length, timeout, 0) < 0) {
163 IBWARN("send failed; %s", strerror(errno));
167 /* Use same timeout on receive side just in case */
168 /* send packet is lost somewhere. */
171 if (umad_recv(port_id, rcvbuf, &length, timeout) < 0) {
172 IBWARN("recv failed: %s", strerror(errno));
177 umad_addr_dump(umad_get_mad_addr(rcvbuf));
180 xdump(stderr, "rcv buf\n", umad_get_mad(rcvbuf),
184 mad_get_field64(umad_get_mad(rcvbuf), 0,
185 IB_MAD_TRID_F) != trid);
187 status = umad_status(rcvbuf);
189 return length; /* done */
190 if (status == ENOMEM)
195 *p_error = ETIMEDOUT;
196 ERRS("timeout after %d retries, %d ms", retries, timeout * retries);
200 static int redirect_port(ib_portid_t * port, uint8_t * mad)
202 port->lid = mad_get_field(mad, 64, IB_CPI_REDIRECT_LID_F);
204 IBWARN("GID-based redirection is not supported");
208 port->qp = mad_get_field(mad, 64, IB_CPI_REDIRECT_QP_F);
209 port->qkey = mad_get_field(mad, 64, IB_CPI_REDIRECT_QKEY_F);
210 port->sl = (uint8_t) mad_get_field(mad, 64, IB_CPI_REDIRECT_SL_F);
212 /* TODO: Reverse map redirection P_Key to P_Key index */
215 IBWARN("redirected to lid %d, qp 0x%x, qkey 0x%x, sl 0x%x",
216 port->lid, port->qp, port->qkey, port->sl);
221 void *mad_rpc(const struct ibmad_port *port, ib_rpc_t * rpc,
222 ib_portid_t * dport, void *payload, void *rcvdata)
225 uint8_t sndbuf[1024], rcvbuf[1024], *mad;
226 ib_rpc_v1_t *rpcv1 = (ib_rpc_v1_t *)rpc;
229 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
233 memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
235 if ((len = mad_build_pkt(sndbuf, rpc, dport, 0, payload)) < 0)
238 if ((len = _do_madrpc(port->port_id, sndbuf, rcvbuf,
239 port->class_agents[rpc->mgtclass & 0xff],
240 len, mad_get_timeout(port, rpc->timeout),
241 mad_get_retries(port), &error)) < 0) {
242 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) ==
244 rpcv1->error = error;
245 IBWARN("_do_madrpc failed; dport (%s)",
250 mad = umad_get_mad(rcvbuf);
251 status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F);
253 /* check for exact match instead of only the redirect bit;
254 * that way, weird statuses cause an error, too */
255 if (status == IB_MAD_STS_REDIRECT) {
256 /* update dport for next request and retry */
257 /* bail if redirection fails */
258 if (redirect_port(dport, mad))
264 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
265 rpcv1->error = error;
266 rpc->rstatus = status;
269 ERRS("MAD completed with error status 0x%x; dport (%s)",
270 status, portid2str(dport));
276 IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz);
277 xdump(stderr, "mad data\n", mad + rpc->dataoffs, rpc->datasz);
281 memcpy(rcvdata, mad + rpc->dataoffs, rpc->datasz);
286 void *mad_rpc_rmpp(const struct ibmad_port *port, ib_rpc_t * rpc,
287 ib_portid_t * dport, ib_rmpp_hdr_t * rmpp, void *data)
290 uint8_t sndbuf[1024], rcvbuf[1024], *mad;
291 ib_rpc_v1_t *rpcv1 = (ib_rpc_v1_t *)rpc;
294 memset(sndbuf, 0, umad_size() + IB_MAD_SIZE);
296 DEBUG("rmpp %p data %p", rmpp, data);
298 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
300 if ((len = mad_build_pkt(sndbuf, rpc, dport, rmpp, data)) < 0)
303 if ((len = _do_madrpc(port->port_id, sndbuf, rcvbuf,
304 port->class_agents[rpc->mgtclass & 0xff],
305 len, mad_get_timeout(port, rpc->timeout),
306 mad_get_retries(port), &error)) < 0) {
307 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
308 rpcv1->error = error;
309 IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport));
313 if ((rpc->mgtclass & IB_MAD_RPC_VERSION_MASK) == IB_MAD_RPC_VERSION1)
314 rpcv1->error = error;
316 mad = umad_get_mad(rcvbuf);
318 if ((status = mad_get_field(mad, 0, IB_MAD_STATUS_F)) != 0) {
319 ERRS("MAD completed with error status 0x%x; dport (%s)",
320 status, portid2str(dport));
326 IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz);
327 xdump(stderr, "rmpp mad data\n", mad + rpc->dataoffs,
332 rmpp->flags = mad_get_field(mad, 0, IB_SA_RMPP_FLAGS_F);
333 if ((rmpp->flags & 0x3) &&
334 mad_get_field(mad, 0, IB_SA_RMPP_VERS_F) != 1) {
335 IBWARN("bad rmpp version");
338 rmpp->type = mad_get_field(mad, 0, IB_SA_RMPP_TYPE_F);
339 rmpp->status = mad_get_field(mad, 0, IB_SA_RMPP_STATUS_F);
340 DEBUG("rmpp type %d status %d", rmpp->type, rmpp->status);
341 rmpp->d1.u = mad_get_field(mad, 0, IB_SA_RMPP_D1_F);
342 rmpp->d2.u = mad_get_field(mad, 0, IB_SA_RMPP_D2_F);
346 memcpy(data, mad + rpc->dataoffs, rpc->datasz);
348 rpc->recsz = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
353 void *madrpc(ib_rpc_t * rpc, ib_portid_t * dport, void *payload, void *rcvdata)
355 return mad_rpc(ibmp, rpc, dport, payload, rcvdata);
358 void *madrpc_rmpp(ib_rpc_t * rpc, ib_portid_t * dport, ib_rmpp_hdr_t * rmpp,
361 return mad_rpc_rmpp(ibmp, rpc, dport, rmpp, data);
365 madrpc_init(char *dev_name, int dev_port, int *mgmt_classes, int num_classes)
370 IBPANIC("can't init UMAD library");
372 if ((fd = umad_open_port(dev_name, dev_port)) < 0)
373 IBPANIC("can't open UMAD port (%s:%d)",
374 dev_name ? dev_name : "(nil)", dev_port);
376 if (num_classes >= MAX_CLASS)
377 IBPANIC("too many classes %d requested", num_classes);
380 memset(ibmp->class_agents, 0xff, sizeof ibmp->class_agents);
381 while (num_classes--) {
382 uint8_t rmpp_version = 0;
383 int mgmt = *mgmt_classes++;
385 if (mgmt == IB_SA_CLASS)
387 if (mad_register_client_via(mgmt, rmpp_version, ibmp) < 0)
388 IBPANIC("client_register for mgmt class %d failed",
393 struct ibmad_port *mad_rpc_open_port(char *dev_name, int dev_port,
394 int *mgmt_classes, int num_classes)
396 struct ibmad_port *p;
399 if (num_classes >= MAX_CLASS) {
400 IBWARN("too many classes %d requested", num_classes);
405 if (umad_init() < 0) {
406 IBWARN("can't init UMAD library");
411 p = malloc(sizeof(*p));
416 memset(p, 0, sizeof(*p));
418 if ((port_id = umad_open_port(dev_name, dev_port)) < 0) {
419 IBWARN("can't open UMAD port (%s:%d)", dev_name, dev_port);
426 p->port_id = port_id;
428 strncpy(p->ca_name, dev_name, sizeof p->ca_name - 1);
429 p->portnum = dev_port;
431 memset(p->class_agents, 0xff, sizeof p->class_agents);
432 while (num_classes--) {
433 uint8_t rmpp_version = 0;
434 int mgmt = *mgmt_classes++;
436 if (mgmt == IB_SA_CLASS)
438 if (mgmt < 0 || mgmt >= MAX_CLASS ||
439 mad_register_client_via(mgmt, rmpp_version, p) < 0) {
440 IBWARN("client_register for mgmt %d failed", mgmt);
443 umad_close_port(port_id);
452 void mad_rpc_close_port(struct ibmad_port *port)
454 umad_close_port(port->port_id);