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 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 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 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 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 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 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 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 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 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