1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2007 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 <string.h> 42219820Sjeff#include <pthread.h> 43219820Sjeff#include <sys/time.h> 44219820Sjeff 45219820Sjeff#include <infiniband/common.h> 46219820Sjeff#include <infiniband/umad.h> 47219820Sjeff#include <mad.h> 48219820Sjeff 49219820Sjeff#undef DEBUG 50219820Sjeff#define DEBUG if (ibdebug) IBWARN 51219820Sjeff 52219820Sjeffvoid 53219820Sjeffmad_decode_field(uint8_t *buf, int field, void *val) 54219820Sjeff{ 55219820Sjeff ib_field_t *f = ib_mad_f + field; 56219820Sjeff 57219820Sjeff if (!field) { 58219820Sjeff *(int *)val = *(int *)buf; 59219820Sjeff return; 60219820Sjeff } 61219820Sjeff if (f->bitlen <= 32) { 62219820Sjeff *(uint32_t *)val = _get_field(buf, 0, f); 63219820Sjeff return; 64219820Sjeff } 65219820Sjeff if (f->bitlen == 64) { 66219820Sjeff *(uint64_t *)val = _get_field64(buf, 0, f); 67219820Sjeff return; 68219820Sjeff } 69219820Sjeff _get_array(buf, 0, f, val); 70219820Sjeff} 71219820Sjeff 72219820Sjeffvoid 73219820Sjeffmad_encode_field(uint8_t *buf, int field, void *val) 74219820Sjeff{ 75219820Sjeff ib_field_t *f = ib_mad_f + field; 76219820Sjeff 77219820Sjeff if (!field) { 78219820Sjeff *(int *)buf = *(int *)val; 79219820Sjeff return; 80219820Sjeff } 81219820Sjeff if (f->bitlen <= 32) { 82219820Sjeff _set_field(buf, 0, f, *(uint32_t *)val); 83219820Sjeff return; 84219820Sjeff } 85219820Sjeff if (f->bitlen == 64) { 86219820Sjeff _set_field64(buf, 0, f, *(uint64_t *)val); 87219820Sjeff return; 88219820Sjeff } 89219820Sjeff _set_array(buf, 0, f, val); 90219820Sjeff} 91219820Sjeff 92219820Sjeffuint64_t 93219820Sjeffmad_trid(void) 94219820Sjeff{ 95219820Sjeff static uint64_t base; 96219820Sjeff static uint64_t trid; 97219820Sjeff uint64_t next; 98219820Sjeff 99219820Sjeff if (!base) { 100219820Sjeff srandom(time(0)*getpid()); 101219820Sjeff base = random(); 102219820Sjeff trid = random(); 103219820Sjeff } 104219820Sjeff next = ++trid | (base << 32); 105219820Sjeff return next; 106219820Sjeff} 107219820Sjeff 108219820Sjeffvoid * 109219820Sjeffmad_encode(void *buf, ib_rpc_t *rpc, ib_dr_path_t *drpath, void *data) 110219820Sjeff{ 111219820Sjeff int is_resp = rpc->method & IB_MAD_RESPONSE; 112219820Sjeff 113219820Sjeff /* first word */ 114219820Sjeff mad_set_field(buf, 0, IB_MAD_METHOD_F, rpc->method); 115219820Sjeff mad_set_field(buf, 0, IB_MAD_RESPONSE_F, is_resp ? 1 : 0); 116219820Sjeff mad_set_field(buf, 0, IB_MAD_CLASSVER_F, rpc->mgtclass == IB_SA_CLASS ? 2 : 1); 117219820Sjeff mad_set_field(buf, 0, IB_MAD_MGMTCLASS_F, rpc->mgtclass); 118219820Sjeff mad_set_field(buf, 0, IB_MAD_BASEVER_F, 1); 119219820Sjeff 120219820Sjeff /* second word */ 121219820Sjeff if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) { 122219820Sjeff if (!drpath) { 123219820Sjeff IBWARN("encoding dr mad without drpath (null)"); 124219820Sjeff return 0; 125219820Sjeff } 126219820Sjeff mad_set_field(buf, 0, IB_DRSMP_HOPCNT_F, drpath->cnt); 127219820Sjeff mad_set_field(buf, 0, IB_DRSMP_HOPPTR_F, is_resp ? drpath->cnt + 1 : 0x0); 128219820Sjeff mad_set_field(buf, 0, IB_DRSMP_STATUS_F, rpc->rstatus); 129219820Sjeff mad_set_field(buf, 0, IB_DRSMP_DIRECTION_F, is_resp ? 1 : 0); /* out */ 130219820Sjeff } else 131219820Sjeff mad_set_field(buf, 0, IB_MAD_STATUS_F, rpc->rstatus); 132219820Sjeff 133219820Sjeff /* words 3,4,5,6 */ 134219820Sjeff if (!rpc->trid) 135219820Sjeff rpc->trid = mad_trid(); 136219820Sjeff 137219820Sjeff mad_set_field64(buf, 0, IB_MAD_TRID_F, rpc->trid); 138219820Sjeff mad_set_field(buf, 0, IB_MAD_ATTRID_F, rpc->attr.id); 139219820Sjeff mad_set_field(buf, 0, IB_MAD_ATTRMOD_F, rpc->attr.mod); 140219820Sjeff 141219820Sjeff /* words 7,8 */ 142219820Sjeff mad_set_field(buf, 0, IB_MAD_MKEY_F, rpc->mkey >> 32); 143219820Sjeff mad_set_field(buf, 4, IB_MAD_MKEY_F, rpc->mkey & 0xffffffff); 144219820Sjeff 145219820Sjeff if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) { 146219820Sjeff /* word 9 */ 147219820Sjeff mad_set_field(buf, 0, IB_DRSMP_DRDLID_F, drpath->drdlid ? drpath->drdlid : 0xffff); 148219820Sjeff mad_set_field(buf, 0, IB_DRSMP_DRSLID_F, drpath->drslid ? drpath->drslid : 0xffff); 149219820Sjeff 150219820Sjeff /* bytes 128 - 256 - by default should be zero due to memset*/ 151219820Sjeff if (is_resp) 152219820Sjeff mad_set_array(buf, 0, IB_DRSMP_RPATH_F, drpath->p); 153219820Sjeff else 154219820Sjeff mad_set_array(buf, 0, IB_DRSMP_PATH_F, drpath->p); 155219820Sjeff } 156219820Sjeff 157219820Sjeff if (rpc->mgtclass == IB_SA_CLASS) 158219820Sjeff mad_set_field64(buf, 0, IB_SA_COMPMASK_F, rpc->mask); 159219820Sjeff 160219820Sjeff if (data) 161219820Sjeff memcpy((char *)buf + rpc->dataoffs, data, rpc->datasz); 162219820Sjeff 163219820Sjeff /* vendor mads range 2 */ 164219820Sjeff if (mad_is_vendor_range2(rpc->mgtclass)) 165219820Sjeff mad_set_field(buf, 0, IB_VEND2_OUI_F, rpc->oui); 166219820Sjeff 167219820Sjeff return (uint8_t *)buf + IB_MAD_SIZE; 168219820Sjeff} 169219820Sjeff 170219820Sjeffint 171219820Sjeffmad_build_pkt(void *umad, ib_rpc_t *rpc, ib_portid_t *dport, 172219820Sjeff ib_rmpp_hdr_t *rmpp, void *data) 173219820Sjeff{ 174219820Sjeff uint8_t *p, *mad; 175219820Sjeff int lid_routed = rpc->mgtclass != IB_SMI_DIRECT_CLASS; 176219820Sjeff int is_smi = (rpc->mgtclass == IB_SMI_CLASS || 177219820Sjeff rpc->mgtclass == IB_SMI_DIRECT_CLASS); 178219820Sjeff struct ib_mad_addr addr; 179219820Sjeff 180219820Sjeff if (!is_smi) 181219820Sjeff umad_set_addr(umad, dport->lid, dport->qp, dport->sl, dport->qkey); 182219820Sjeff else if (lid_routed) 183219820Sjeff umad_set_addr(umad, dport->lid, dport->qp, 0, 0); 184219820Sjeff else if ((dport->drpath.drslid != 0xffff) && (dport->lid > 0)) 185219820Sjeff umad_set_addr(umad, dport->lid, 0, 0, 0); 186219820Sjeff else 187219820Sjeff umad_set_addr(umad, 0xffff, 0, 0, 0); 188219820Sjeff 189219820Sjeff if (dport->grh_present && !is_smi) { 190219820Sjeff addr.grh_present = 1; 191219820Sjeff memcpy(addr.gid, dport->gid, 16); 192219820Sjeff addr.hop_limit = 0xff; 193219820Sjeff addr.traffic_class = 0; 194219820Sjeff addr.flow_label = 0; 195219820Sjeff umad_set_grh(umad, &addr); 196219820Sjeff } else 197219820Sjeff umad_set_grh(umad, 0); 198219820Sjeff umad_set_pkey(umad, is_smi ? 0 : dport->pkey_idx); 199219820Sjeff 200219820Sjeff mad = umad_get_mad(umad); 201219820Sjeff p = mad_encode(mad, rpc, lid_routed ? 0 : &dport->drpath, data); 202219820Sjeff 203219820Sjeff if (!is_smi && rmpp) { 204219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_VERS_F, 1); 205219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_TYPE_F, rmpp->type); 206219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_RESP_F, 0x3f); 207219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_FLAGS_F, rmpp->flags); 208219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_STATUS_F, rmpp->status); 209219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_D1_F, rmpp->d1.u); 210219820Sjeff mad_set_field(mad, 0, IB_SA_RMPP_D2_F, rmpp->d2.u); 211219820Sjeff } 212219820Sjeff 213219820Sjeff return p - mad; 214219820Sjeff} 215