1321936Shselasky/* 2321936Shselasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3321936Shselasky * 4321936Shselasky * This software is available to you under a choice of one of two 5321936Shselasky * licenses. You may choose to be licensed under the terms of the GNU 6321936Shselasky * General Public License (GPL) Version 2, available from the file 7321936Shselasky * COPYING in the main directory of this source tree, or the 8321936Shselasky * OpenIB.org BSD license below: 9321936Shselasky * 10321936Shselasky * Redistribution and use in source and binary forms, with or 11321936Shselasky * without modification, are permitted provided that the following 12321936Shselasky * conditions are met: 13321936Shselasky * 14321936Shselasky * - Redistributions of source code must retain the above 15321936Shselasky * copyright notice, this list of conditions and the following 16321936Shselasky * disclaimer. 17321936Shselasky * 18321936Shselasky * - Redistributions in binary form must reproduce the above 19321936Shselasky * copyright notice, this list of conditions and the following 20321936Shselasky * disclaimer in the documentation and/or other materials 21321936Shselasky * provided with the distribution. 22321936Shselasky * 23321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30321936Shselasky * SOFTWARE. 31321936Shselasky * 32321936Shselasky */ 33321936Shselasky 34321936Shselasky#if HAVE_CONFIG_H 35321936Shselasky# include <config.h> 36321936Shselasky#endif /* HAVE_CONFIG_H */ 37321936Shselasky 38321936Shselasky#include <stdio.h> 39321936Shselasky#include <stdlib.h> 40321936Shselasky#include <string.h> 41321936Shselasky#include <errno.h> 42321936Shselasky 43321936Shselasky#include <infiniband/umad.h> 44321936Shselasky#include <infiniband/mad.h> 45321936Shselasky 46321936Shselasky#include "mad_internal.h" 47321936Shselasky 48321936Shselasky#undef DEBUG 49321936Shselasky#define DEBUG if (ibdebug) IBWARN 50321936Shselasky 51321936Shselaskyint mad_send(ib_rpc_t * rpc, ib_portid_t * dport, ib_rmpp_hdr_t * rmpp, 52321936Shselasky void *data) 53321936Shselasky{ 54321936Shselasky return mad_send_via(rpc, dport, rmpp, data, ibmp); 55321936Shselasky} 56321936Shselasky 57321936Shselaskyint mad_send_via(ib_rpc_t * rpc, ib_portid_t * dport, ib_rmpp_hdr_t * rmpp, 58321936Shselasky void *data, struct ibmad_port *srcport) 59321936Shselasky{ 60321936Shselasky uint8_t pktbuf[1024]; 61321936Shselasky void *umad = pktbuf; 62321936Shselasky 63321936Shselasky memset(pktbuf, 0, umad_size() + IB_MAD_SIZE); 64321936Shselasky 65321936Shselasky DEBUG("rmpp %p data %p", rmpp, data); 66321936Shselasky 67321936Shselasky if (mad_build_pkt(umad, rpc, dport, rmpp, data) < 0) 68321936Shselasky return -1; 69321936Shselasky 70321936Shselasky if (ibdebug) { 71321936Shselasky IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz); 72321936Shselasky xdump(stderr, "mad send data\n", 73321936Shselasky (char *)umad_get_mad(umad) + rpc->dataoffs, rpc->datasz); 74321936Shselasky } 75321936Shselasky 76321936Shselasky if (umad_send(srcport->port_id, srcport->class_agents[rpc->mgtclass & 0xff], 77321936Shselasky umad, IB_MAD_SIZE, mad_get_timeout(srcport, rpc->timeout), 78321936Shselasky 0) < 0) { 79321936Shselasky IBWARN("send failed; %s", strerror(errno)); 80321936Shselasky return -1; 81321936Shselasky } 82321936Shselasky 83321936Shselasky return 0; 84321936Shselasky} 85321936Shselasky 86321936Shselaskyint mad_respond(void *umad, ib_portid_t * portid, uint32_t rstatus) 87321936Shselasky{ 88321936Shselasky return mad_respond_via(umad, portid, rstatus, ibmp); 89321936Shselasky} 90321936Shselasky 91321936Shselaskyint mad_respond_via(void *umad, ib_portid_t * portid, uint32_t rstatus, 92321936Shselasky struct ibmad_port *srcport) 93321936Shselasky{ 94321936Shselasky uint8_t *mad = umad_get_mad(umad); 95321936Shselasky ib_mad_addr_t *mad_addr; 96321936Shselasky ib_rpc_t rpc = { 0 }; 97321936Shselasky ib_portid_t rport; 98321936Shselasky int is_smi; 99321936Shselasky 100321936Shselasky if (!portid) { 101321936Shselasky if (!(mad_addr = umad_get_mad_addr(umad))) { 102321936Shselasky errno = EINVAL; 103321936Shselasky return -1; 104321936Shselasky } 105321936Shselasky 106321936Shselasky memset(&rport, 0, sizeof(rport)); 107321936Shselasky 108321936Shselasky rport.lid = ntohs(mad_addr->lid); 109321936Shselasky rport.qp = ntohl(mad_addr->qpn); 110321936Shselasky rport.qkey = ntohl(mad_addr->qkey); 111321936Shselasky rport.sl = mad_addr->sl; 112321936Shselasky 113321936Shselasky if (mad_addr->grh_present) { 114321936Shselasky rport.grh_present = 1; 115321936Shselasky memcpy(&rport.gid, &mad_addr->gid, sizeof(rport.gid)); 116321936Shselasky } 117321936Shselasky 118321936Shselasky portid = &rport; 119321936Shselasky } 120321936Shselasky 121321936Shselasky DEBUG("dest %s", portid2str(portid)); 122321936Shselasky 123321936Shselasky rpc.mgtclass = mad_get_field(mad, 0, IB_MAD_MGMTCLASS_F); 124321936Shselasky 125321936Shselasky rpc.method = mad_get_field(mad, 0, IB_MAD_METHOD_F); 126321936Shselasky if (rpc.method == IB_MAD_METHOD_SET) 127321936Shselasky rpc.method = IB_MAD_METHOD_GET; 128321936Shselasky if (rpc.method != IB_MAD_METHOD_SEND) 129321936Shselasky rpc.method |= IB_MAD_RESPONSE; 130321936Shselasky 131321936Shselasky rpc.attr.id = mad_get_field(mad, 0, IB_MAD_ATTRID_F); 132321936Shselasky rpc.attr.mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F); 133321936Shselasky if (rpc.mgtclass == IB_SA_CLASS) 134321936Shselasky rpc.recsz = mad_get_field(mad, 0, IB_SA_ATTROFFS_F); 135321936Shselasky if (mad_is_vendor_range2(rpc.mgtclass)) 136321936Shselasky rpc.oui = mad_get_field(mad, 0, IB_VEND2_OUI_F); 137321936Shselasky 138321936Shselasky rpc.trid = mad_get_field64(mad, 0, IB_MAD_TRID_F); 139321936Shselasky rpc.rstatus = rstatus; 140321936Shselasky 141321936Shselasky /* cleared by default: timeout, datasz, dataoffs, mkey, mask */ 142321936Shselasky 143321936Shselasky is_smi = rpc.mgtclass == IB_SMI_CLASS || 144321936Shselasky rpc.mgtclass == IB_SMI_DIRECT_CLASS; 145321936Shselasky 146321936Shselasky if (is_smi) 147321936Shselasky portid->qp = 0; 148321936Shselasky else if (!portid->qp) 149321936Shselasky portid->qp = 1; 150321936Shselasky 151321936Shselasky if (!portid->qkey && portid->qp == 1) 152321936Shselasky portid->qkey = IB_DEFAULT_QP1_QKEY; 153321936Shselasky 154321936Shselasky DEBUG 155321936Shselasky ("qp 0x%x class 0x%x method %d attr 0x%x mod 0x%x datasz %d off %d qkey %x", 156321936Shselasky portid->qp, rpc.mgtclass, rpc.method, rpc.attr.id, rpc.attr.mod, 157321936Shselasky rpc.datasz, rpc.dataoffs, portid->qkey); 158321936Shselasky 159321936Shselasky if (mad_build_pkt(umad, &rpc, portid, 0, 0) < 0) 160321936Shselasky return -1; 161321936Shselasky 162321936Shselasky if (ibdebug > 1) 163321936Shselasky xdump(stderr, "mad respond pkt\n", mad, IB_MAD_SIZE); 164321936Shselasky 165321936Shselasky if (umad_send 166321936Shselasky (srcport->port_id, srcport->class_agents[rpc.mgtclass], umad, 167321936Shselasky IB_MAD_SIZE, mad_get_timeout(srcport, rpc.timeout), 0) < 0) { 168321936Shselasky DEBUG("send failed; %s", strerror(errno)); 169321936Shselasky return -1; 170321936Shselasky } 171321936Shselasky 172321936Shselasky return 0; 173321936Shselasky} 174321936Shselasky 175321936Shselaskyvoid *mad_receive(void *umad, int timeout) 176321936Shselasky{ 177321936Shselasky return mad_receive_via(umad, timeout, ibmp); 178321936Shselasky} 179321936Shselasky 180321936Shselaskyvoid *mad_receive_via(void *umad, int timeout, struct ibmad_port *srcport) 181321936Shselasky{ 182321936Shselasky void *mad = umad ? umad : umad_alloc(1, umad_size() + IB_MAD_SIZE); 183321936Shselasky int agent; 184321936Shselasky int length = IB_MAD_SIZE; 185321936Shselasky 186321936Shselasky if ((agent = umad_recv(srcport->port_id, mad, &length, 187321936Shselasky mad_get_timeout(srcport, timeout))) < 0) { 188321936Shselasky if (!umad) 189321936Shselasky umad_free(mad); 190321936Shselasky DEBUG("recv failed: %s", strerror(errno)); 191321936Shselasky return 0; 192321936Shselasky } 193321936Shselasky 194321936Shselasky return mad; 195321936Shselasky} 196321936Shselasky 197321936Shselaskyvoid *mad_alloc(void) 198321936Shselasky{ 199321936Shselasky return umad_alloc(1, umad_size() + IB_MAD_SIZE); 200321936Shselasky} 201321936Shselasky 202321936Shselaskyvoid mad_free(void *umad) 203321936Shselasky{ 204321936Shselasky umad_free(umad); 205321936Shselasky} 206