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 * 6219820Sjeff * This software is available to you under a choice of one of two 7219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 8219820Sjeff * General Public License (GPL) Version 2, available from the file 9219820Sjeff * COPYING in the main directory of this source tree, or the 10219820Sjeff * OpenIB.org BSD license below: 11219820Sjeff * 12219820Sjeff * Redistribution and use in source and binary forms, with or 13219820Sjeff * without modification, are permitted provided that the following 14219820Sjeff * conditions are met: 15219820Sjeff * 16219820Sjeff * - Redistributions of source code must retain the above 17219820Sjeff * copyright notice, this list of conditions and the following 18219820Sjeff * disclaimer. 19219820Sjeff * 20219820Sjeff * - Redistributions in binary form must reproduce the above 21219820Sjeff * copyright notice, this list of conditions and the following 22219820Sjeff * disclaimer in the documentation and/or other materials 23219820Sjeff * provided with the distribution. 24219820Sjeff * 25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32219820Sjeff * SOFTWARE. 33219820Sjeff * 34219820Sjeff */ 35219820Sjeff 36219820Sjeff/* 37219820Sjeff * Abstract: 38219820Sjeff * Implementation of osm_sm_mad_ctrl_t. 39219820Sjeff * This object represents the SM MAD request controller object. 40219820Sjeff * This object is part of the opensm family of objects. 41219820Sjeff */ 42219820Sjeff 43219820Sjeff#if HAVE_CONFIG_H 44219820Sjeff# include <config.h> 45219820Sjeff#endif /* HAVE_CONFIG_H */ 46219820Sjeff 47219820Sjeff#include <string.h> 48219820Sjeff#include <complib/cl_debug.h> 49219820Sjeff#include <iba/ib_types.h> 50219820Sjeff#include <opensm/osm_sm_mad_ctrl.h> 51219820Sjeff#include <vendor/osm_vendor_api.h> 52219820Sjeff#include <opensm/osm_madw.h> 53219820Sjeff#include <opensm/osm_msgdef.h> 54219820Sjeff#include <opensm/osm_helper.h> 55219820Sjeff#include <opensm/osm_opensm.h> 56219820Sjeff 57219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_retire_trans_mad 58219820Sjeff * NAME 59219820Sjeff * __osm_sm_mad_ctrl_retire_trans_mad 60219820Sjeff * 61219820Sjeff * DESCRIPTION 62219820Sjeff * This function handles clean-up of MADs associated with the SM's 63219820Sjeff * outstanding transactions on the wire. 64219820Sjeff * 65219820Sjeff * SYNOPSIS 66219820Sjeff */ 67219820Sjeff 68219820Sjeffstatic void 69219820Sjeff__osm_sm_mad_ctrl_retire_trans_mad(IN osm_sm_mad_ctrl_t * const p_ctrl, 70219820Sjeff IN osm_madw_t * const p_madw) 71219820Sjeff{ 72219820Sjeff uint32_t outstanding; 73219820Sjeff 74219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 75219820Sjeff 76219820Sjeff CL_ASSERT(p_madw); 77219820Sjeff /* 78219820Sjeff Return the MAD & wrapper to the pool. 79219820Sjeff */ 80219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 81219820Sjeff "Retiring MAD with TID 0x%" PRIx64 "\n", 82219820Sjeff cl_ntoh64(osm_madw_get_smp_ptr(p_madw)->trans_id)); 83219820Sjeff 84219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 85219820Sjeff 86219820Sjeff outstanding = osm_stats_dec_qp0_outstanding(p_ctrl->p_stats); 87219820Sjeff 88219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs outstanding%s\n", 89219820Sjeff p_ctrl->p_stats->qp0_mads_outstanding, 90219820Sjeff outstanding ? "" : ": wire is clean."); 91219820Sjeff 92219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 93219820Sjeff} 94219820Sjeff 95219820Sjeff/************/ 96219820Sjeff 97219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_disp_done_callback 98219820Sjeff * NAME 99219820Sjeff * __osm_sm_mad_ctrl_disp_done_callback 100219820Sjeff * 101219820Sjeff * DESCRIPTION 102219820Sjeff * This function is the Dispatcher callback that indicates 103219820Sjeff * a received MAD has been processed by the recipient. 104219820Sjeff * 105219820Sjeff * SYNOPSIS 106219820Sjeff */ 107219820Sjeffstatic void 108219820Sjeff__osm_sm_mad_ctrl_disp_done_callback(IN void *context, IN void *p_data) 109219820Sjeff{ 110219820Sjeff osm_sm_mad_ctrl_t *const p_ctrl = (osm_sm_mad_ctrl_t *) context; 111219820Sjeff osm_madw_t *const p_madw = (osm_madw_t *) p_data; 112219820Sjeff ib_smp_t *p_smp; 113219820Sjeff 114219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 115219820Sjeff 116219820Sjeff /* 117219820Sjeff If the MAD that just finished processing was a response, 118219820Sjeff then retire the transaction, since we must have generated 119219820Sjeff the request. 120219820Sjeff 121219820Sjeff Otherwise, retire the transaction if a response was expected, 122219820Sjeff as in the case of a send failure. If a response was not expected, 123219820Sjeff just put the MAD back in the pool, because the MAD was a query 124219820Sjeff from some outside agent, e.g. Get(SMInfo) from another SM. 125219820Sjeff */ 126219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 127219820Sjeff if (ib_smp_is_response(p_smp)) { 128219820Sjeff CL_ASSERT(p_madw->resp_expected == FALSE); 129219820Sjeff __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 130219820Sjeff } else if (p_madw->resp_expected == TRUE) 131219820Sjeff __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 132219820Sjeff else 133219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 134219820Sjeff 135219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 136219820Sjeff} 137219820Sjeff 138219820Sjeff/************/ 139219820Sjeff 140219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_update_wire_stats 141219820Sjeff * NAME 142219820Sjeff * __osm_sm_mad_ctrl_update_wire_stats 143219820Sjeff * 144219820Sjeff * DESCRIPTION 145219820Sjeff * Updates wire stats for outstanding MADs and calls the VL15 poller. 146219820Sjeff * 147219820Sjeff * SYNOPSIS 148219820Sjeff */ 149219820Sjeffstatic void 150219820Sjeff__osm_sm_mad_ctrl_update_wire_stats(IN osm_sm_mad_ctrl_t * const p_ctrl) 151219820Sjeff{ 152219820Sjeff uint32_t mads_on_wire; 153219820Sjeff 154219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 155219820Sjeff 156219820Sjeff mads_on_wire = 157219820Sjeff cl_atomic_dec(&p_ctrl->p_stats->qp0_mads_outstanding_on_wire); 158219820Sjeff 159219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 160219820Sjeff "%u SMPs on the wire, %u outstanding\n", mads_on_wire, 161219820Sjeff p_ctrl->p_stats->qp0_mads_outstanding); 162219820Sjeff 163219820Sjeff /* 164219820Sjeff We can signal the VL15 controller to send another MAD 165219820Sjeff if any are waiting for transmission. 166219820Sjeff */ 167219820Sjeff osm_vl15_poll(p_ctrl->p_vl15); 168219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 169219820Sjeff} 170219820Sjeff 171219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_process_get_resp 172219820Sjeff * NAME 173219820Sjeff * __osm_sm_mad_ctrl_process_get_resp 174219820Sjeff * 175219820Sjeff * DESCRIPTION 176219820Sjeff * This function handles method GetResp() for received MADs. 177219820Sjeff * This is the most common path for QP0 MADs. 178219820Sjeff * 179219820Sjeff * SYNOPSIS 180219820Sjeff */ 181219820Sjeffstatic void 182219820Sjeff__osm_sm_mad_ctrl_process_get_resp(IN osm_sm_mad_ctrl_t * const p_ctrl, 183219820Sjeff IN osm_madw_t * p_madw, 184219820Sjeff IN void *transaction_context) 185219820Sjeff{ 186219820Sjeff ib_smp_t *p_smp; 187219820Sjeff cl_status_t status; 188219820Sjeff osm_madw_t *p_old_madw; 189219820Sjeff cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 190219820Sjeff 191219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 192219820Sjeff 193219820Sjeff CL_ASSERT(p_madw); 194219820Sjeff CL_ASSERT(transaction_context); 195219820Sjeff 196219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 197219820Sjeff 198219820Sjeff if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR && !ib_smp_is_d(p_smp)) { 199219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3102: " 200219820Sjeff "'D' bit not set in returned SMP\n"); 201219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 202219820Sjeff } 203219820Sjeff 204219820Sjeff p_old_madw = (osm_madw_t *) transaction_context; 205219820Sjeff 206219820Sjeff __osm_sm_mad_ctrl_update_wire_stats(p_ctrl); 207219820Sjeff 208219820Sjeff /* 209219820Sjeff Copy the MAD Wrapper context from the requesting MAD 210219820Sjeff to the new MAD. This mechanism allows the recipient 211219820Sjeff controller to recover its own context regarding this 212219820Sjeff MAD transaction. Once we've copied the context, we 213219820Sjeff can return the original MAD to the pool. 214219820Sjeff */ 215219820Sjeff osm_madw_copy_context(p_madw, p_old_madw); 216219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_old_madw); 217219820Sjeff 218219820Sjeff /* 219219820Sjeff Note that attr_id (like the rest of the MAD) is in 220219820Sjeff network byte order. 221219820Sjeff */ 222219820Sjeff switch (p_smp->attr_id) { 223219820Sjeff case IB_MAD_ATTR_NODE_DESC: 224219820Sjeff msg_id = OSM_MSG_MAD_NODE_DESC; 225219820Sjeff break; 226219820Sjeff case IB_MAD_ATTR_NODE_INFO: 227219820Sjeff msg_id = OSM_MSG_MAD_NODE_INFO; 228219820Sjeff break; 229219820Sjeff case IB_MAD_ATTR_SWITCH_INFO: 230219820Sjeff msg_id = OSM_MSG_MAD_SWITCH_INFO; 231219820Sjeff break; 232219820Sjeff case IB_MAD_ATTR_PORT_INFO: 233219820Sjeff msg_id = OSM_MSG_MAD_PORT_INFO; 234219820Sjeff break; 235219820Sjeff case IB_MAD_ATTR_LIN_FWD_TBL: 236219820Sjeff msg_id = OSM_MSG_MAD_LFT; 237219820Sjeff break; 238219820Sjeff case IB_MAD_ATTR_MCAST_FWD_TBL: 239219820Sjeff msg_id = OSM_MSG_MAD_MFT; 240219820Sjeff break; 241219820Sjeff case IB_MAD_ATTR_SM_INFO: 242219820Sjeff msg_id = OSM_MSG_MAD_SM_INFO; 243219820Sjeff break; 244219820Sjeff case IB_MAD_ATTR_SLVL_TABLE: 245219820Sjeff msg_id = OSM_MSG_MAD_SLVL; 246219820Sjeff break; 247219820Sjeff case IB_MAD_ATTR_VL_ARBITRATION: 248219820Sjeff msg_id = OSM_MSG_MAD_VL_ARB; 249219820Sjeff break; 250219820Sjeff case IB_MAD_ATTR_P_KEY_TABLE: 251219820Sjeff msg_id = OSM_MSG_MAD_PKEY; 252219820Sjeff break; 253219820Sjeff 254219820Sjeff case IB_MAD_ATTR_GUID_INFO: 255219820Sjeff case IB_MAD_ATTR_CLASS_PORT_INFO: 256219820Sjeff case IB_MAD_ATTR_NOTICE: 257219820Sjeff case IB_MAD_ATTR_INFORM_INFO: 258219820Sjeff default: 259219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 260219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3103: " 261219820Sjeff "Unsupported attribute = 0x%X\n", 262219820Sjeff cl_ntoh16(p_smp->attr_id)); 263219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 264219820Sjeff goto Exit; 265219820Sjeff } 266219820Sjeff 267219820Sjeff if (msg_id == CL_DISP_MSGID_NONE) 268219820Sjeff goto Exit; 269219820Sjeff 270219820Sjeff /* 271219820Sjeff Post this MAD to the dispatcher for asynchronous 272219820Sjeff processing by the appropriate controller. 273219820Sjeff */ 274219820Sjeff 275219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 276219820Sjeff osm_get_disp_msg_str(msg_id)); 277219820Sjeff 278219820Sjeff status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 279219820Sjeff __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 280219820Sjeff 281219820Sjeff if (status != CL_SUCCESS) { 282219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3104: " 283219820Sjeff "Dispatcher post message failed (%s) for attribute = 0x%X\n", 284219820Sjeff CL_STATUS_MSG(status), cl_ntoh16(p_smp->attr_id)); 285219820Sjeff goto Exit; 286219820Sjeff } 287219820Sjeff 288219820SjeffExit: 289219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 290219820Sjeff} 291219820Sjeff 292219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_process_get 293219820Sjeff * NAME 294219820Sjeff * __osm_sm_mad_ctrl_process_get 295219820Sjeff * 296219820Sjeff * DESCRIPTION 297219820Sjeff * This function handles method Get() for received MADs. 298219820Sjeff * 299219820Sjeff * SYNOPSIS 300219820Sjeff */ 301219820Sjeffstatic void 302219820Sjeff__osm_sm_mad_ctrl_process_get(IN osm_sm_mad_ctrl_t * const p_ctrl, 303219820Sjeff IN osm_madw_t * p_madw) 304219820Sjeff{ 305219820Sjeff ib_smp_t *p_smp; 306219820Sjeff cl_status_t status; 307219820Sjeff cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 308219820Sjeff 309219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 310219820Sjeff 311219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 312219820Sjeff 313219820Sjeff /* 314219820Sjeff Note that attr_id (like the rest of the MAD) is in 315219820Sjeff network byte order. 316219820Sjeff */ 317219820Sjeff switch (p_smp->attr_id) { 318219820Sjeff case IB_MAD_ATTR_SM_INFO: 319219820Sjeff msg_id = OSM_MSG_MAD_SM_INFO; 320219820Sjeff break; 321219820Sjeff 322219820Sjeff default: 323219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 324219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 325219820Sjeff "Ignoring SubnGet MAD - unsupported attribute = 0x%X\n", 326219820Sjeff cl_ntoh16(p_smp->attr_id)); 327219820Sjeff break; 328219820Sjeff } 329219820Sjeff 330219820Sjeff if (msg_id == CL_DISP_MSGID_NONE) { 331219820Sjeff /* 332219820Sjeff There is an unknown MAD attribute type for which there is 333219820Sjeff no recipient. Simply retire the MAD here. 334219820Sjeff */ 335219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 336219820Sjeff goto Exit; 337219820Sjeff } 338219820Sjeff 339219820Sjeff /* 340219820Sjeff Post this MAD to the dispatcher for asynchronous 341219820Sjeff processing by the appropriate controller. 342219820Sjeff */ 343219820Sjeff 344219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 345219820Sjeff osm_get_disp_msg_str(msg_id)); 346219820Sjeff 347219820Sjeff status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 348219820Sjeff __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 349219820Sjeff 350219820Sjeff if (status != CL_SUCCESS) { 351219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3106: " 352219820Sjeff "Dispatcher post message failed (%s)\n", 353219820Sjeff CL_STATUS_MSG(status)); 354219820Sjeff goto Exit; 355219820Sjeff } 356219820Sjeff 357219820SjeffExit: 358219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 359219820Sjeff} 360219820Sjeff 361219820Sjeff/* 362219820Sjeff * PARAMETERS 363219820Sjeff * 364219820Sjeff * RETURN VALUES 365219820Sjeff * 366219820Sjeff * NOTES 367219820Sjeff * 368219820Sjeff * SEE ALSO 369219820Sjeff *********/ 370219820Sjeff 371219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_process_set 372219820Sjeff * NAME 373219820Sjeff * __osm_sm_mad_ctrl_process_set 374219820Sjeff * 375219820Sjeff * DESCRIPTION 376219820Sjeff * This function handles method Set() for received MADs. 377219820Sjeff * 378219820Sjeff * SYNOPSIS 379219820Sjeff */ 380219820Sjeffstatic void 381219820Sjeff__osm_sm_mad_ctrl_process_set(IN osm_sm_mad_ctrl_t * const p_ctrl, 382219820Sjeff IN osm_madw_t * p_madw) 383219820Sjeff{ 384219820Sjeff ib_smp_t *p_smp; 385219820Sjeff cl_status_t status; 386219820Sjeff cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 387219820Sjeff 388219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 389219820Sjeff 390219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 391219820Sjeff 392219820Sjeff /* 393219820Sjeff Note that attr_id (like the rest of the MAD) is in 394219820Sjeff network byte order. 395219820Sjeff */ 396219820Sjeff switch (p_smp->attr_id) { 397219820Sjeff case IB_MAD_ATTR_SM_INFO: 398219820Sjeff msg_id = OSM_MSG_MAD_SM_INFO; 399219820Sjeff break; 400219820Sjeff 401219820Sjeff default: 402219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 403219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3107: " 404219820Sjeff "Unsupported attribute = 0x%X\n", 405219820Sjeff cl_ntoh16(p_smp->attr_id)); 406219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 407219820Sjeff break; 408219820Sjeff } 409219820Sjeff 410219820Sjeff if (msg_id == CL_DISP_MSGID_NONE) { 411219820Sjeff /* 412219820Sjeff There is an unknown MAD attribute type for which there is 413219820Sjeff no recipient. Simply retire the MAD here. 414219820Sjeff */ 415219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 416219820Sjeff goto Exit; 417219820Sjeff } 418219820Sjeff 419219820Sjeff /* 420219820Sjeff Post this MAD to the dispatcher for asynchronous 421219820Sjeff processing by the appropriate controller. 422219820Sjeff */ 423219820Sjeff 424219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 425219820Sjeff osm_get_disp_msg_str(msg_id)); 426219820Sjeff 427219820Sjeff status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 428219820Sjeff __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 429219820Sjeff 430219820Sjeff if (status != CL_SUCCESS) { 431219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3108: " 432219820Sjeff "Dispatcher post message failed (%s)\n", 433219820Sjeff CL_STATUS_MSG(status)); 434219820Sjeff goto Exit; 435219820Sjeff } 436219820Sjeff 437219820SjeffExit: 438219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 439219820Sjeff} 440219820Sjeff 441219820Sjeff/* 442219820Sjeff * PARAMETERS 443219820Sjeff * 444219820Sjeff * RETURN VALUES 445219820Sjeff * 446219820Sjeff * NOTES 447219820Sjeff * 448219820Sjeff * SEE ALSO 449219820Sjeff *********/ 450219820Sjeff 451219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_process_trap 452219820Sjeff * NAME 453219820Sjeff * __osm_sm_mad_ctrl_process_trap 454219820Sjeff * 455219820Sjeff * DESCRIPTION 456219820Sjeff * This function handles method Trap() for received MADs. 457219820Sjeff * 458219820Sjeff * SYNOPSIS 459219820Sjeff */ 460219820Sjeffstatic void 461219820Sjeff__osm_sm_mad_ctrl_process_trap(IN osm_sm_mad_ctrl_t * const p_ctrl, 462219820Sjeff IN osm_madw_t * p_madw) 463219820Sjeff{ 464219820Sjeff ib_smp_t *p_smp; 465219820Sjeff cl_status_t status; 466219820Sjeff cl_disp_msgid_t msg_id = CL_DISP_MSGID_NONE; 467219820Sjeff 468219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 469219820Sjeff 470219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 471219820Sjeff 472219820Sjeff /* Make sure OpenSM is master. If not - then we should not process the trap */ 473219820Sjeff if (p_ctrl->p_subn->sm_state != IB_SMINFO_STATE_MASTER) { 474219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 475219820Sjeff "Received trap but OpenSM is not in MASTER state. " 476219820Sjeff "Dropping mad\n"); 477219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 478219820Sjeff goto Exit; 479219820Sjeff } 480219820Sjeff 481219820Sjeff /* 482219820Sjeff Note that attr_id (like the rest of the MAD) is in 483219820Sjeff network byte order. 484219820Sjeff */ 485219820Sjeff switch (p_smp->attr_id) { 486219820Sjeff case IB_MAD_ATTR_NOTICE: 487219820Sjeff msg_id = OSM_MSG_MAD_NOTICE; 488219820Sjeff break; 489219820Sjeff 490219820Sjeff default: 491219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 492219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3109: " 493219820Sjeff "Unsupported attribute = 0x%X\n", 494219820Sjeff cl_ntoh16(p_smp->attr_id)); 495219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 496219820Sjeff break; 497219820Sjeff } 498219820Sjeff 499219820Sjeff if (msg_id == CL_DISP_MSGID_NONE) { 500219820Sjeff /* 501219820Sjeff There is an unknown MAD attribute type for which there is 502219820Sjeff no recipient. Simply retire the MAD here. 503219820Sjeff */ 504219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 505219820Sjeff goto Exit; 506219820Sjeff } 507219820Sjeff 508219820Sjeff /* 509219820Sjeff Post this MAD to the dispatcher for asynchronous 510219820Sjeff processing by the appropriate controller. 511219820Sjeff */ 512219820Sjeff 513219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "Posting Dispatcher message %s\n", 514219820Sjeff osm_get_disp_msg_str(msg_id)); 515219820Sjeff 516219820Sjeff status = cl_disp_post(p_ctrl->h_disp, msg_id, p_madw, 517219820Sjeff __osm_sm_mad_ctrl_disp_done_callback, p_ctrl); 518219820Sjeff 519219820Sjeff if (status != CL_SUCCESS) { 520219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3110: " 521219820Sjeff "Dispatcher post message failed (%s)\n", 522219820Sjeff CL_STATUS_MSG(status)); 523219820Sjeff goto Exit; 524219820Sjeff } 525219820Sjeff 526219820SjeffExit: 527219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 528219820Sjeff} 529219820Sjeff 530219820Sjeff/* 531219820Sjeff * PARAMETERS 532219820Sjeff * 533219820Sjeff * RETURN VALUES 534219820Sjeff * 535219820Sjeff * NOTES 536219820Sjeff * 537219820Sjeff * SEE ALSO 538219820Sjeff *********/ 539219820Sjeff 540219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_rcv_callback 541219820Sjeff * NAME 542219820Sjeff * __osm_sm_mad_ctrl_rcv_callback 543219820Sjeff * 544219820Sjeff * DESCRIPTION 545219820Sjeff * This is the callback from the transport layer for received MADs. 546219820Sjeff * 547219820Sjeff * SYNOPSIS 548219820Sjeff */ 549219820Sjeffstatic void 550219820Sjeff__osm_sm_mad_ctrl_rcv_callback(IN osm_madw_t * p_madw, 551219820Sjeff IN void *bind_context, 552219820Sjeff IN osm_madw_t * p_req_madw) 553219820Sjeff{ 554219820Sjeff osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context; 555219820Sjeff ib_smp_t *p_smp; 556219820Sjeff ib_net16_t status; 557219820Sjeff 558219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 559219820Sjeff 560219820Sjeff CL_ASSERT(p_madw); 561219820Sjeff 562219820Sjeff /* 563219820Sjeff A MAD was received from the wire, possibly in response to a request. 564219820Sjeff */ 565219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd); 566219820Sjeff 567219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, "%u QP0 MADs received\n", 568219820Sjeff p_ctrl->p_stats->qp0_mads_rcvd); 569219820Sjeff 570219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 571219820Sjeff 572219820Sjeff /* if we are closing down simply do nothing */ 573219820Sjeff if (osm_exit_flag) { 574219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, 575219820Sjeff "Ignoring received mad - since we are exiting\n"); 576219820Sjeff 577219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_DEBUG); 578219820Sjeff 579219820Sjeff /* retire the mad or put it back */ 580219820Sjeff if (ib_smp_is_response(p_smp) || 581219820Sjeff (p_smp->method == IB_MAD_METHOD_TRAP_REPRESS)) { 582219820Sjeff CL_ASSERT(p_madw->resp_expected == FALSE); 583219820Sjeff __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 584219820Sjeff } else if (p_madw->resp_expected == TRUE) 585219820Sjeff __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 586219820Sjeff else 587219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 588219820Sjeff 589219820Sjeff goto Exit; 590219820Sjeff } 591219820Sjeff 592219820Sjeff if (osm_log_is_active(p_ctrl->p_log, OSM_LOG_FRAMES)) 593219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_FRAMES); 594219820Sjeff 595219820Sjeff if (p_smp->mgmt_class == IB_MCLASS_SUBN_DIR) 596219820Sjeff status = ib_smp_get_status(p_smp); 597219820Sjeff else 598219820Sjeff status = p_smp->status; 599219820Sjeff 600219820Sjeff if (status != 0) { 601219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3111: " 602219820Sjeff "Error status = 0x%X\n", status); 603219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 604219820Sjeff } 605219820Sjeff 606219820Sjeff switch (p_smp->method) { 607219820Sjeff case IB_MAD_METHOD_GET_RESP: 608219820Sjeff CL_ASSERT(p_req_madw != NULL); 609219820Sjeff __osm_sm_mad_ctrl_process_get_resp(p_ctrl, p_madw, p_req_madw); 610219820Sjeff break; 611219820Sjeff 612219820Sjeff case IB_MAD_METHOD_GET: 613219820Sjeff CL_ASSERT(p_req_madw == NULL); 614219820Sjeff __osm_sm_mad_ctrl_process_get(p_ctrl, p_madw); 615219820Sjeff break; 616219820Sjeff 617219820Sjeff case IB_MAD_METHOD_TRAP: 618219820Sjeff CL_ASSERT(p_req_madw == NULL); 619219820Sjeff __osm_sm_mad_ctrl_process_trap(p_ctrl, p_madw); 620219820Sjeff break; 621219820Sjeff 622219820Sjeff case IB_MAD_METHOD_SET: 623219820Sjeff CL_ASSERT(p_req_madw == NULL); 624219820Sjeff __osm_sm_mad_ctrl_process_set(p_ctrl, p_madw); 625219820Sjeff break; 626219820Sjeff 627219820Sjeff case IB_MAD_METHOD_SEND: 628219820Sjeff case IB_MAD_METHOD_REPORT: 629219820Sjeff case IB_MAD_METHOD_REPORT_RESP: 630219820Sjeff case IB_MAD_METHOD_TRAP_REPRESS: 631219820Sjeff default: 632219820Sjeff cl_atomic_inc(&p_ctrl->p_stats->qp0_mads_rcvd_unknown); 633219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3112: " 634219820Sjeff "Unsupported method = 0x%X\n", p_smp->method); 635219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, p_smp, OSM_LOG_ERROR); 636219820Sjeff osm_mad_pool_put(p_ctrl->p_mad_pool, p_madw); 637219820Sjeff goto Exit; 638219820Sjeff } 639219820Sjeff 640219820SjeffExit: 641219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 642219820Sjeff} 643219820Sjeff 644219820Sjeff/* 645219820Sjeff * PARAMETERS 646219820Sjeff * 647219820Sjeff * RETURN VALUES 648219820Sjeff * 649219820Sjeff * NOTES 650219820Sjeff * 651219820Sjeff * SEE ALSO 652219820Sjeff *********/ 653219820Sjeff 654219820Sjeff/****f* opensm: SM/__osm_sm_mad_ctrl_send_err_cb 655219820Sjeff * NAME 656219820Sjeff * __osm_sm_mad_ctrl_send_err_cb 657219820Sjeff * 658219820Sjeff * DESCRIPTION 659219820Sjeff * This is the callback from the transport layer for send errors 660219820Sjeff * on MADs that were expecting a response. 661219820Sjeff * 662219820Sjeff * SYNOPSIS 663219820Sjeff */ 664219820Sjeffstatic void 665219820Sjeff__osm_sm_mad_ctrl_send_err_cb(IN void *bind_context, IN osm_madw_t * p_madw) 666219820Sjeff{ 667219820Sjeff osm_sm_mad_ctrl_t *p_ctrl = (osm_sm_mad_ctrl_t *) bind_context; 668219820Sjeff ib_api_status_t status; 669219820Sjeff ib_smp_t *p_smp; 670219820Sjeff 671219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 672219820Sjeff 673219820Sjeff CL_ASSERT(p_madw); 674219820Sjeff 675219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3113: " 676219820Sjeff "MAD completed in error (%s)\n", 677219820Sjeff ib_get_err_str(p_madw->status)); 678219820Sjeff 679219820Sjeff /* 680219820Sjeff If this was a SubnSet MAD, then this error might indicate a problem 681219820Sjeff in configuring the subnet. In this case - need to mark that there was 682219820Sjeff such a problem. The subnet will not be up, and the next sweep should 683219820Sjeff be a heavy sweep as well. 684219820Sjeff */ 685219820Sjeff p_smp = osm_madw_get_smp_ptr(p_madw); 686219820Sjeff if (p_smp->method == IB_MAD_METHOD_SET && 687219820Sjeff (p_smp->attr_id == IB_MAD_ATTR_PORT_INFO || 688219820Sjeff p_smp->attr_id == IB_MAD_ATTR_MCAST_FWD_TBL || 689219820Sjeff p_smp->attr_id == IB_MAD_ATTR_SWITCH_INFO || 690219820Sjeff p_smp->attr_id == IB_MAD_ATTR_LIN_FWD_TBL)) { 691219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3119: " 692219820Sjeff "Set method failed\n"); 693219820Sjeff p_ctrl->p_subn->subnet_initialization_error = TRUE; 694219820Sjeff } 695219820Sjeff 696219820Sjeff /* 697219820Sjeff Since we did not get any response we suspect the DR path 698219820Sjeff used for the target port. 699219820Sjeff Find it and replace it with an alternate path. 700219820Sjeff This is true only if the destination lid is not 0xFFFF, since 701219820Sjeff then we are aiming for a specific path and not specific destination 702219820Sjeff lid. 703219820Sjeff */ 704219820Sjeff /* For now - do not add the alternate dr path to the release */ 705219820Sjeff#if 0 706219820Sjeff if (p_madw->mad_addr.dest_lid != 0xFFFF) { 707219820Sjeff osm_physp_t *p_physp = 708219820Sjeff osm_get_physp_by_mad_addr(p_ctrl->p_log, 709219820Sjeff p_ctrl->p_subn, 710219820Sjeff &(p_madw->mad_addr)); 711219820Sjeff if (!p_physp) { 712219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3114: " 713219820Sjeff "Failed to find the corresponding phys port\n"); 714219820Sjeff } else { 715219820Sjeff osm_physp_replace_dr_path_with_alternate_dr_path 716219820Sjeff (p_ctrl->p_log, p_ctrl->p_subn, p_physp, 717219820Sjeff p_madw->h_bind); 718219820Sjeff } 719219820Sjeff } 720219820Sjeff#endif 721219820Sjeff 722219820Sjeff /* 723219820Sjeff An error occurred. No response was received to a request MAD. 724219820Sjeff Retire the original request MAD. 725219820Sjeff */ 726219820Sjeff 727219820Sjeff osm_dump_dr_smp(p_ctrl->p_log, osm_madw_get_smp_ptr(p_madw), 728219820Sjeff OSM_LOG_ERROR); 729219820Sjeff 730219820Sjeff __osm_sm_mad_ctrl_update_wire_stats(p_ctrl); 731219820Sjeff 732219820Sjeff if (osm_madw_get_err_msg(p_madw) != CL_DISP_MSGID_NONE) { 733219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_DEBUG, 734219820Sjeff "Posting Dispatcher message %s\n", 735219820Sjeff osm_get_disp_msg_str(osm_madw_get_err_msg(p_madw))); 736219820Sjeff 737219820Sjeff status = cl_disp_post(p_ctrl->h_disp, 738219820Sjeff osm_madw_get_err_msg(p_madw), 739219820Sjeff p_madw, 740219820Sjeff __osm_sm_mad_ctrl_disp_done_callback, 741219820Sjeff p_ctrl); 742219820Sjeff if (status != CL_SUCCESS) 743219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3115: " 744219820Sjeff "Dispatcher post message failed (%s)\n", 745219820Sjeff CL_STATUS_MSG(status)); 746219820Sjeff } else 747219820Sjeff /* 748219820Sjeff No error message was provided, just retire the MAD. 749219820Sjeff */ 750219820Sjeff __osm_sm_mad_ctrl_retire_trans_mad(p_ctrl, p_madw); 751219820Sjeff 752219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 753219820Sjeff} 754219820Sjeff 755219820Sjeff/* 756219820Sjeff * PARAMETERS 757219820Sjeff * 758219820Sjeff * RETURN VALUES 759219820Sjeff * 760219820Sjeff * NOTES 761219820Sjeff * 762219820Sjeff * SEE ALSO 763219820Sjeff *********/ 764219820Sjeff 765219820Sjeff/********************************************************************** 766219820Sjeff **********************************************************************/ 767219820Sjeffvoid osm_sm_mad_ctrl_construct(IN osm_sm_mad_ctrl_t * const p_ctrl) 768219820Sjeff{ 769219820Sjeff CL_ASSERT(p_ctrl); 770219820Sjeff memset(p_ctrl, 0, sizeof(*p_ctrl)); 771219820Sjeff p_ctrl->h_disp = CL_DISP_INVALID_HANDLE; 772219820Sjeff} 773219820Sjeff 774219820Sjeff/********************************************************************** 775219820Sjeff **********************************************************************/ 776219820Sjeffvoid osm_sm_mad_ctrl_destroy(IN osm_sm_mad_ctrl_t * const p_ctrl) 777219820Sjeff{ 778219820Sjeff CL_ASSERT(p_ctrl); 779219820Sjeff 780219820Sjeff if (p_ctrl->h_bind != CL_DISP_INVALID_HANDLE) 781219820Sjeff osm_vendor_unbind(p_ctrl->h_bind); 782219820Sjeff cl_disp_unregister(p_ctrl->h_disp); 783219820Sjeff} 784219820Sjeff 785219820Sjeff/********************************************************************** 786219820Sjeff **********************************************************************/ 787219820Sjeffib_api_status_t 788219820Sjeffosm_sm_mad_ctrl_init(IN osm_sm_mad_ctrl_t * const p_ctrl, 789219820Sjeff IN osm_subn_t * const p_subn, 790219820Sjeff IN osm_mad_pool_t * const p_mad_pool, 791219820Sjeff IN osm_vl15_t * const p_vl15, 792219820Sjeff IN osm_vendor_t * const p_vendor, 793219820Sjeff IN osm_log_t * const p_log, 794219820Sjeff IN osm_stats_t * const p_stats, 795219820Sjeff IN cl_plock_t * const p_lock, 796219820Sjeff IN cl_dispatcher_t * const p_disp) 797219820Sjeff{ 798219820Sjeff ib_api_status_t status = IB_SUCCESS; 799219820Sjeff 800219820Sjeff OSM_LOG_ENTER(p_log); 801219820Sjeff 802219820Sjeff osm_sm_mad_ctrl_construct(p_ctrl); 803219820Sjeff 804219820Sjeff p_ctrl->p_subn = p_subn; 805219820Sjeff p_ctrl->p_log = p_log; 806219820Sjeff p_ctrl->p_disp = p_disp; 807219820Sjeff p_ctrl->p_mad_pool = p_mad_pool; 808219820Sjeff p_ctrl->p_vendor = p_vendor; 809219820Sjeff p_ctrl->p_stats = p_stats; 810219820Sjeff p_ctrl->p_lock = p_lock; 811219820Sjeff p_ctrl->p_vl15 = p_vl15; 812219820Sjeff 813219820Sjeff p_ctrl->h_disp = cl_disp_register(p_disp, 814219820Sjeff CL_DISP_MSGID_NONE, NULL, NULL); 815219820Sjeff 816219820Sjeff if (p_ctrl->h_disp == CL_DISP_INVALID_HANDLE) { 817219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 3116: " 818219820Sjeff "Dispatcher registration failed\n"); 819219820Sjeff status = IB_INSUFFICIENT_RESOURCES; 820219820Sjeff goto Exit; 821219820Sjeff } 822219820Sjeff 823219820SjeffExit: 824219820Sjeff OSM_LOG_EXIT(p_log); 825219820Sjeff return (status); 826219820Sjeff} 827219820Sjeff 828219820Sjeff/********************************************************************** 829219820Sjeff **********************************************************************/ 830219820Sjeffib_api_status_t 831219820Sjeffosm_sm_mad_ctrl_bind(IN osm_sm_mad_ctrl_t * const p_ctrl, 832219820Sjeff IN const ib_net64_t port_guid) 833219820Sjeff{ 834219820Sjeff osm_bind_info_t bind_info; 835219820Sjeff ib_api_status_t status = IB_SUCCESS; 836219820Sjeff 837219820Sjeff OSM_LOG_ENTER(p_ctrl->p_log); 838219820Sjeff 839219820Sjeff if (p_ctrl->h_bind != OSM_BIND_INVALID_HANDLE) { 840219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3117: " 841219820Sjeff "Multiple binds not allowed\n"); 842219820Sjeff status = IB_ERROR; 843219820Sjeff goto Exit; 844219820Sjeff } 845219820Sjeff 846219820Sjeff bind_info.class_version = 1; 847219820Sjeff bind_info.is_report_processor = FALSE; 848219820Sjeff bind_info.is_responder = TRUE; 849219820Sjeff bind_info.is_trap_processor = TRUE; 850219820Sjeff bind_info.mad_class = IB_MCLASS_SUBN_DIR; 851219820Sjeff bind_info.port_guid = port_guid; 852219820Sjeff bind_info.recv_q_size = OSM_SM_DEFAULT_QP0_RCV_SIZE; 853219820Sjeff bind_info.send_q_size = OSM_SM_DEFAULT_QP0_SEND_SIZE; 854219820Sjeff 855219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_VERBOSE, 856219820Sjeff "Binding to port 0x%" PRIx64 "\n", cl_ntoh64(port_guid)); 857219820Sjeff 858219820Sjeff p_ctrl->h_bind = osm_vendor_bind(p_ctrl->p_vendor, 859219820Sjeff &bind_info, 860219820Sjeff p_ctrl->p_mad_pool, 861219820Sjeff __osm_sm_mad_ctrl_rcv_callback, 862219820Sjeff __osm_sm_mad_ctrl_send_err_cb, p_ctrl); 863219820Sjeff 864219820Sjeff if (p_ctrl->h_bind == OSM_BIND_INVALID_HANDLE) { 865219820Sjeff status = IB_ERROR; 866219820Sjeff OSM_LOG(p_ctrl->p_log, OSM_LOG_ERROR, "ERR 3118: " 867219820Sjeff "Vendor specific bind failed\n"); 868219820Sjeff goto Exit; 869219820Sjeff } 870219820Sjeff 871219820SjeffExit: 872219820Sjeff OSM_LOG_EXIT(p_ctrl->p_log); 873219820Sjeff return (status); 874219820Sjeff} 875