|
Packit |
db064d |
/*
|
|
Packit |
db064d |
* Copyright (c) 2006-2007 The Regents of the University of California.
|
|
Packit |
db064d |
* Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 2009 HNR Consulting. All rights reserved.
|
|
Packit |
db064d |
* Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* This software is available to you under a choice of one of two
|
|
Packit |
db064d |
* licenses. You may choose to be licensed under the terms of the GNU
|
|
Packit |
db064d |
* General Public License (GPL) Version 2, available from the file
|
|
Packit |
db064d |
* COPYING in the main directory of this source tree, or the
|
|
Packit |
db064d |
* OpenIB.org BSD license below:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* Redistribution and use in source and binary forms, with or
|
|
Packit |
db064d |
* without modification, are permitted provided that the following
|
|
Packit |
db064d |
* conditions are met:
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions of source code must retain the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* - Redistributions in binary form must reproduce the above
|
|
Packit |
db064d |
* copyright notice, this list of conditions and the following
|
|
Packit |
db064d |
* disclaimer in the documentation and/or other materials
|
|
Packit |
db064d |
* provided with the distribution.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
Packit |
db064d |
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
Packit |
db064d |
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
Packit |
db064d |
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
Packit |
db064d |
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
Packit |
db064d |
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit |
db064d |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
Packit |
db064d |
* SOFTWARE.
|
|
Packit |
db064d |
*
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include <errno.h>
|
|
Packit |
db064d |
#include <infiniband/umad.h>
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#include "ibdiag_common.h"
|
|
Packit |
db064d |
#include "ibdiag_sa.h"
|
|
Packit |
db064d |
|
|
Packit |
db064d |
/* define a common SA query structure
|
|
Packit |
db064d |
* This is by no means optimal but it moves the saquery functionality out of
|
|
Packit |
db064d |
* the saquery tool and provides it to other utilities.
|
|
Packit |
db064d |
*/
|
|
Packit |
db064d |
|
|
Packit |
db064d |
struct sa_handle * sa_get_handle(void)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
struct sa_handle * handle;
|
|
Packit |
db064d |
handle = calloc(1, sizeof(*handle));
|
|
Packit |
db064d |
if (!handle)
|
|
Packit |
db064d |
IBPANIC("calloc failed");
|
|
Packit |
db064d |
|
|
Packit |
db064d |
resolve_sm_portid(ibd_ca, ibd_ca_port, &handle->dport);
|
|
Packit |
db064d |
if (!handle->dport.lid) {
|
|
Packit |
db064d |
IBWARN("No SM/SA found on port %s:%d",
|
|
Packit |
db064d |
ibd_ca ? "" : ibd_ca,
|
|
Packit |
db064d |
ibd_ca_port);
|
|
Packit |
db064d |
goto err;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
handle->dport.qp = 1;
|
|
Packit |
db064d |
if (!handle->dport.qkey)
|
|
Packit |
db064d |
handle->dport.qkey = IB_DEFAULT_QP1_QKEY;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((handle->fd = umad_open_port(ibd_ca, ibd_ca_port)) < 0) {
|
|
Packit |
db064d |
IBWARN("umad_open_port on port %s:%d failed",
|
|
Packit |
db064d |
ibd_ca ? "" : ibd_ca,
|
|
Packit |
db064d |
ibd_ca_port);
|
|
Packit |
db064d |
goto err;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
if ((handle->agent = umad_register(handle->fd, IB_SA_CLASS, 2, 1, NULL)) < 0) {
|
|
Packit |
db064d |
umad_close_port(handle->fd);
|
|
Packit |
db064d |
IBWARN("umad_register for SA class failed on port %s:%d",
|
|
Packit |
db064d |
ibd_ca ? "" : ibd_ca,
|
|
Packit |
db064d |
ibd_ca_port);
|
|
Packit |
db064d |
goto err;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return handle;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
err:
|
|
Packit |
db064d |
free(handle);
|
|
Packit |
db064d |
return (NULL);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
void sa_free_handle(struct sa_handle * h)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
umad_unregister(h->fd, h->agent);
|
|
Packit |
db064d |
umad_close_port(h->fd);
|
|
Packit |
db064d |
free(h);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
int sa_query(struct sa_handle * h, uint8_t method,
|
|
Packit |
db064d |
uint16_t attr, uint32_t mod, uint64_t comp_mask,
|
|
Packit |
db064d |
uint64_t sm_key, void *data, size_t datasz,
|
|
Packit |
db064d |
struct sa_query_result *result)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
ib_rpc_t rpc;
|
|
Packit |
db064d |
void *umad, *mad;
|
|
Packit |
db064d |
int ret, offset, len = 256;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
memset(&rpc, 0, sizeof(rpc));
|
|
Packit |
db064d |
rpc.mgtclass = IB_SA_CLASS;
|
|
Packit |
db064d |
rpc.method = method;
|
|
Packit |
db064d |
rpc.attr.id = attr;
|
|
Packit |
db064d |
rpc.attr.mod = mod;
|
|
Packit |
db064d |
rpc.mask = comp_mask;
|
|
Packit |
db064d |
rpc.datasz = datasz;
|
|
Packit |
db064d |
rpc.dataoffs = IB_SA_DATA_OFFS;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
umad = calloc(1, len + umad_size());
|
|
Packit |
db064d |
if (!umad)
|
|
Packit |
db064d |
IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibdebug > 1)
|
|
Packit |
db064d |
xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
|
|
Packit |
db064d |
if (ret < 0) {
|
|
Packit |
db064d |
IBWARN("umad_send failed: attr 0x%x: %s\n",
|
|
Packit |
db064d |
attr, strerror(errno));
|
|
Packit |
db064d |
free(umad);
|
|
Packit |
db064d |
return (-ret);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
recv_mad:
|
|
Packit |
db064d |
ret = umad_recv(h->fd, umad, &len, ibd_timeout);
|
|
Packit |
db064d |
if (ret < 0) {
|
|
Packit |
db064d |
if (errno == ENOSPC) {
|
|
Packit |
db064d |
umad = realloc(umad, umad_size() + len);
|
|
Packit |
db064d |
goto recv_mad;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
IBWARN("umad_recv failed: attr 0x%x: %s\n", attr,
|
|
Packit |
db064d |
strerror(errno));
|
|
Packit |
db064d |
free(umad);
|
|
Packit |
db064d |
return (-ret);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if ((ret = umad_status(umad)))
|
|
Packit |
db064d |
return ret;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
mad = umad_get_mad(umad);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (ibdebug > 1)
|
|
Packit |
db064d |
xdump(stdout, "SA Response:\n", mad, len);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
|
|
Packit |
db064d |
offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
|
|
Packit |
db064d |
result->status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
|
|
Packit |
db064d |
result->p_result_madw = mad;
|
|
Packit |
db064d |
if (result->status != IB_SA_MAD_STATUS_SUCCESS)
|
|
Packit |
db064d |
result->result_cnt = 0;
|
|
Packit |
db064d |
else if (method != IB_MAD_METHOD_GET_TABLE)
|
|
Packit |
db064d |
result->result_cnt = 1;
|
|
Packit |
db064d |
else if (!offset)
|
|
Packit |
db064d |
result->result_cnt = 0;
|
|
Packit |
db064d |
else
|
|
Packit |
db064d |
result->result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
|
|
Packit |
db064d |
|
|
Packit |
db064d |
return 0;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
void sa_free_result_mad(struct sa_query_result *result)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (result->p_result_madw) {
|
|
Packit |
db064d |
free((uint8_t *) result->p_result_madw - umad_size());
|
|
Packit |
db064d |
result->p_result_madw = NULL;
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
void *sa_get_query_rec(void *mad, unsigned i)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
|
|
Packit |
db064d |
return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static const char *ib_sa_error_str[] = {
|
|
Packit |
db064d |
"SA_NO_ERROR",
|
|
Packit |
db064d |
"SA_ERR_NO_RESOURCES",
|
|
Packit |
db064d |
"SA_ERR_REQ_INVALID",
|
|
Packit |
db064d |
"SA_ERR_NO_RECORDS",
|
|
Packit |
db064d |
"SA_ERR_TOO_MANY_RECORDS",
|
|
Packit |
db064d |
"SA_ERR_REQ_INVALID_GID",
|
|
Packit |
db064d |
"SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
|
|
Packit |
db064d |
"SA_ERR_REQ_DENIED",
|
|
Packit |
db064d |
"SA_ERR_STATUS_PRIO_SUGGESTED",
|
|
Packit |
db064d |
"SA_ERR_UNKNOWN"
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
|
|
Packit |
db064d |
#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
|
|
Packit |
db064d |
#define SA_ERR_UNKNOWN (ARR_SIZE(ib_sa_error_str) - 1)
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static inline const char *ib_sa_err_str(uint8_t status)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (status > SA_ERR_UNKNOWN)
|
|
Packit |
db064d |
status = SA_ERR_UNKNOWN;
|
|
Packit |
db064d |
return (ib_sa_error_str[status]);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static const char *ib_mad_inv_field_str[] = {
|
|
Packit |
db064d |
"MAD No invalid fields",
|
|
Packit |
db064d |
"MAD Bad version",
|
|
Packit |
db064d |
"MAD Method specified is not supported",
|
|
Packit |
db064d |
"MAD Method/Attribute combination is not supported",
|
|
Packit |
db064d |
"MAD Reserved",
|
|
Packit |
db064d |
"MAD Reserved",
|
|
Packit |
db064d |
"MAD Reserved",
|
|
Packit |
db064d |
"MAD Invalid value in Attribute field(s) or Attribute Modifier",
|
|
Packit |
db064d |
"MAD UNKNOWN ERROR"
|
|
Packit |
db064d |
};
|
|
Packit |
db064d |
#define MAD_ERR_UNKNOWN (ARR_SIZE(ib_mad_inv_field_str) - 1)
|
|
Packit |
db064d |
|
|
Packit |
db064d |
static inline const char *ib_mad_inv_field_err_str(uint8_t f)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
if (f > MAD_ERR_UNKNOWN)
|
|
Packit |
db064d |
f = MAD_ERR_UNKNOWN;
|
|
Packit |
db064d |
return (ib_mad_inv_field_str[f]);
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
void sa_report_err(int status)
|
|
Packit |
db064d |
{
|
|
Packit |
db064d |
int st = status & 0xff;
|
|
Packit |
db064d |
char mad_err_str[128] = { 0 };
|
|
Packit |
db064d |
char sa_err_str[64] = { 0 };
|
|
Packit |
db064d |
int rc;
|
|
Packit |
db064d |
|
|
Packit |
db064d |
if (st) {
|
|
Packit |
db064d |
rc = snprintf(mad_err_str, sizeof(mad_err_str), " (%s; %s; %s)",
|
|
Packit |
db064d |
(st & 0x1) ? "BUSY" : "",
|
|
Packit |
db064d |
(st & 0x2) ? "Redirection Required" : "",
|
|
Packit |
db064d |
ib_mad_inv_field_err_str(st>>2));
|
|
Packit |
db064d |
if (rc > sizeof(mad_err_str))
|
|
Packit |
db064d |
fprintf(stderr, "WARN: string buffer overflow\n");
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
st = status >> 8;
|
|
Packit |
db064d |
if (st) {
|
|
Packit |
db064d |
rc = snprintf(sa_err_str, sizeof(sa_err_str), " SA(%s)",
|
|
Packit |
db064d |
ib_sa_err_str((uint8_t) st));
|
|
Packit |
db064d |
if (rc > sizeof(sa_err_str))
|
|
Packit |
db064d |
fprintf(stderr, "WARN: string buffer overflow\n");
|
|
Packit |
db064d |
}
|
|
Packit |
db064d |
|
|
Packit |
db064d |
fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
|
|
Packit |
db064d |
status, mad_err_str, sa_err_str);
|
|
Packit |
db064d |
}
|