1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5219820Sjeff * Copyright (c) 2008 Xsigo Systems Inc. All rights reserved. 6219820Sjeff * 7219820Sjeff * This software is available to you under a choice of one of two 8219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 9219820Sjeff * General Public License (GPL) Version 2, available from the file 10219820Sjeff * COPYING in the main directory of this source tree, or the 11219820Sjeff * OpenIB.org BSD license below: 12219820Sjeff * 13219820Sjeff * Redistribution and use in source and binary forms, with or 14219820Sjeff * without modification, are permitted provided that the following 15219820Sjeff * conditions are met: 16219820Sjeff * 17219820Sjeff * - Redistributions of source code must retain the above 18219820Sjeff * copyright notice, this list of conditions and the following 19219820Sjeff * disclaimer. 20219820Sjeff * 21219820Sjeff * - Redistributions in binary form must reproduce the above 22219820Sjeff * copyright notice, this list of conditions and the following 23219820Sjeff * disclaimer in the documentation and/or other materials 24219820Sjeff * provided with the distribution. 25219820Sjeff * 26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 33219820Sjeff * SOFTWARE. 34219820Sjeff * 35219820Sjeff */ 36219820Sjeff 37219820Sjeff/* 38219820Sjeff * Abstract: 39219820Sjeff * Implementation of osm_sa_t. 40219820Sjeff * This object represents the Subnet Administration object. 41219820Sjeff * This object is part of the opensm family of objects. 42219820Sjeff */ 43219820Sjeff 44219820Sjeff#if HAVE_CONFIG_H 45219820Sjeff# include <config.h> 46219820Sjeff#endif /* HAVE_CONFIG_H */ 47219820Sjeff 48219820Sjeff#include <string.h> 49219820Sjeff#include <ctype.h> 50219820Sjeff#include <errno.h> 51219820Sjeff#include <stdlib.h> 52219820Sjeff#include <sys/types.h> 53219820Sjeff#include <sys/stat.h> 54219820Sjeff#include <complib/cl_qmap.h> 55219820Sjeff#include <complib/cl_passivelock.h> 56219820Sjeff#include <complib/cl_debug.h> 57219820Sjeff#include <iba/ib_types.h> 58219820Sjeff#include <opensm/osm_sa.h> 59219820Sjeff#include <opensm/osm_madw.h> 60219820Sjeff#include <opensm/osm_log.h> 61219820Sjeff#include <opensm/osm_subnet.h> 62219820Sjeff#include <opensm/osm_mad_pool.h> 63219820Sjeff#include <opensm/osm_msgdef.h> 64219820Sjeff#include <opensm/osm_opensm.h> 65219820Sjeff#include <opensm/osm_multicast.h> 66219820Sjeff#include <opensm/osm_inform.h> 67219820Sjeff#include <opensm/osm_service.h> 68219820Sjeff#include <opensm/osm_helper.h> 69219820Sjeff#include <vendor/osm_vendor_api.h> 70219820Sjeff 71219820Sjeff#define OSM_SA_INITIAL_TID_VALUE 0xabc 72219820Sjeff 73219820Sjeffextern void osm_cpi_rcv_process(IN void *context, IN void *data); 74219820Sjeffextern void osm_gir_rcv_process(IN void *context, IN void *data); 75219820Sjeffextern void osm_infr_rcv_process(IN void *context, IN void *data); 76219820Sjeffextern void osm_infir_rcv_process(IN void *context, IN void *data); 77219820Sjeffextern void osm_lftr_rcv_process(IN void *context, IN void *data); 78219820Sjeffextern void osm_lr_rcv_process(IN void *context, IN void *data); 79219820Sjeffextern void osm_mcmr_rcv_process(IN void *context, IN void *data); 80219820Sjeffextern void osm_mftr_rcv_process(IN void *context, IN void *data); 81219820Sjeffextern void osm_mpr_rcv_process(IN void *context, IN void *data); 82219820Sjeffextern void osm_nr_rcv_process(IN void *context, IN void *data); 83219820Sjeffextern void osm_pr_rcv_process(IN void *context, IN void *data); 84219820Sjeffextern void osm_pkey_rec_rcv_process(IN void *context, IN void *data); 85219820Sjeffextern void osm_pir_rcv_process(IN void *context, IN void *data); 86219820Sjeffextern void osm_sr_rcv_process(IN void *context, IN void *data); 87219820Sjeffextern void osm_slvl_rec_rcv_process(IN void *context, IN void *data); 88219820Sjeffextern void osm_smir_rcv_process(IN void *context, IN void *data); 89219820Sjeffextern void osm_sir_rcv_process(IN void *context, IN void *data); 90219820Sjeffextern void osm_vlarb_rec_rcv_process(IN void *context, IN void *data); 91219820Sjeffextern void osm_sr_rcv_lease_cb(IN void *context); 92219820Sjeff 93219820Sjeff/********************************************************************** 94219820Sjeff **********************************************************************/ 95219820Sjeffvoid osm_sa_construct(IN osm_sa_t * const p_sa) 96219820Sjeff{ 97219820Sjeff memset(p_sa, 0, sizeof(*p_sa)); 98219820Sjeff p_sa->state = OSM_SA_STATE_INIT; 99219820Sjeff p_sa->sa_trans_id = OSM_SA_INITIAL_TID_VALUE; 100219820Sjeff 101219820Sjeff cl_timer_construct(&p_sa->sr_timer); 102219820Sjeff} 103219820Sjeff 104219820Sjeff/********************************************************************** 105219820Sjeff **********************************************************************/ 106219820Sjeffvoid osm_sa_shutdown(IN osm_sa_t * const p_sa) 107219820Sjeff{ 108219820Sjeff ib_api_status_t status; 109219820Sjeff OSM_LOG_ENTER(p_sa->p_log); 110219820Sjeff 111219820Sjeff cl_timer_stop(&p_sa->sr_timer); 112219820Sjeff 113219820Sjeff /* unbind from the mad service */ 114219820Sjeff status = osm_sa_mad_ctrl_unbind(&p_sa->mad_ctrl); 115219820Sjeff 116219820Sjeff /* remove any registered dispatcher message */ 117219820Sjeff cl_disp_unregister(p_sa->nr_disp_h); 118219820Sjeff cl_disp_unregister(p_sa->pir_disp_h); 119219820Sjeff cl_disp_unregister(p_sa->gir_disp_h); 120219820Sjeff cl_disp_unregister(p_sa->lr_disp_h); 121219820Sjeff cl_disp_unregister(p_sa->pr_disp_h); 122219820Sjeff#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) 123219820Sjeff cl_disp_unregister(p_sa->mpr_disp_h); 124219820Sjeff#endif 125219820Sjeff cl_disp_unregister(p_sa->smir_disp_h); 126219820Sjeff cl_disp_unregister(p_sa->mcmr_disp_h); 127219820Sjeff cl_disp_unregister(p_sa->sr_disp_h); 128219820Sjeff cl_disp_unregister(p_sa->infr_disp_h); 129219820Sjeff cl_disp_unregister(p_sa->infir_disp_h); 130219820Sjeff cl_disp_unregister(p_sa->vlarb_disp_h); 131219820Sjeff cl_disp_unregister(p_sa->slvl_disp_h); 132219820Sjeff cl_disp_unregister(p_sa->pkey_disp_h); 133219820Sjeff cl_disp_unregister(p_sa->lft_disp_h); 134219820Sjeff cl_disp_unregister(p_sa->sir_disp_h); 135219820Sjeff cl_disp_unregister(p_sa->mft_disp_h); 136219820Sjeff osm_sa_mad_ctrl_destroy(&p_sa->mad_ctrl); 137219820Sjeff 138219820Sjeff OSM_LOG_EXIT(p_sa->p_log); 139219820Sjeff} 140219820Sjeff 141219820Sjeff/********************************************************************** 142219820Sjeff **********************************************************************/ 143219820Sjeffvoid osm_sa_destroy(IN osm_sa_t * const p_sa) 144219820Sjeff{ 145219820Sjeff OSM_LOG_ENTER(p_sa->p_log); 146219820Sjeff 147219820Sjeff p_sa->state = OSM_SA_STATE_INIT; 148219820Sjeff 149219820Sjeff cl_timer_destroy(&p_sa->sr_timer); 150219820Sjeff 151219820Sjeff OSM_LOG_EXIT(p_sa->p_log); 152219820Sjeff} 153219820Sjeff 154219820Sjeff/********************************************************************** 155219820Sjeff **********************************************************************/ 156219820Sjeffib_api_status_t 157219820Sjeffosm_sa_init(IN osm_sm_t * const p_sm, 158219820Sjeff IN osm_sa_t * const p_sa, 159219820Sjeff IN osm_subn_t * const p_subn, 160219820Sjeff IN osm_vendor_t * const p_vendor, 161219820Sjeff IN osm_mad_pool_t * const p_mad_pool, 162219820Sjeff IN osm_log_t * const p_log, 163219820Sjeff IN osm_stats_t * const p_stats, 164219820Sjeff IN cl_dispatcher_t * const p_disp, IN cl_plock_t * const p_lock) 165219820Sjeff{ 166219820Sjeff ib_api_status_t status = IB_SUCCESS; 167219820Sjeff 168219820Sjeff OSM_LOG_ENTER(p_log); 169219820Sjeff 170219820Sjeff p_sa->sm = p_sm; 171219820Sjeff p_sa->p_subn = p_subn; 172219820Sjeff p_sa->p_vendor = p_vendor; 173219820Sjeff p_sa->p_mad_pool = p_mad_pool; 174219820Sjeff p_sa->p_log = p_log; 175219820Sjeff p_sa->p_disp = p_disp; 176219820Sjeff p_sa->p_lock = p_lock; 177219820Sjeff 178219820Sjeff p_sa->state = OSM_SA_STATE_READY; 179219820Sjeff 180219820Sjeff status = osm_sa_mad_ctrl_init(&p_sa->mad_ctrl, 181219820Sjeff p_sa, 182219820Sjeff p_sa->p_mad_pool, 183219820Sjeff p_sa->p_vendor, 184219820Sjeff p_subn, p_log, p_stats, p_disp); 185219820Sjeff if (status != IB_SUCCESS) 186219820Sjeff goto Exit; 187219820Sjeff 188219820Sjeff status = cl_timer_init(&p_sa->sr_timer, osm_sr_rcv_lease_cb, p_sa); 189219820Sjeff if (status != IB_SUCCESS) 190219820Sjeff goto Exit; 191219820Sjeff 192219820Sjeff p_sa->cpi_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_CLASS_PORT_INFO, 193219820Sjeff osm_cpi_rcv_process, p_sa); 194219820Sjeff if (p_sa->cpi_disp_h == CL_DISP_INVALID_HANDLE) 195219820Sjeff goto Exit; 196219820Sjeff 197219820Sjeff p_sa->nr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_NODE_RECORD, 198219820Sjeff osm_nr_rcv_process, p_sa); 199219820Sjeff if (p_sa->nr_disp_h == CL_DISP_INVALID_HANDLE) 200219820Sjeff goto Exit; 201219820Sjeff 202219820Sjeff p_sa->pir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PORTINFO_RECORD, 203219820Sjeff osm_pir_rcv_process, p_sa); 204219820Sjeff if (p_sa->pir_disp_h == CL_DISP_INVALID_HANDLE) 205219820Sjeff goto Exit; 206219820Sjeff 207219820Sjeff p_sa->gir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_GUIDINFO_RECORD, 208219820Sjeff osm_gir_rcv_process, p_sa); 209219820Sjeff if (p_sa->gir_disp_h == CL_DISP_INVALID_HANDLE) 210219820Sjeff goto Exit; 211219820Sjeff 212219820Sjeff p_sa->lr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LINK_RECORD, 213219820Sjeff osm_lr_rcv_process, p_sa); 214219820Sjeff if (p_sa->lr_disp_h == CL_DISP_INVALID_HANDLE) 215219820Sjeff goto Exit; 216219820Sjeff 217219820Sjeff p_sa->pr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_PATH_RECORD, 218219820Sjeff osm_pr_rcv_process, p_sa); 219219820Sjeff if (p_sa->pr_disp_h == CL_DISP_INVALID_HANDLE) 220219820Sjeff goto Exit; 221219820Sjeff 222219820Sjeff#if defined (VENDOR_RMPP_SUPPORT) && defined (DUAL_SIDED_RMPP) 223219820Sjeff p_sa->mpr_disp_h = 224219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_MULTIPATH_RECORD, 225219820Sjeff osm_mpr_rcv_process, p_sa); 226219820Sjeff if (p_sa->mpr_disp_h == CL_DISP_INVALID_HANDLE) 227219820Sjeff goto Exit; 228219820Sjeff#endif 229219820Sjeff 230219820Sjeff p_sa->smir_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SMINFO_RECORD, 231219820Sjeff osm_smir_rcv_process, p_sa); 232219820Sjeff if (p_sa->smir_disp_h == CL_DISP_INVALID_HANDLE) 233219820Sjeff goto Exit; 234219820Sjeff 235219820Sjeff p_sa->mcmr_disp_h = 236219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_MCMEMBER_RECORD, 237219820Sjeff osm_mcmr_rcv_process, p_sa); 238219820Sjeff if (p_sa->mcmr_disp_h == CL_DISP_INVALID_HANDLE) 239219820Sjeff goto Exit; 240219820Sjeff 241219820Sjeff p_sa->sr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_SERVICE_RECORD, 242219820Sjeff osm_sr_rcv_process, p_sa); 243219820Sjeff if (p_sa->sr_disp_h == CL_DISP_INVALID_HANDLE) 244219820Sjeff goto Exit; 245219820Sjeff 246219820Sjeff p_sa->infr_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO, 247219820Sjeff osm_infr_rcv_process, p_sa); 248219820Sjeff if (p_sa->infr_disp_h == CL_DISP_INVALID_HANDLE) 249219820Sjeff goto Exit; 250219820Sjeff 251219820Sjeff p_sa->infir_disp_h = 252219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_INFORM_INFO_RECORD, 253219820Sjeff osm_infir_rcv_process, p_sa); 254219820Sjeff if (p_sa->infir_disp_h == CL_DISP_INVALID_HANDLE) 255219820Sjeff goto Exit; 256219820Sjeff 257219820Sjeff p_sa->vlarb_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_VL_ARB_RECORD, 258219820Sjeff osm_vlarb_rec_rcv_process, p_sa); 259219820Sjeff if (p_sa->vlarb_disp_h == CL_DISP_INVALID_HANDLE) 260219820Sjeff goto Exit; 261219820Sjeff 262219820Sjeff p_sa->slvl_disp_h = 263219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_SLVL_TBL_RECORD, 264219820Sjeff osm_slvl_rec_rcv_process, p_sa); 265219820Sjeff if (p_sa->slvl_disp_h == CL_DISP_INVALID_HANDLE) 266219820Sjeff goto Exit; 267219820Sjeff 268219820Sjeff p_sa->pkey_disp_h = 269219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_PKEY_TBL_RECORD, 270219820Sjeff osm_pkey_rec_rcv_process, p_sa); 271219820Sjeff if (p_sa->pkey_disp_h == CL_DISP_INVALID_HANDLE) 272219820Sjeff goto Exit; 273219820Sjeff 274219820Sjeff p_sa->lft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_LFT_RECORD, 275219820Sjeff osm_lftr_rcv_process, p_sa); 276219820Sjeff if (p_sa->lft_disp_h == CL_DISP_INVALID_HANDLE) 277219820Sjeff goto Exit; 278219820Sjeff 279219820Sjeff p_sa->sir_disp_h = 280219820Sjeff cl_disp_register(p_disp, OSM_MSG_MAD_SWITCH_INFO_RECORD, 281219820Sjeff osm_sir_rcv_process, p_sa); 282219820Sjeff if (p_sa->sir_disp_h == CL_DISP_INVALID_HANDLE) 283219820Sjeff goto Exit; 284219820Sjeff 285219820Sjeff p_sa->mft_disp_h = cl_disp_register(p_disp, OSM_MSG_MAD_MFT_RECORD, 286219820Sjeff osm_mftr_rcv_process, p_sa); 287219820Sjeff if (p_sa->mft_disp_h == CL_DISP_INVALID_HANDLE) 288219820Sjeff goto Exit; 289219820Sjeff 290219820SjeffExit: 291219820Sjeff OSM_LOG_EXIT(p_log); 292219820Sjeff return (status); 293219820Sjeff} 294219820Sjeff 295219820Sjeff/********************************************************************** 296219820Sjeff **********************************************************************/ 297219820Sjeffib_api_status_t 298219820Sjeffosm_sa_bind(IN osm_sa_t * const p_sa, IN const ib_net64_t port_guid) 299219820Sjeff{ 300219820Sjeff ib_api_status_t status; 301219820Sjeff 302219820Sjeff OSM_LOG_ENTER(p_sa->p_log); 303219820Sjeff 304219820Sjeff status = osm_sa_mad_ctrl_bind(&p_sa->mad_ctrl, port_guid); 305219820Sjeff 306219820Sjeff if (status != IB_SUCCESS) { 307219820Sjeff OSM_LOG(p_sa->p_log, OSM_LOG_ERROR, "ERR 4C03: " 308219820Sjeff "SA MAD Controller bind failed (%s)\n", 309219820Sjeff ib_get_err_str(status)); 310219820Sjeff goto Exit; 311219820Sjeff } 312219820Sjeff 313219820SjeffExit: 314219820Sjeff OSM_LOG_EXIT(p_sa->p_log); 315219820Sjeff return (status); 316219820Sjeff} 317219820Sjeff 318219820Sjeffib_api_status_t osm_sa_send(osm_sa_t *sa, 319219820Sjeff IN osm_madw_t * const p_madw, 320219820Sjeff IN boolean_t const resp_expected) 321219820Sjeff{ 322219820Sjeff ib_api_status_t status; 323219820Sjeff 324219820Sjeff cl_atomic_inc(&sa->p_subn->p_osm->stats.sa_mads_sent); 325219820Sjeff status = osm_vendor_send(p_madw->h_bind, p_madw, resp_expected); 326219820Sjeff if (status != IB_SUCCESS) { 327219820Sjeff cl_atomic_dec(&sa->p_subn->p_osm->stats.sa_mads_sent); 328219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C04: " 329219820Sjeff "osm_vendor_send failed, status = %s\n", 330219820Sjeff ib_get_err_str(status)); 331219820Sjeff } 332219820Sjeff return status; 333219820Sjeff} 334219820Sjeff 335219820Sjeffvoid 336219820Sjeffosm_sa_send_error(IN osm_sa_t * sa, 337219820Sjeff IN const osm_madw_t * const p_madw, 338219820Sjeff IN const ib_net16_t sa_status) 339219820Sjeff{ 340219820Sjeff osm_madw_t *p_resp_madw; 341219820Sjeff ib_sa_mad_t *p_resp_sa_mad; 342219820Sjeff ib_sa_mad_t *p_sa_mad; 343219820Sjeff 344219820Sjeff OSM_LOG_ENTER(sa->p_log); 345219820Sjeff 346219820Sjeff /* avoid races - if we are exiting - exit */ 347219820Sjeff if (osm_exit_flag) { 348219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 349219820Sjeff "Ignoring requested send after exit\n"); 350219820Sjeff goto Exit; 351219820Sjeff } 352219820Sjeff 353219820Sjeff p_resp_madw = osm_mad_pool_get(sa->p_mad_pool, 354219820Sjeff p_madw->h_bind, MAD_BLOCK_SIZE, 355219820Sjeff &p_madw->mad_addr); 356219820Sjeff 357219820Sjeff if (p_resp_madw == NULL) { 358219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C07: " 359219820Sjeff "Unable to acquire response MAD\n"); 360219820Sjeff goto Exit; 361219820Sjeff } 362219820Sjeff 363219820Sjeff p_resp_sa_mad = osm_madw_get_sa_mad_ptr(p_resp_madw); 364219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 365219820Sjeff 366219820Sjeff /* Copy the MAD header back into the response mad */ 367219820Sjeff *p_resp_sa_mad = *p_sa_mad; 368219820Sjeff p_resp_sa_mad->status = sa_status; 369219820Sjeff 370219820Sjeff if (p_resp_sa_mad->method == IB_MAD_METHOD_SET) 371219820Sjeff p_resp_sa_mad->method = IB_MAD_METHOD_GET; 372219820Sjeff else if (p_resp_sa_mad->method == IB_MAD_METHOD_GETTABLE) 373219820Sjeff p_resp_sa_mad->attr_offset = 0; 374219820Sjeff 375219820Sjeff p_resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; 376219820Sjeff 377219820Sjeff /* 378219820Sjeff * C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) 379219820Sjeff */ 380219820Sjeff p_resp_sa_mad->sm_key = 0; 381219820Sjeff 382219820Sjeff /* 383219820Sjeff * o15-0.2.7 - The PathRecord Attribute ID shall be used in 384219820Sjeff * the response (to a SubnAdmGetMulti(MultiPathRecord) 385219820Sjeff */ 386219820Sjeff if (p_resp_sa_mad->attr_id == IB_MAD_ATTR_MULTIPATH_RECORD) 387219820Sjeff p_resp_sa_mad->attr_id = IB_MAD_ATTR_PATH_RECORD; 388219820Sjeff 389219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_FRAMES)) 390219820Sjeff osm_dump_sa_mad(sa->p_log, p_resp_sa_mad, OSM_LOG_FRAMES); 391219820Sjeff 392219820Sjeff osm_sa_send(sa, p_resp_madw, FALSE); 393219820Sjeff 394219820SjeffExit: 395219820Sjeff OSM_LOG_EXIT(sa->p_log); 396219820Sjeff} 397219820Sjeff 398219820Sjeffvoid osm_sa_respond(osm_sa_t *sa, osm_madw_t *madw, size_t attr_size, 399219820Sjeff cl_qlist_t *list) 400219820Sjeff{ 401219820Sjeff struct item_data { 402219820Sjeff cl_list_item_t list; 403219820Sjeff char data[0]; 404219820Sjeff }; 405219820Sjeff cl_list_item_t *item; 406219820Sjeff osm_madw_t *resp_madw; 407219820Sjeff ib_sa_mad_t *sa_mad, *resp_sa_mad; 408219820Sjeff unsigned num_rec, i; 409219820Sjeff#ifndef VENDOR_RMPP_SUPPORT 410219820Sjeff unsigned trim_num_rec; 411219820Sjeff#endif 412219820Sjeff void *p; 413219820Sjeff 414219820Sjeff sa_mad = osm_madw_get_sa_mad_ptr(madw); 415219820Sjeff num_rec = cl_qlist_count(list); 416219820Sjeff 417219820Sjeff /* 418219820Sjeff * C15-0.1.30: 419219820Sjeff * If we do a SubnAdmGet and got more than one record it is an error! 420219820Sjeff */ 421219820Sjeff if (sa_mad->method == IB_MAD_METHOD_GET && num_rec > 1) { 422219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C05: " 423219820Sjeff "Got more than one record for SubnAdmGet (%u)\n", 424219820Sjeff num_rec); 425219820Sjeff osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_TOO_MANY_RECORDS); 426219820Sjeff goto Exit; 427219820Sjeff } 428219820Sjeff 429219820Sjeff#ifndef VENDOR_RMPP_SUPPORT 430219820Sjeff trim_num_rec = (MAD_BLOCK_SIZE - IB_SA_MAD_HDR_SIZE) / attr_size; 431219820Sjeff if (trim_num_rec < num_rec) { 432219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 433219820Sjeff "Number of records:%u trimmed to:%u to fit in one MAD\n", 434219820Sjeff num_rec, trim_num_rec); 435219820Sjeff num_rec = trim_num_rec; 436219820Sjeff } 437219820Sjeff#endif 438219820Sjeff 439219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Returning %u records\n", num_rec); 440219820Sjeff 441219820Sjeff if (sa_mad->method == IB_MAD_METHOD_GET && num_rec == 0) { 442219820Sjeff osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RECORDS); 443219820Sjeff goto Exit; 444219820Sjeff } 445219820Sjeff 446219820Sjeff /* 447219820Sjeff * Get a MAD to reply. Address of Mad is in the received mad_wrapper 448219820Sjeff */ 449219820Sjeff resp_madw = osm_mad_pool_get(sa->p_mad_pool, madw->h_bind, 450219820Sjeff num_rec * attr_size + IB_SA_MAD_HDR_SIZE, 451219820Sjeff &madw->mad_addr); 452219820Sjeff if (!resp_madw) { 453219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4C06: " 454219820Sjeff "osm_mad_pool_get failed\n"); 455219820Sjeff osm_sa_send_error(sa, madw, IB_SA_MAD_STATUS_NO_RESOURCES); 456219820Sjeff goto Exit; 457219820Sjeff } 458219820Sjeff 459219820Sjeff resp_sa_mad = osm_madw_get_sa_mad_ptr(resp_madw); 460219820Sjeff 461219820Sjeff /* 462219820Sjeff Copy the MAD header back into the response mad. 463219820Sjeff Set the 'R' bit and the payload length, 464219820Sjeff Then copy all records from the list into the response payload. 465219820Sjeff */ 466219820Sjeff 467219820Sjeff memcpy(resp_sa_mad, sa_mad, IB_SA_MAD_HDR_SIZE); 468219820Sjeff if (resp_sa_mad->method == IB_MAD_METHOD_SET) 469219820Sjeff resp_sa_mad->method = IB_MAD_METHOD_GET; 470219820Sjeff resp_sa_mad->method |= IB_MAD_METHOD_RESP_MASK; 471219820Sjeff /* C15-0.1.5 - always return SM_Key = 0 (table 185 p 884) */ 472219820Sjeff resp_sa_mad->sm_key = 0; 473219820Sjeff 474219820Sjeff /* Fill in the offset (paylen will be done by the rmpp SAR) */ 475219820Sjeff resp_sa_mad->attr_offset = num_rec ? ib_get_attr_offset(attr_size) : 0; 476219820Sjeff 477219820Sjeff p = ib_sa_mad_get_payload_ptr(resp_sa_mad); 478219820Sjeff 479219820Sjeff#ifndef VENDOR_RMPP_SUPPORT 480219820Sjeff /* we support only one packet RMPP - so we will set the first and 481219820Sjeff last flags for gettable */ 482219820Sjeff if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) { 483219820Sjeff resp_sa_mad->rmpp_type = IB_RMPP_TYPE_DATA; 484219820Sjeff resp_sa_mad->rmpp_flags = 485219820Sjeff IB_RMPP_FLAG_FIRST | IB_RMPP_FLAG_LAST | 486219820Sjeff IB_RMPP_FLAG_ACTIVE; 487219820Sjeff } 488219820Sjeff#else 489219820Sjeff /* forcefully define the packet as RMPP one */ 490219820Sjeff if (resp_sa_mad->method == IB_MAD_METHOD_GETTABLE_RESP) 491219820Sjeff resp_sa_mad->rmpp_flags = IB_RMPP_FLAG_ACTIVE; 492219820Sjeff#endif 493219820Sjeff 494219820Sjeff for (i = 0; i < num_rec; i++) { 495219820Sjeff item = cl_qlist_remove_head(list); 496219820Sjeff memcpy(p, ((struct item_data *)item)->data, attr_size); 497219820Sjeff p += attr_size; 498219820Sjeff free(item); 499219820Sjeff } 500219820Sjeff 501219820Sjeff osm_sa_send(sa, resp_madw, FALSE); 502219820Sjeff 503219820Sjeff osm_dump_sa_mad(sa->p_log, resp_sa_mad, OSM_LOG_FRAMES); 504219820SjeffExit: 505219820Sjeff /* need to set the mem free ... */ 506219820Sjeff item = cl_qlist_remove_head(list); 507219820Sjeff while (item != cl_qlist_end(list)) { 508219820Sjeff free(item); 509219820Sjeff item = cl_qlist_remove_head(list); 510219820Sjeff } 511219820Sjeff} 512219820Sjeff 513219820Sjeff/********************************************************************** 514219820Sjeff **********************************************************************/ 515219820Sjeff/* 516219820Sjeff * SA DB Dumper 517219820Sjeff * 518219820Sjeff */ 519219820Sjeff 520219820Sjeffstruct opensm_dump_context { 521219820Sjeff osm_opensm_t *p_osm; 522219820Sjeff FILE *file; 523219820Sjeff}; 524219820Sjeff 525219820Sjeffstatic int 526219820Sjeffopensm_dump_to_file(osm_opensm_t * p_osm, const char *file_name, 527219820Sjeff void (*dump_func) (osm_opensm_t * p_osm, FILE * file)) 528219820Sjeff{ 529219820Sjeff char path[1024]; 530219820Sjeff FILE *file; 531219820Sjeff 532219820Sjeff snprintf(path, sizeof(path), "%s/%s", 533219820Sjeff p_osm->subn.opt.dump_files_dir, file_name); 534219820Sjeff 535219820Sjeff file = fopen(path, "w"); 536219820Sjeff if (!file) { 537219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, "ERR 4C01: " 538219820Sjeff "cannot open file \'%s\': %s\n", 539219820Sjeff file_name, strerror(errno)); 540219820Sjeff return -1; 541219820Sjeff } 542219820Sjeff 543219820Sjeff chmod(path, S_IRUSR | S_IWUSR); 544219820Sjeff 545219820Sjeff dump_func(p_osm, file); 546219820Sjeff 547219820Sjeff fclose(file); 548219820Sjeff return 0; 549219820Sjeff} 550219820Sjeff 551219820Sjeffstatic void mcast_mgr_dump_one_port(cl_map_item_t * p_map_item, void *cxt) 552219820Sjeff{ 553219820Sjeff FILE *file = ((struct opensm_dump_context *)cxt)->file; 554219820Sjeff osm_mcm_port_t *p_mcm_port = (osm_mcm_port_t *) p_map_item; 555219820Sjeff 556219820Sjeff fprintf(file, "mcm_port: " 557219820Sjeff "port_gid=0x%016" PRIx64 ":0x%016" PRIx64 " " 558219820Sjeff "scope_state=0x%02x proxy_join=0x%x" "\n\n", 559219820Sjeff cl_ntoh64(p_mcm_port->port_gid.unicast.prefix), 560219820Sjeff cl_ntoh64(p_mcm_port->port_gid.unicast.interface_id), 561219820Sjeff p_mcm_port->scope_state, p_mcm_port->proxy_join); 562219820Sjeff} 563219820Sjeff 564219820Sjeffstatic void sa_dump_one_mgrp(osm_mgrp_t *p_mgrp, void *cxt) 565219820Sjeff{ 566219820Sjeff struct opensm_dump_context dump_context; 567219820Sjeff osm_opensm_t *p_osm = ((struct opensm_dump_context *)cxt)->p_osm; 568219820Sjeff FILE *file = ((struct opensm_dump_context *)cxt)->file; 569219820Sjeff 570219820Sjeff fprintf(file, "MC Group 0x%04x %s:" 571219820Sjeff " mgid=0x%016" PRIx64 ":0x%016" PRIx64 572219820Sjeff " port_gid=0x%016" PRIx64 ":0x%016" PRIx64 573219820Sjeff " qkey=0x%08x mlid=0x%04x mtu=0x%02x tclass=0x%02x" 574219820Sjeff " pkey=0x%04x rate=0x%02x pkt_life=0x%02x sl_flow_hop=0x%08x" 575219820Sjeff " scope_state=0x%02x proxy_join=0x%x" "\n\n", 576219820Sjeff cl_ntoh16(p_mgrp->mlid), 577219820Sjeff p_mgrp->well_known ? " (well known)" : "", 578219820Sjeff cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.prefix), 579219820Sjeff cl_ntoh64(p_mgrp->mcmember_rec.mgid.unicast.interface_id), 580219820Sjeff cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.prefix), 581219820Sjeff cl_ntoh64(p_mgrp->mcmember_rec.port_gid.unicast.interface_id), 582219820Sjeff cl_ntoh32(p_mgrp->mcmember_rec.qkey), 583219820Sjeff cl_ntoh16(p_mgrp->mcmember_rec.mlid), 584219820Sjeff p_mgrp->mcmember_rec.mtu, 585219820Sjeff p_mgrp->mcmember_rec.tclass, 586219820Sjeff cl_ntoh16(p_mgrp->mcmember_rec.pkey), 587219820Sjeff p_mgrp->mcmember_rec.rate, 588219820Sjeff p_mgrp->mcmember_rec.pkt_life, 589219820Sjeff cl_ntoh32(p_mgrp->mcmember_rec.sl_flow_hop), 590219820Sjeff p_mgrp->mcmember_rec.scope_state, 591219820Sjeff p_mgrp->mcmember_rec.proxy_join); 592219820Sjeff 593219820Sjeff dump_context.p_osm = p_osm; 594219820Sjeff dump_context.file = file; 595219820Sjeff 596219820Sjeff cl_qmap_apply_func(&p_mgrp->mcm_port_tbl, 597219820Sjeff mcast_mgr_dump_one_port, &dump_context); 598219820Sjeff} 599219820Sjeff 600219820Sjeffstatic void sa_dump_one_inform(cl_list_item_t * p_list_item, void *cxt) 601219820Sjeff{ 602219820Sjeff FILE *file = ((struct opensm_dump_context *)cxt)->file; 603219820Sjeff osm_infr_t *p_infr = (osm_infr_t *) p_list_item; 604219820Sjeff ib_inform_info_record_t *p_iir = &p_infr->inform_record; 605219820Sjeff 606219820Sjeff fprintf(file, "InformInfo Record:" 607219820Sjeff " subscriber_gid=0x%016" PRIx64 ":0x%016" PRIx64 608219820Sjeff " subscriber_enum=0x%x" 609219820Sjeff " InformInfo:" 610219820Sjeff " gid=0x%016" PRIx64 ":0x%016" PRIx64 611219820Sjeff " lid_range_begin=0x%x" 612219820Sjeff " lid_range_end=0x%x" 613219820Sjeff " is_generic=0x%x" 614219820Sjeff " subscribe=0x%x" 615219820Sjeff " trap_type=0x%x" 616219820Sjeff " trap_num=0x%x" 617219820Sjeff " qpn_resp_time_val=0x%x" 618219820Sjeff " node_type=0x%06x" 619219820Sjeff " rep_addr: lid=0x%04x path_bits=0x%02x static_rate=0x%02x" 620219820Sjeff " remote_qp=0x%08x remote_qkey=0x%08x pkey_ix=0x%04x sl=0x%02x" 621219820Sjeff "\n\n", 622219820Sjeff cl_ntoh64(p_iir->subscriber_gid.unicast.prefix), 623219820Sjeff cl_ntoh64(p_iir->subscriber_gid.unicast.interface_id), 624219820Sjeff cl_ntoh16(p_iir->subscriber_enum), 625219820Sjeff cl_ntoh64(p_iir->inform_info.gid.unicast.prefix), 626219820Sjeff cl_ntoh64(p_iir->inform_info.gid.unicast.interface_id), 627219820Sjeff cl_ntoh16(p_iir->inform_info.lid_range_begin), 628219820Sjeff cl_ntoh16(p_iir->inform_info.lid_range_end), 629219820Sjeff p_iir->inform_info.is_generic, 630219820Sjeff p_iir->inform_info.subscribe, 631219820Sjeff cl_ntoh16(p_iir->inform_info.trap_type), 632219820Sjeff cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num), 633219820Sjeff cl_ntoh32(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val), 634219820Sjeff cl_ntoh32(ib_inform_info_get_prod_type(&p_iir->inform_info)), 635219820Sjeff cl_ntoh16(p_infr->report_addr.dest_lid), 636219820Sjeff p_infr->report_addr.path_bits, 637219820Sjeff p_infr->report_addr.static_rate, 638219820Sjeff cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qp), 639219820Sjeff cl_ntoh32(p_infr->report_addr.addr_type.gsi.remote_qkey), 640219820Sjeff p_infr->report_addr.addr_type.gsi.pkey_ix, 641219820Sjeff p_infr->report_addr.addr_type.gsi.service_level); 642219820Sjeff} 643219820Sjeff 644219820Sjeffstatic void sa_dump_one_service(cl_list_item_t * p_list_item, void *cxt) 645219820Sjeff{ 646219820Sjeff FILE *file = ((struct opensm_dump_context *)cxt)->file; 647219820Sjeff osm_svcr_t *p_svcr = (osm_svcr_t *) p_list_item; 648219820Sjeff ib_service_record_t *p_sr = &p_svcr->service_record; 649219820Sjeff 650219820Sjeff fprintf(file, "Service Record: id=0x%016" PRIx64 651219820Sjeff " gid=0x%016" PRIx64 ":0x%016" PRIx64 652219820Sjeff " pkey=0x%x" 653219820Sjeff " lease=0x%x" 654219820Sjeff " key=0x%02x%02x%02x%02x%02x%02x%02x%02x" 655219820Sjeff ":0x%02x%02x%02x%02x%02x%02x%02x%02x" 656219820Sjeff " name=\'%s\'" 657219820Sjeff " data8=0x%02x%02x%02x%02x%02x%02x%02x%02x" 658219820Sjeff ":0x%02x%02x%02x%02x%02x%02x%02x%02x" 659219820Sjeff " data16=0x%04x%04x%04x%04x:0x%04x%04x%04x%04x" 660219820Sjeff " data32=0x%08x%08x:0x%08x%08x" 661219820Sjeff " data64=0x%016" PRIx64 ":0x%016" PRIx64 662219820Sjeff " modified_time=0x%x lease_period=0x%x\n\n", 663219820Sjeff cl_ntoh64(p_sr->service_id), 664219820Sjeff cl_ntoh64(p_sr->service_gid.unicast.prefix), 665219820Sjeff cl_ntoh64(p_sr->service_gid.unicast.interface_id), 666219820Sjeff cl_ntoh16(p_sr->service_pkey), 667219820Sjeff cl_ntoh32(p_sr->service_lease), 668219820Sjeff p_sr->service_key[0], p_sr->service_key[1], 669219820Sjeff p_sr->service_key[2], p_sr->service_key[3], 670219820Sjeff p_sr->service_key[4], p_sr->service_key[5], 671219820Sjeff p_sr->service_key[6], p_sr->service_key[7], 672219820Sjeff p_sr->service_key[8], p_sr->service_key[9], 673219820Sjeff p_sr->service_key[10], p_sr->service_key[11], 674219820Sjeff p_sr->service_key[12], p_sr->service_key[13], 675219820Sjeff p_sr->service_key[14], p_sr->service_key[15], 676219820Sjeff p_sr->service_name, 677219820Sjeff p_sr->service_data8[0], p_sr->service_data8[1], 678219820Sjeff p_sr->service_data8[2], p_sr->service_data8[3], 679219820Sjeff p_sr->service_data8[4], p_sr->service_data8[5], 680219820Sjeff p_sr->service_data8[6], p_sr->service_data8[7], 681219820Sjeff p_sr->service_data8[8], p_sr->service_data8[9], 682219820Sjeff p_sr->service_data8[10], p_sr->service_data8[11], 683219820Sjeff p_sr->service_data8[12], p_sr->service_data8[13], 684219820Sjeff p_sr->service_data8[14], p_sr->service_data8[15], 685219820Sjeff cl_ntoh16(p_sr->service_data16[0]), 686219820Sjeff cl_ntoh16(p_sr->service_data16[1]), 687219820Sjeff cl_ntoh16(p_sr->service_data16[2]), 688219820Sjeff cl_ntoh16(p_sr->service_data16[3]), 689219820Sjeff cl_ntoh16(p_sr->service_data16[4]), 690219820Sjeff cl_ntoh16(p_sr->service_data16[5]), 691219820Sjeff cl_ntoh16(p_sr->service_data16[6]), 692219820Sjeff cl_ntoh16(p_sr->service_data16[7]), 693219820Sjeff cl_ntoh32(p_sr->service_data32[0]), 694219820Sjeff cl_ntoh32(p_sr->service_data32[1]), 695219820Sjeff cl_ntoh32(p_sr->service_data32[2]), 696219820Sjeff cl_ntoh32(p_sr->service_data32[3]), 697219820Sjeff cl_ntoh64(p_sr->service_data64[0]), 698219820Sjeff cl_ntoh64(p_sr->service_data64[1]), 699219820Sjeff p_svcr->modified_time, p_svcr->lease_period); 700219820Sjeff} 701219820Sjeff 702219820Sjeffstatic void sa_dump_all_sa(osm_opensm_t * p_osm, FILE * file) 703219820Sjeff{ 704219820Sjeff struct opensm_dump_context dump_context; 705219820Sjeff osm_mgrp_t *p_mgrp; 706219820Sjeff int i; 707219820Sjeff 708219820Sjeff dump_context.p_osm = p_osm; 709219820Sjeff dump_context.file = file; 710219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump multicast:\n"); 711219820Sjeff cl_plock_acquire(&p_osm->lock); 712219820Sjeff for (i = 0; i <= p_osm->subn.max_mcast_lid_ho - IB_LID_MCAST_START_HO; 713219820Sjeff i++) { 714219820Sjeff p_mgrp = p_osm->subn.mgroups[i]; 715219820Sjeff if (p_mgrp) 716219820Sjeff sa_dump_one_mgrp(p_mgrp, &dump_context); 717219820Sjeff } 718219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump inform:\n"); 719219820Sjeff cl_qlist_apply_func(&p_osm->subn.sa_infr_list, 720219820Sjeff sa_dump_one_inform, &dump_context); 721219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "Dump services:\n"); 722219820Sjeff cl_qlist_apply_func(&p_osm->subn.sa_sr_list, 723219820Sjeff sa_dump_one_service, &dump_context); 724219820Sjeff cl_plock_release(&p_osm->lock); 725219820Sjeff} 726219820Sjeff 727219820Sjeffint osm_sa_db_file_dump(osm_opensm_t * p_osm) 728219820Sjeff{ 729219820Sjeff return opensm_dump_to_file(p_osm, "opensm-sa.dump", sa_dump_all_sa); 730219820Sjeff} 731219820Sjeff 732219820Sjeff/* 733219820Sjeff * SA DB Loader 734219820Sjeff */ 735219820Sjeffstatic osm_mgrp_t *load_mcgroup(osm_opensm_t * p_osm, ib_net16_t mlid, 736219820Sjeff ib_member_rec_t * p_mcm_rec, 737219820Sjeff unsigned well_known) 738219820Sjeff{ 739219820Sjeff ib_net64_t comp_mask; 740219820Sjeff osm_mgrp_t *p_mgrp; 741219820Sjeff 742219820Sjeff cl_plock_excl_acquire(&p_osm->lock); 743219820Sjeff 744219820Sjeff p_mgrp = osm_get_mgrp_by_mlid(&p_osm->subn, mlid); 745219820Sjeff if (p_mgrp) { 746219820Sjeff if (!memcmp(&p_mgrp->mcmember_rec.mgid, &p_mcm_rec->mgid, 747219820Sjeff sizeof(ib_gid_t))) { 748219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, 749219820Sjeff "mgrp %04x is already here.", cl_ntoh16(mlid)); 750219820Sjeff goto _out; 751219820Sjeff } 752219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, 753219820Sjeff "mlid %04x is already used by another MC group. Will " 754219820Sjeff "request clients reregistration.\n", cl_ntoh16(mlid)); 755219820Sjeff p_mgrp = NULL; 756219820Sjeff goto _out; 757219820Sjeff } 758219820Sjeff 759219820Sjeff comp_mask = IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_MTU_SEL 760219820Sjeff | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_RATE_SEL; 761219820Sjeff if (osm_mcmr_rcv_find_or_create_new_mgrp(&p_osm->sa, 762219820Sjeff comp_mask, p_mcm_rec, 763219820Sjeff &p_mgrp) != IB_SUCCESS || 764219820Sjeff !p_mgrp || p_mgrp->mlid != mlid) { 765219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, 766219820Sjeff "cannot create MC group with mlid 0x%04x and mgid " 767219820Sjeff "0x%016" PRIx64 ":0x%016" PRIx64 "\n", cl_ntoh16(mlid), 768219820Sjeff cl_ntoh64(p_mcm_rec->mgid.unicast.prefix), 769219820Sjeff cl_ntoh64(p_mcm_rec->mgid.unicast.interface_id)); 770219820Sjeff p_mgrp = NULL; 771219820Sjeff } else if (well_known) 772219820Sjeff p_mgrp->well_known = TRUE; 773219820Sjeff 774219820Sjeff_out: 775219820Sjeff cl_plock_release(&p_osm->lock); 776219820Sjeff 777219820Sjeff return p_mgrp; 778219820Sjeff} 779219820Sjeff 780219820Sjeffstatic int load_svcr(osm_opensm_t * p_osm, ib_service_record_t * sr, 781219820Sjeff uint32_t modified_time, uint32_t lease_period) 782219820Sjeff{ 783219820Sjeff osm_svcr_t *p_svcr; 784219820Sjeff int ret = 0; 785219820Sjeff 786219820Sjeff cl_plock_excl_acquire(&p_osm->lock); 787219820Sjeff 788219820Sjeff if (osm_svcr_get_by_rid(&p_osm->subn, &p_osm->log, sr)) { 789219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, 790219820Sjeff "ServiceRecord already exists\n"); 791219820Sjeff goto _out; 792219820Sjeff } 793219820Sjeff 794219820Sjeff if (!(p_svcr = osm_svcr_new(sr))) { 795219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, 796219820Sjeff "cannot allocate new service struct\n"); 797219820Sjeff ret = -1; 798219820Sjeff goto _out; 799219820Sjeff } 800219820Sjeff 801219820Sjeff p_svcr->modified_time = modified_time; 802219820Sjeff p_svcr->lease_period = lease_period; 803219820Sjeff 804219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding ServiceRecord...\n"); 805219820Sjeff 806219820Sjeff osm_svcr_insert_to_db(&p_osm->subn, &p_osm->log, p_svcr); 807219820Sjeff 808219820Sjeff if (lease_period != 0xffffffff) 809219820Sjeff cl_timer_trim(&p_osm->sa.sr_timer, 1000); 810219820Sjeff 811219820Sjeff_out: 812219820Sjeff cl_plock_release(&p_osm->lock); 813219820Sjeff 814219820Sjeff return ret; 815219820Sjeff} 816219820Sjeff 817219820Sjeffstatic int load_infr(osm_opensm_t * p_osm, ib_inform_info_record_t * iir, 818219820Sjeff osm_mad_addr_t * addr) 819219820Sjeff{ 820219820Sjeff osm_infr_t infr, *p_infr; 821219820Sjeff int ret = 0; 822219820Sjeff 823219820Sjeff infr.h_bind = p_osm->sa.mad_ctrl.h_bind; 824219820Sjeff infr.sa = &p_osm->sa; 825219820Sjeff /* other possible way to restore mad_addr partially is 826219820Sjeff to extract qpn from InformInfo and to find lid by gid */ 827219820Sjeff infr.report_addr = *addr; 828219820Sjeff infr.inform_record = *iir; 829219820Sjeff 830219820Sjeff cl_plock_excl_acquire(&p_osm->lock); 831219820Sjeff if (osm_infr_get_by_rec(&p_osm->subn, &p_osm->log, &infr)) { 832219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, 833219820Sjeff "InformInfo Record already exists\n"); 834219820Sjeff goto _out; 835219820Sjeff } 836219820Sjeff 837219820Sjeff if (!(p_infr = osm_infr_new(&infr))) { 838219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, 839219820Sjeff "cannot allocate new infr struct\n"); 840219820Sjeff ret = -1; 841219820Sjeff goto _out; 842219820Sjeff } 843219820Sjeff 844219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_DEBUG, "adding InformInfo Record...\n"); 845219820Sjeff 846219820Sjeff osm_infr_insert_to_db(&p_osm->subn, &p_osm->log, p_infr); 847219820Sjeff 848219820Sjeff_out: 849219820Sjeff cl_plock_release(&p_osm->lock); 850219820Sjeff 851219820Sjeff return ret; 852219820Sjeff} 853219820Sjeff 854219820Sjeff#define UNPACK_FUNC(name,x) \ 855219820Sjeffstatic int unpack_##name##x(char *p, uint##x##_t *val_ptr) \ 856219820Sjeff{ \ 857219820Sjeff char *q; \ 858219820Sjeff unsigned long long num; \ 859219820Sjeff num = strtoull(p, &q, 16); \ 860219820Sjeff if (num > ~((uint##x##_t)0x0) \ 861219820Sjeff || q == p || (!isspace(*q) && *q != ':')) { \ 862219820Sjeff *val_ptr = 0; \ 863219820Sjeff return -1; \ 864219820Sjeff } \ 865219820Sjeff *val_ptr = cl_hton##x((uint##x##_t)num); \ 866219820Sjeff return (int)(q - p); \ 867219820Sjeff} 868219820Sjeff 869219820Sjeff#define cl_hton8(x) (x) 870219820Sjeff 871219820SjeffUNPACK_FUNC(net, 8); 872219820SjeffUNPACK_FUNC(net, 16); 873219820SjeffUNPACK_FUNC(net, 32); 874219820SjeffUNPACK_FUNC(net, 64); 875219820Sjeff 876219820Sjeffstatic int unpack_string(char *p, uint8_t * buf, unsigned len) 877219820Sjeff{ 878219820Sjeff char *q = p; 879219820Sjeff char delim = ' '; 880219820Sjeff 881219820Sjeff if (*q == '\'' || *q == '\"') 882219820Sjeff delim = *q++; 883219820Sjeff while (--len && *q && *q != delim) 884219820Sjeff *buf++ = *q++; 885219820Sjeff *buf = '\0'; 886219820Sjeff if (*q == delim && delim != ' ') 887219820Sjeff q++; 888219820Sjeff return (int)(q - p); 889219820Sjeff} 890219820Sjeff 891219820Sjeffstatic int unpack_string64(char *p, uint8_t * buf) 892219820Sjeff{ 893219820Sjeff return unpack_string(p, buf, 64); 894219820Sjeff} 895219820Sjeff 896219820Sjeff#define PARSE_AHEAD(p, x, name, val_ptr) { int _ret; \ 897219820Sjeff p = strstr(p, name); \ 898219820Sjeff if (!p) { \ 899219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \ 900219820Sjeff "PARSE ERROR: %s:%u: cannot find \"%s\" string\n", \ 901219820Sjeff file_name, lineno, (name)); \ 902219820Sjeff ret = -2; \ 903219820Sjeff goto _error; \ 904219820Sjeff } \ 905219820Sjeff p += strlen(name); \ 906219820Sjeff _ret = unpack_##x(p, (val_ptr)); \ 907219820Sjeff if (_ret < 0) { \ 908219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR, \ 909219820Sjeff "PARSE ERROR: %s:%u: cannot parse "#x" value " \ 910219820Sjeff "after \"%s\"\n", file_name, lineno, (name)); \ 911219820Sjeff ret = _ret; \ 912219820Sjeff goto _error; \ 913219820Sjeff } \ 914219820Sjeff p += _ret; \ 915219820Sjeff} 916219820Sjeff 917219820Sjeffint osm_sa_db_file_load(osm_opensm_t * p_osm) 918219820Sjeff{ 919219820Sjeff char line[1024]; 920219820Sjeff char *file_name; 921219820Sjeff FILE *file; 922219820Sjeff int ret = 0; 923219820Sjeff osm_mgrp_t *p_mgrp = NULL; 924219820Sjeff unsigned rereg_clients = 0; 925219820Sjeff unsigned lineno; 926219820Sjeff 927219820Sjeff file_name = p_osm->subn.opt.sa_db_file; 928219820Sjeff if (!file_name) { 929219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_VERBOSE, 930219820Sjeff "sa db file name is not specifed. Skip restore\n"); 931219820Sjeff return 0; 932219820Sjeff } 933219820Sjeff 934219820Sjeff file = fopen(file_name, "r"); 935219820Sjeff if (!file) { 936219820Sjeff OSM_LOG(&p_osm->log, OSM_LOG_ERROR | OSM_LOG_SYS, "ERR 4C02: " 937219820Sjeff "cannot open sa db file \'%s\'. Skip restoring\n", 938219820Sjeff file_name); 939219820Sjeff return -1; 940219820Sjeff } 941219820Sjeff 942219820Sjeff lineno = 0; 943219820Sjeff 944219820Sjeff while (fgets(line, sizeof(line) - 1, file) != NULL) { 945219820Sjeff char *p; 946219820Sjeff uint8_t val; 947219820Sjeff 948219820Sjeff lineno++; 949219820Sjeff 950219820Sjeff p = line; 951219820Sjeff while (isspace(*p)) 952219820Sjeff p++; 953219820Sjeff 954219820Sjeff if (*p == '#') 955219820Sjeff continue; 956219820Sjeff 957219820Sjeff if (!strncmp(p, "MC Group", 8)) { 958219820Sjeff ib_member_rec_t mcm_rec; 959219820Sjeff ib_net16_t mlid; 960219820Sjeff unsigned well_known = 0; 961219820Sjeff 962219820Sjeff p_mgrp = NULL; 963219820Sjeff memset(&mcm_rec, 0, sizeof(mcm_rec)); 964219820Sjeff 965219820Sjeff PARSE_AHEAD(p, net16, " 0x", &mlid); 966219820Sjeff if (strstr(p, "well known")) 967219820Sjeff well_known = 1; 968219820Sjeff PARSE_AHEAD(p, net64, " mgid=0x", 969219820Sjeff &mcm_rec.mgid.unicast.prefix); 970219820Sjeff PARSE_AHEAD(p, net64, ":0x", 971219820Sjeff &mcm_rec.mgid.unicast.interface_id); 972219820Sjeff PARSE_AHEAD(p, net64, " port_gid=0x", 973219820Sjeff &mcm_rec.port_gid.unicast.prefix); 974219820Sjeff PARSE_AHEAD(p, net64, ":0x", 975219820Sjeff &mcm_rec.port_gid.unicast.interface_id); 976219820Sjeff PARSE_AHEAD(p, net32, " qkey=0x", &mcm_rec.qkey); 977219820Sjeff PARSE_AHEAD(p, net16, " mlid=0x", &mcm_rec.mlid); 978219820Sjeff PARSE_AHEAD(p, net8, " mtu=0x", &mcm_rec.mtu); 979219820Sjeff PARSE_AHEAD(p, net8, " tclass=0x", &mcm_rec.tclass); 980219820Sjeff PARSE_AHEAD(p, net16, " pkey=0x", &mcm_rec.pkey); 981219820Sjeff PARSE_AHEAD(p, net8, " rate=0x", &mcm_rec.rate); 982219820Sjeff PARSE_AHEAD(p, net8, " pkt_life=0x", &mcm_rec.pkt_life); 983219820Sjeff PARSE_AHEAD(p, net32, " sl_flow_hop=0x", 984219820Sjeff &mcm_rec.sl_flow_hop); 985219820Sjeff PARSE_AHEAD(p, net8, " scope_state=0x", 986219820Sjeff &mcm_rec.scope_state); 987219820Sjeff PARSE_AHEAD(p, net8, " proxy_join=0x", &val); 988219820Sjeff mcm_rec.proxy_join = val; 989219820Sjeff 990219820Sjeff p_mgrp = load_mcgroup(p_osm, mlid, &mcm_rec, 991219820Sjeff well_known); 992219820Sjeff if (!p_mgrp) 993219820Sjeff rereg_clients = 1; 994219820Sjeff } else if (p_mgrp && !strncmp(p, "mcm_port", 8)) { 995219820Sjeff ib_gid_t port_gid; 996219820Sjeff ib_net64_t guid; 997219820Sjeff uint8_t scope_state; 998219820Sjeff boolean_t proxy_join; 999219820Sjeff 1000219820Sjeff PARSE_AHEAD(p, net64, " port_gid=0x", 1001219820Sjeff &port_gid.unicast.prefix); 1002219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1003219820Sjeff &port_gid.unicast.interface_id); 1004219820Sjeff PARSE_AHEAD(p, net8, " scope_state=0x", &scope_state); 1005219820Sjeff PARSE_AHEAD(p, net8, " proxy_join=0x", &val); 1006219820Sjeff proxy_join = val; 1007219820Sjeff 1008219820Sjeff guid = port_gid.unicast.interface_id; 1009219820Sjeff if (cl_qmap_get(&p_mgrp->mcm_port_tbl, 1010219820Sjeff port_gid.unicast.interface_id) == 1011219820Sjeff cl_qmap_end(&p_mgrp->mcm_port_tbl)) 1012219820Sjeff osm_mgrp_add_port(&p_osm->subn, &p_osm->log, 1013219820Sjeff p_mgrp, &port_gid, 1014219820Sjeff scope_state, proxy_join); 1015219820Sjeff } else if (!strncmp(p, "Service Record:", 15)) { 1016219820Sjeff ib_service_record_t s_rec; 1017219820Sjeff uint32_t modified_time, lease_period; 1018219820Sjeff 1019219820Sjeff p_mgrp = NULL; 1020219820Sjeff memset(&s_rec, 0, sizeof(s_rec)); 1021219820Sjeff 1022219820Sjeff PARSE_AHEAD(p, net64, " id=0x", &s_rec.service_id); 1023219820Sjeff PARSE_AHEAD(p, net64, " gid=0x", 1024219820Sjeff &s_rec.service_gid.unicast.prefix); 1025219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1026219820Sjeff &s_rec.service_gid.unicast.interface_id); 1027219820Sjeff PARSE_AHEAD(p, net16, " pkey=0x", &s_rec.service_pkey); 1028219820Sjeff PARSE_AHEAD(p, net32, " lease=0x", 1029219820Sjeff &s_rec.service_lease); 1030219820Sjeff PARSE_AHEAD(p, net64, " key=0x", 1031219820Sjeff (ib_net64_t *) (&s_rec.service_key[0])); 1032219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1033219820Sjeff (ib_net64_t *) (&s_rec.service_key[8])); 1034219820Sjeff PARSE_AHEAD(p, string64, " name=", s_rec.service_name); 1035219820Sjeff PARSE_AHEAD(p, net64, " data8=0x", 1036219820Sjeff (ib_net64_t *) (&s_rec.service_data8[0])); 1037219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1038219820Sjeff (ib_net64_t *) (&s_rec.service_data8[8])); 1039219820Sjeff PARSE_AHEAD(p, net64, " data16=0x", 1040219820Sjeff (ib_net64_t *) (&s_rec.service_data16[0])); 1041219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1042219820Sjeff (ib_net64_t *) (&s_rec.service_data16[4])); 1043219820Sjeff PARSE_AHEAD(p, net64, " data32=0x", 1044219820Sjeff (ib_net64_t *) (&s_rec.service_data32[0])); 1045219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1046219820Sjeff (ib_net64_t *) (&s_rec.service_data32[2])); 1047219820Sjeff PARSE_AHEAD(p, net64, " data64=0x", 1048219820Sjeff &s_rec.service_data64[0]); 1049219820Sjeff PARSE_AHEAD(p, net64, ":0x", &s_rec.service_data64[1]); 1050219820Sjeff PARSE_AHEAD(p, net32, " modified_time=0x", 1051219820Sjeff &modified_time); 1052219820Sjeff PARSE_AHEAD(p, net32, " lease_period=0x", 1053219820Sjeff &lease_period); 1054219820Sjeff 1055219820Sjeff if (load_svcr(p_osm, &s_rec, cl_ntoh32(modified_time), 1056219820Sjeff cl_ntoh32(lease_period))) 1057219820Sjeff rereg_clients = 1; 1058219820Sjeff } else if (!strncmp(p, "InformInfo Record:", 18)) { 1059219820Sjeff ib_inform_info_record_t i_rec; 1060219820Sjeff osm_mad_addr_t rep_addr; 1061219820Sjeff ib_net16_t val16; 1062219820Sjeff 1063219820Sjeff p_mgrp = NULL; 1064219820Sjeff memset(&i_rec, 0, sizeof(i_rec)); 1065219820Sjeff memset(&rep_addr, 0, sizeof(rep_addr)); 1066219820Sjeff 1067219820Sjeff PARSE_AHEAD(p, net64, " subscriber_gid=0x", 1068219820Sjeff &i_rec.subscriber_gid.unicast.prefix); 1069219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1070219820Sjeff &i_rec.subscriber_gid.unicast.interface_id); 1071219820Sjeff PARSE_AHEAD(p, net16, " subscriber_enum=0x", 1072219820Sjeff &i_rec.subscriber_enum); 1073219820Sjeff PARSE_AHEAD(p, net64, " gid=0x", 1074219820Sjeff &i_rec.inform_info.gid.unicast.prefix); 1075219820Sjeff PARSE_AHEAD(p, net64, ":0x", 1076219820Sjeff &i_rec.inform_info.gid.unicast. 1077219820Sjeff interface_id); 1078219820Sjeff PARSE_AHEAD(p, net16, " lid_range_begin=0x", 1079219820Sjeff &i_rec.inform_info.lid_range_begin); 1080219820Sjeff PARSE_AHEAD(p, net16, " lid_range_end=0x", 1081219820Sjeff &i_rec.inform_info.lid_range_end); 1082219820Sjeff PARSE_AHEAD(p, net8, " is_generic=0x", 1083219820Sjeff &i_rec.inform_info.is_generic); 1084219820Sjeff PARSE_AHEAD(p, net8, " subscribe=0x", 1085219820Sjeff &i_rec.inform_info.subscribe); 1086219820Sjeff PARSE_AHEAD(p, net16, " trap_type=0x", 1087219820Sjeff &i_rec.inform_info.trap_type); 1088219820Sjeff PARSE_AHEAD(p, net16, " trap_num=0x", 1089219820Sjeff &i_rec.inform_info.g_or_v.generic.trap_num); 1090219820Sjeff PARSE_AHEAD(p, net32, " qpn_resp_time_val=0x", 1091219820Sjeff &i_rec.inform_info.g_or_v.generic. 1092219820Sjeff qpn_resp_time_val); 1093219820Sjeff PARSE_AHEAD(p, net32, " node_type=0x", 1094219820Sjeff (uint32_t *) & i_rec.inform_info.g_or_v. 1095219820Sjeff generic.reserved2); 1096219820Sjeff 1097219820Sjeff PARSE_AHEAD(p, net16, " rep_addr: lid=0x", 1098219820Sjeff &rep_addr.dest_lid); 1099219820Sjeff PARSE_AHEAD(p, net8, " path_bits=0x", 1100219820Sjeff &rep_addr.path_bits); 1101219820Sjeff PARSE_AHEAD(p, net8, " static_rate=0x", 1102219820Sjeff &rep_addr.static_rate); 1103219820Sjeff PARSE_AHEAD(p, net32, " remote_qp=0x", 1104219820Sjeff &rep_addr.addr_type.gsi.remote_qp); 1105219820Sjeff PARSE_AHEAD(p, net32, " remote_qkey=0x", 1106219820Sjeff &rep_addr.addr_type.gsi.remote_qkey); 1107219820Sjeff PARSE_AHEAD(p, net16, " pkey_ix=0x", &val16); 1108219820Sjeff rep_addr.addr_type.gsi.pkey_ix = cl_ntoh16(val16); 1109219820Sjeff PARSE_AHEAD(p, net8, " sl=0x", 1110219820Sjeff &rep_addr.addr_type.gsi.service_level); 1111219820Sjeff 1112219820Sjeff if (load_infr(p_osm, &i_rec, &rep_addr)) 1113219820Sjeff rereg_clients = 1; 1114219820Sjeff } 1115219820Sjeff } 1116219820Sjeff 1117219820Sjeff if (!rereg_clients) 1118219820Sjeff p_osm->subn.opt.no_clients_rereg = TRUE; 1119219820Sjeff 1120219820Sjeff_error: 1121219820Sjeff fclose(file); 1122219820Sjeff return ret; 1123219820Sjeff} 1124