1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004,2005 Voltaire Inc. All rights reserved. 3219820Sjeff * 4219820Sjeff * This software is available to you under a choice of one of two 5219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 6219820Sjeff * General Public License (GPL) Version 2, available from the file 7219820Sjeff * COPYING in the main directory of this source tree, or the 8219820Sjeff * OpenIB.org BSD license below: 9219820Sjeff * 10219820Sjeff * Redistribution and use in source and binary forms, with or 11219820Sjeff * without modification, are permitted provided that the following 12219820Sjeff * conditions are met: 13219820Sjeff * 14219820Sjeff * - Redistributions of source code must retain the above 15219820Sjeff * copyright notice, this list of conditions and the following 16219820Sjeff * disclaimer. 17219820Sjeff * 18219820Sjeff * - Redistributions in binary form must reproduce the above 19219820Sjeff * copyright notice, this list of conditions and the following 20219820Sjeff * disclaimer in the documentation and/or other materials 21219820Sjeff * provided with the distribution. 22219820Sjeff * 23219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30219820Sjeff * SOFTWARE. 31219820Sjeff * 32219820Sjeff */ 33219820Sjeff 34219820Sjeff#if HAVE_CONFIG_H 35219820Sjeff# include <config.h> 36219820Sjeff#endif /* HAVE_CONFIG_H */ 37219820Sjeff 38219820Sjeff#include <stdio.h> 39219820Sjeff#include <stdlib.h> 40219820Sjeff#include <unistd.h> 41219820Sjeff#include <pthread.h> 42219820Sjeff#include <sys/time.h> 43219820Sjeff#include <string.h> 44219820Sjeff#include <netinet/in.h> 45219820Sjeff 46219820Sjeff#include <infiniband/common.h> 47219820Sjeff#include <infiniband/umad.h> 48219820Sjeff#include <mad.h> 49219820Sjeff 50219820Sjeff#undef DEBUG 51219820Sjeff#define DEBUG if (ibdebug) IBWARN 52219820Sjeff 53219820Sjeffint 54219820Sjeffmad_send(ib_rpc_t *rpc, ib_portid_t *dport, ib_rmpp_hdr_t *rmpp, void *data) 55219820Sjeff{ 56219820Sjeff uint8_t pktbuf[1024]; 57219820Sjeff void *umad = pktbuf; 58219820Sjeff 59219820Sjeff memset(pktbuf, 0, umad_size()); 60219820Sjeff 61219820Sjeff DEBUG("rmpp %p data %p", rmpp, data); 62219820Sjeff 63219820Sjeff if (mad_build_pkt(umad, rpc, dport, rmpp, data) < 0) 64219820Sjeff return 0; 65219820Sjeff 66219820Sjeff if (ibdebug) { 67219820Sjeff IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz); 68219820Sjeff xdump(stderr, "mad send data\n", 69219820Sjeff (char *)umad_get_mad(umad) + rpc->dataoffs, rpc->datasz); 70219820Sjeff } 71219820Sjeff 72219820Sjeff if (umad_send(madrpc_portid(), mad_class_agent(rpc->mgtclass), 73219820Sjeff umad, IB_MAD_SIZE, rpc->timeout, 0) < 0) { 74219820Sjeff IBWARN("send failed; %m"); 75219820Sjeff return -1; 76219820Sjeff } 77219820Sjeff 78219820Sjeff return 0; 79219820Sjeff} 80219820Sjeff 81219820Sjeffint 82219820Sjeffmad_respond(void *umad, ib_portid_t *portid, uint32_t rstatus) 83219820Sjeff{ 84219820Sjeff uint8_t *mad = umad_get_mad(umad); 85219820Sjeff ib_mad_addr_t *mad_addr; 86219820Sjeff ib_rpc_t rpc = {0}; 87219820Sjeff ib_portid_t rport; 88219820Sjeff int is_smi; 89219820Sjeff 90219820Sjeff if (!portid) { 91219820Sjeff if (!(mad_addr = umad_get_mad_addr(umad))) 92219820Sjeff return -1; 93219820Sjeff 94219820Sjeff memset(&rport, 0, sizeof(rport)); 95219820Sjeff 96219820Sjeff rport.lid = ntohs(mad_addr->lid); 97219820Sjeff rport.qp = ntohl(mad_addr->qpn); 98219820Sjeff rport.qkey = ntohl(mad_addr->qkey); 99219820Sjeff rport.sl = mad_addr->sl; 100219820Sjeff 101219820Sjeff portid = &rport; 102219820Sjeff } 103219820Sjeff 104219820Sjeff DEBUG("dest %s", portid2str(portid)); 105219820Sjeff 106219820Sjeff rpc.mgtclass = mad_get_field(mad, 0, IB_MAD_MGMTCLASS_F); 107219820Sjeff 108219820Sjeff rpc.method = mad_get_field(mad, 0, IB_MAD_METHOD_F); 109219820Sjeff if (rpc.method == IB_MAD_METHOD_SET) 110219820Sjeff rpc.method = IB_MAD_METHOD_GET; 111219820Sjeff if (rpc.method != IB_MAD_METHOD_SEND) 112219820Sjeff rpc.method |= IB_MAD_RESPONSE; 113219820Sjeff 114219820Sjeff rpc.attr.id = mad_get_field(mad, 0, IB_MAD_ATTRID_F); 115219820Sjeff rpc.attr.mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F); 116219820Sjeff if (rpc.mgtclass == IB_SA_CLASS) 117219820Sjeff rpc.recsz = mad_get_field(mad, 0, IB_SA_ATTROFFS_F); 118219820Sjeff if (mad_is_vendor_range2(rpc.mgtclass)) 119219820Sjeff rpc.oui = mad_get_field(mad, 0, IB_VEND2_OUI_F); 120219820Sjeff 121219820Sjeff rpc.trid = mad_get_field64(mad, 0, IB_MAD_TRID_F); 122219820Sjeff 123219820Sjeff /* cleared by default: timeout, datasz, dataoffs, mkey, mask */ 124219820Sjeff 125219820Sjeff is_smi = rpc.mgtclass == IB_SMI_CLASS || 126219820Sjeff rpc.mgtclass == IB_SMI_DIRECT_CLASS; 127219820Sjeff 128219820Sjeff if (is_smi) 129219820Sjeff portid->qp = 0; 130219820Sjeff else if (!portid->qp) 131219820Sjeff portid->qp = 1; 132219820Sjeff 133219820Sjeff if (!portid->qkey && portid->qp == 1) 134219820Sjeff portid->qkey = IB_DEFAULT_QP1_QKEY; 135219820Sjeff 136219820Sjeff DEBUG("qp 0x%x class 0x%x method %d attr 0x%x mod 0x%x datasz %d off %d qkey %x", 137219820Sjeff portid->qp, rpc.mgtclass, rpc.method, rpc.attr.id, rpc.attr.mod, 138219820Sjeff rpc.datasz, rpc.dataoffs, portid->qkey); 139219820Sjeff 140219820Sjeff if (mad_build_pkt(umad, &rpc, portid, 0, 0) < 0) 141219820Sjeff return -1; 142219820Sjeff 143219820Sjeff if (ibdebug > 1) 144219820Sjeff xdump(stderr, "mad respond pkt\n", mad, IB_MAD_SIZE); 145219820Sjeff 146219820Sjeff if (umad_send(madrpc_portid(), mad_class_agent(rpc.mgtclass), umad, 147219820Sjeff IB_MAD_SIZE, rpc.timeout, 0) < 0) { 148219820Sjeff DEBUG("send failed; %m"); 149219820Sjeff return -1; 150219820Sjeff } 151219820Sjeff 152219820Sjeff return 0; 153219820Sjeff} 154219820Sjeff 155219820Sjeffvoid * 156219820Sjeffmad_receive(void *umad, int timeout) 157219820Sjeff{ 158219820Sjeff void *mad = umad ? umad : umad_alloc(1, umad_size() + IB_MAD_SIZE); 159219820Sjeff int agent; 160219820Sjeff int length = IB_MAD_SIZE; 161219820Sjeff 162219820Sjeff if ((agent = umad_recv(madrpc_portid(), mad, 163219820Sjeff &length, timeout)) < 0) { 164219820Sjeff if (!umad) 165219820Sjeff umad_free(mad); 166219820Sjeff DEBUG("recv failed: %m"); 167219820Sjeff return 0; 168219820Sjeff } 169219820Sjeff 170219820Sjeff return mad; 171219820Sjeff} 172219820Sjeff 173219820Sjeffvoid * 174219820Sjeffmad_alloc(void) 175219820Sjeff{ 176219820Sjeff return umad_alloc(1, umad_size() + IB_MAD_SIZE); 177219820Sjeff} 178219820Sjeff 179219820Sjeffvoid 180219820Sjeffmad_free(void *umad) 181219820Sjeff{ 182219820Sjeff umad_free(umad); 183219820Sjeff} 184