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 <errno.h> 45219820Sjeff 46219820Sjeff#include <infiniband/umad.h> 47219820Sjeff#include "mad.h" 48219820Sjeff 49219820Sjeff#undef DEBUG 50219820Sjeff#define DEBUG if (ibdebug) IBWARN 51219820Sjeff 52219820Sjeff#define MAX_CLASS 256 53219820Sjeff#define MAX_AGENTS 256 54219820Sjeff 55219820Sjeffstatic int class_agent[MAX_CLASS]; 56219820Sjeffstatic int agent_class[MAX_AGENTS]; 57219820Sjeff 58219820Sjeffstatic int 59219820Sjeffregister_agent(int agent, int mclass) 60219820Sjeff{ 61219820Sjeff static int initialized; 62219820Sjeff 63219820Sjeff if (!initialized) { 64219820Sjeff initialized++; 65219820Sjeff memset(class_agent, 0xff, sizeof class_agent); 66219820Sjeff memset(agent_class, 0xff, sizeof agent_class); 67219820Sjeff } 68219820Sjeff 69219820Sjeff if (mclass < 0 || mclass >= MAX_CLASS || 70219820Sjeff agent < 0 || agent >= MAX_AGENTS) { 71219820Sjeff DEBUG("bad mgmt class %d or agent %d", mclass, agent); 72219820Sjeff return -1; 73219820Sjeff } 74219820Sjeff 75219820Sjeff class_agent[mclass] = agent; 76219820Sjeff agent_class[agent] = mclass; 77219820Sjeff 78219820Sjeff return 0; 79219820Sjeff} 80219820Sjeff 81219820Sjeffstatic int 82219820Sjeffmgmt_class_vers(int mgmt_class) 83219820Sjeff{ 84219820Sjeff if ((mgmt_class >= IB_VENDOR_RANGE1_START_CLASS && 85219820Sjeff mgmt_class <= IB_VENDOR_RANGE1_END_CLASS) || 86219820Sjeff (mgmt_class >= IB_VENDOR_RANGE2_START_CLASS && 87219820Sjeff mgmt_class <= IB_VENDOR_RANGE2_END_CLASS)) 88219820Sjeff return 1; 89219820Sjeff 90219820Sjeff switch(mgmt_class) { 91219820Sjeff case IB_SMI_CLASS: 92219820Sjeff case IB_SMI_DIRECT_CLASS: 93219820Sjeff return 1; 94219820Sjeff case IB_SA_CLASS: 95219820Sjeff return 2; 96219820Sjeff case IB_PERFORMANCE_CLASS: 97219820Sjeff return 1; 98219820Sjeff case IB_DEVICE_MGMT_CLASS: 99219820Sjeff return 1; 100219820Sjeff case IB_CC_CLASS: 101219820Sjeff return 2; 102219820Sjeff } 103219820Sjeff 104219820Sjeff return 0; 105219820Sjeff} 106219820Sjeff 107219820Sjeffint 108219820Sjeffmad_class_agent(int mgmt) 109219820Sjeff{ 110219820Sjeff if (mgmt < 1 || mgmt > MAX_CLASS) 111219820Sjeff return -1; 112219820Sjeff return class_agent[mgmt]; 113219820Sjeff} 114219820Sjeff 115219820Sjeffint 116219820Sjeffmad_agent_class(int agent) 117219820Sjeff{ 118219820Sjeff if (agent < 1 || agent > MAX_AGENTS) 119219820Sjeff return -1; 120219820Sjeff return agent_class[agent]; 121219820Sjeff} 122219820Sjeff 123219820Sjeffint 124219820Sjeffmad_register_port_client(int port_id, int mgmt, uint8_t rmpp_version) 125219820Sjeff{ 126219820Sjeff int vers, agent; 127219820Sjeff 128219820Sjeff if ((vers = mgmt_class_vers(mgmt)) <= 0) { 129219820Sjeff DEBUG("Unknown class %d mgmt_class", mgmt); 130219820Sjeff return -1; 131219820Sjeff } 132219820Sjeff if ((agent = umad_register(port_id, mgmt, 133219820Sjeff vers, rmpp_version, 0)) < 0) { 134219820Sjeff DEBUG("Can't register agent for class %d", mgmt); 135219820Sjeff return -1; 136219820Sjeff } 137219820Sjeff 138219820Sjeff if (mgmt < 0 || mgmt >= MAX_CLASS || agent >= MAX_AGENTS) { 139219820Sjeff DEBUG("bad mgmt class %d or agent %d", mgmt, agent); 140219820Sjeff return -1; 141219820Sjeff } 142219820Sjeff 143219820Sjeff return agent; 144219820Sjeff} 145219820Sjeff 146219820Sjeffint 147219820Sjeffmad_register_client(int mgmt, uint8_t rmpp_version) 148219820Sjeff{ 149219820Sjeff int agent; 150219820Sjeff 151219820Sjeff agent = mad_register_port_client(madrpc_portid(), mgmt, rmpp_version); 152219820Sjeff if (agent < 0) 153219820Sjeff return agent; 154219820Sjeff 155219820Sjeff return register_agent(agent, mgmt); 156219820Sjeff} 157219820Sjeff 158219820Sjeffint 159219820Sjeffmad_register_server(int mgmt, uint8_t rmpp_version, 160219820Sjeff long method_mask[], uint32_t class_oui) 161219820Sjeff{ 162219820Sjeff long class_method_mask[16/sizeof(long)]; 163219820Sjeff uint8_t oui[3]; 164219820Sjeff int agent, vers, mad_portid; 165219820Sjeff 166219820Sjeff if (method_mask) 167219820Sjeff memcpy(class_method_mask, method_mask, sizeof class_method_mask); 168219820Sjeff else 169219820Sjeff memset(class_method_mask, 0xff, sizeof(class_method_mask)); 170219820Sjeff 171219820Sjeff if ((mad_portid = madrpc_portid()) < 0) 172219820Sjeff return -1; 173219820Sjeff 174219820Sjeff if (class_agent[mgmt] >= 0) { 175219820Sjeff DEBUG("Class 0x%x already registered", mgmt); 176219820Sjeff return -1; 177219820Sjeff } 178219820Sjeff if ((vers = mgmt_class_vers(mgmt)) <= 0) { 179219820Sjeff DEBUG("Unknown class 0x%x mgmt_class", mgmt); 180219820Sjeff return -1; 181219820Sjeff } 182219820Sjeff if (mgmt >= IB_VENDOR_RANGE2_START_CLASS && 183219820Sjeff mgmt <= IB_VENDOR_RANGE2_END_CLASS) { 184219820Sjeff oui[0] = (class_oui >> 16) & 0xff; 185219820Sjeff oui[1] = (class_oui >> 8) & 0xff; 186219820Sjeff oui[2] = class_oui & 0xff; 187219820Sjeff if ((agent = umad_register_oui(mad_portid, mgmt, rmpp_version, 188219820Sjeff oui, class_method_mask)) < 0) { 189219820Sjeff DEBUG("Can't register agent for class %d", mgmt); 190219820Sjeff return -1; 191219820Sjeff } 192219820Sjeff } else if ((agent = umad_register(mad_portid, mgmt, vers, rmpp_version, 193219820Sjeff class_method_mask)) < 0) { 194219820Sjeff DEBUG("Can't register agent for class %d", mgmt); 195219820Sjeff return -1; 196219820Sjeff } 197219820Sjeff 198219820Sjeff if (register_agent(agent, mgmt) < 0) 199219820Sjeff return -1; 200219820Sjeff 201219820Sjeff return agent; 202219820Sjeff} 203