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_infr_rcv_t. 39219820Sjeff * This object represents the InformInfo Receiver 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 <iba/ib_types.h> 49219820Sjeff#include <arpa/inet.h> 50219820Sjeff#include <complib/cl_qmap.h> 51219820Sjeff#include <complib/cl_passivelock.h> 52219820Sjeff#include <complib/cl_debug.h> 53219820Sjeff#include <complib/cl_qlist.h> 54219820Sjeff#include <vendor/osm_vendor_api.h> 55219820Sjeff#include <opensm/osm_port.h> 56219820Sjeff#include <opensm/osm_node.h> 57219820Sjeff#include <opensm/osm_switch.h> 58219820Sjeff#include <opensm/osm_helper.h> 59219820Sjeff#include <opensm/osm_sa.h> 60219820Sjeff#include <opensm/osm_inform.h> 61219820Sjeff#include <opensm/osm_pkey.h> 62219820Sjeff 63219820Sjeff#include <sys/socket.h> 64219820Sjeff 65219820Sjefftypedef struct osm_iir_item { 66219820Sjeff cl_list_item_t list_item; 67219820Sjeff ib_inform_info_record_t rec; 68219820Sjeff} osm_iir_item_t; 69219820Sjeff 70219820Sjefftypedef struct osm_iir_search_ctxt { 71219820Sjeff const ib_inform_info_record_t *p_rcvd_rec; 72219820Sjeff ib_net64_t comp_mask; 73219820Sjeff cl_qlist_t *p_list; 74219820Sjeff ib_gid_t subscriber_gid; 75219820Sjeff ib_net16_t subscriber_enum; 76219820Sjeff osm_sa_t *sa; 77219820Sjeff osm_physp_t *p_req_physp; 78219820Sjeff} osm_iir_search_ctxt_t; 79219820Sjeff 80219820Sjeff/********************************************************************** 81219820Sjeffo13-14.1.1: Except for Set(InformInfo) requests with Inform- 82219820SjeffInfo:LIDRangeBegin=0xFFFF, managers that support event forwarding 83219820Sjeffshall, upon receiving a Set(InformInfo), verify that the requester 84219820Sjefforiginating the Set(InformInfo) and a Trap() source identified by Inform- 85219820Sjeffcan access each other - can use path record to verify that. 86219820Sjeff**********************************************************************/ 87219820Sjeffstatic boolean_t 88219820Sjeff__validate_ports_access_rights(IN osm_sa_t * sa, 89219820Sjeff IN osm_infr_t * p_infr_rec) 90219820Sjeff{ 91219820Sjeff boolean_t valid = TRUE; 92219820Sjeff osm_physp_t *p_requester_physp; 93219820Sjeff osm_port_t *p_port; 94219820Sjeff osm_physp_t *p_physp; 95219820Sjeff ib_net64_t portguid; 96219820Sjeff ib_net16_t lid_range_begin; 97219820Sjeff ib_net16_t lid_range_end; 98219820Sjeff ib_net16_t lid; 99219820Sjeff const cl_ptr_vector_t *p_tbl; 100219820Sjeff ib_gid_t zero_gid; 101219820Sjeff 102219820Sjeff OSM_LOG_ENTER(sa->p_log); 103219820Sjeff 104219820Sjeff /* get the requester physp from the request address */ 105219820Sjeff p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 106219820Sjeff &p_infr_rec->report_addr); 107219820Sjeff 108219820Sjeff memset(&zero_gid, 0, sizeof(zero_gid)); 109219820Sjeff if (memcmp(&(p_infr_rec->inform_record.inform_info.gid), 110219820Sjeff &zero_gid, sizeof(ib_gid_t))) { 111219820Sjeff /* a gid is defined */ 112219820Sjeff portguid = 113219820Sjeff p_infr_rec->inform_record.inform_info.gid.unicast. 114219820Sjeff interface_id; 115219820Sjeff 116219820Sjeff p_port = osm_get_port_by_guid(sa->p_subn, portguid); 117219820Sjeff 118219820Sjeff if (p_port == NULL) { 119219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: " 120219820Sjeff "Invalid port guid: 0x%016" PRIx64 "\n", 121219820Sjeff cl_ntoh64(portguid)); 122219820Sjeff valid = FALSE; 123219820Sjeff goto Exit; 124219820Sjeff } 125219820Sjeff 126219820Sjeff /* get the destination InformInfo physical port */ 127219820Sjeff p_physp = p_port->p_physp; 128219820Sjeff 129219820Sjeff /* make sure that the requester and destination port can access each other 130219820Sjeff according to the current partitioning. */ 131219820Sjeff if (!osm_physp_share_pkey 132219820Sjeff (sa->p_log, p_physp, p_requester_physp)) { 133219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 134219820Sjeff "port and requester don't share pkey\n"); 135219820Sjeff valid = FALSE; 136219820Sjeff goto Exit; 137219820Sjeff } 138219820Sjeff } else { 139219820Sjeff /* gid is zero - check if LID range is defined */ 140219820Sjeff lid_range_begin = 141219820Sjeff cl_ntoh16(p_infr_rec->inform_record.inform_info. 142219820Sjeff lid_range_begin); 143219820Sjeff /* if lid is 0xFFFF - meaning all endports managed by the manager */ 144219820Sjeff if (lid_range_begin == 0xFFFF) 145219820Sjeff goto Exit; 146219820Sjeff 147219820Sjeff lid_range_end = 148219820Sjeff cl_ntoh16(p_infr_rec->inform_record.inform_info. 149219820Sjeff lid_range_end); 150219820Sjeff 151219820Sjeff /* lid_range_end is set to zero if no range desired. In this case - 152219820Sjeff just make it equal to the lid_range_begin. */ 153219820Sjeff if (lid_range_end == 0) 154219820Sjeff lid_range_end = lid_range_begin; 155219820Sjeff 156219820Sjeff /* go over all defined lids within the range and make sure that the 157219820Sjeff requester port can access them according to current partitioning. */ 158219820Sjeff for (lid = lid_range_begin; lid <= lid_range_end; lid++) { 159219820Sjeff p_tbl = &sa->p_subn->port_lid_tbl; 160219820Sjeff if (cl_ptr_vector_get_size(p_tbl) > lid) 161219820Sjeff p_port = cl_ptr_vector_get(p_tbl, lid); 162219820Sjeff else { 163219820Sjeff /* lid requested is out of range */ 164219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4302: " 165219820Sjeff "Given LID (%u) is out of range:%u\n", 166219820Sjeff lid, cl_ptr_vector_get_size(p_tbl)); 167219820Sjeff valid = FALSE; 168219820Sjeff goto Exit; 169219820Sjeff } 170219820Sjeff if (p_port == NULL) 171219820Sjeff continue; 172219820Sjeff 173219820Sjeff p_physp = p_port->p_physp; 174219820Sjeff /* make sure that the requester and destination port can access 175219820Sjeff each other according to the current partitioning. */ 176219820Sjeff if (!osm_physp_share_pkey 177219820Sjeff (sa->p_log, p_physp, p_requester_physp)) { 178219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 179219820Sjeff "port and requester don't share pkey\n"); 180219820Sjeff valid = FALSE; 181219820Sjeff goto Exit; 182219820Sjeff } 183219820Sjeff } 184219820Sjeff } 185219820Sjeff 186219820SjeffExit: 187219820Sjeff OSM_LOG_EXIT(sa->p_log); 188219820Sjeff return valid; 189219820Sjeff} 190219820Sjeff 191219820Sjeff/********************************************************************** 192219820Sjeff **********************************************************************/ 193219820Sjeffstatic boolean_t 194219820Sjeff__validate_infr(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec) 195219820Sjeff{ 196219820Sjeff boolean_t valid = TRUE; 197219820Sjeff 198219820Sjeff OSM_LOG_ENTER(sa->p_log); 199219820Sjeff 200219820Sjeff valid = __validate_ports_access_rights(sa, p_infr_rec); 201219820Sjeff if (!valid) { 202219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 203219820Sjeff "Invalid Access for InformInfo\n"); 204219820Sjeff valid = FALSE; 205219820Sjeff } 206219820Sjeff 207219820Sjeff OSM_LOG_EXIT(sa->p_log); 208219820Sjeff return valid; 209219820Sjeff} 210219820Sjeff 211219820Sjeff/********************************************************************** 212219820Sjeffo13-12.1.1: Confirm a valid request for event subscription by responding 213219820Sjeffwith an InformInfo attribute that is a copy of the data in the 214219820SjeffSet(InformInfo) request. 215219820Sjeff**********************************************************************/ 216219820Sjeffstatic void 217219820Sjeff__osm_infr_rcv_respond(IN osm_sa_t * sa, 218219820Sjeff IN osm_madw_t * const p_madw) 219219820Sjeff{ 220219820Sjeff cl_qlist_t rec_list; 221219820Sjeff osm_iir_item_t *item; 222219820Sjeff 223219820Sjeff OSM_LOG_ENTER(sa->p_log); 224219820Sjeff 225219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 226219820Sjeff "Generating successful InformInfo response\n"); 227219820Sjeff 228219820Sjeff item = malloc(sizeof(*item)); 229219820Sjeff if (!item) { 230219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4303: " 231219820Sjeff "rec_item alloc failed\n"); 232219820Sjeff goto Exit; 233219820Sjeff } 234219820Sjeff 235219820Sjeff memcpy(&item->rec, 236219820Sjeff ib_sa_mad_get_payload_ptr(osm_madw_get_sa_mad_ptr(p_madw)), 237219820Sjeff sizeof(item->rec)); 238219820Sjeff 239219820Sjeff cl_qlist_init(&rec_list); 240219820Sjeff cl_qlist_insert_tail(&rec_list, &item->list_item); 241219820Sjeff 242219820Sjeff osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_t), &rec_list); 243219820Sjeff 244219820SjeffExit: 245219820Sjeff OSM_LOG_EXIT(sa->p_log); 246219820Sjeff} 247219820Sjeff 248219820Sjeff/********************************************************************** 249219820Sjeff **********************************************************************/ 250219820Sjeffstatic void 251219820Sjeff__osm_sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa, 252219820Sjeff IN const osm_infr_t * const p_infr, 253219820Sjeff osm_iir_search_ctxt_t * const p_ctxt) 254219820Sjeff{ 255219820Sjeff const ib_inform_info_record_t *p_rcvd_rec = NULL; 256219820Sjeff ib_net64_t comp_mask; 257219820Sjeff ib_net64_t portguid; 258219820Sjeff osm_port_t *p_subscriber_port; 259219820Sjeff osm_physp_t *p_subscriber_physp; 260219820Sjeff const osm_physp_t *p_req_physp; 261219820Sjeff osm_iir_item_t *p_rec_item; 262219820Sjeff 263219820Sjeff OSM_LOG_ENTER(sa->p_log); 264219820Sjeff 265219820Sjeff p_rcvd_rec = p_ctxt->p_rcvd_rec; 266219820Sjeff comp_mask = p_ctxt->comp_mask; 267219820Sjeff p_req_physp = p_ctxt->p_req_physp; 268219820Sjeff 269219820Sjeff if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID && 270219820Sjeff memcmp(&p_infr->inform_record.subscriber_gid, 271219820Sjeff &p_ctxt->subscriber_gid, 272219820Sjeff sizeof(p_infr->inform_record.subscriber_gid))) 273219820Sjeff goto Exit; 274219820Sjeff 275219820Sjeff if (comp_mask & IB_IIR_COMPMASK_ENUM && 276219820Sjeff p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum) 277219820Sjeff goto Exit; 278219820Sjeff 279219820Sjeff /* Implement any other needed search cases */ 280219820Sjeff 281219820Sjeff /* Ensure pkey is shared before returning any records */ 282219820Sjeff portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id; 283219820Sjeff p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid); 284219820Sjeff if (p_subscriber_port == NULL) { 285219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: " 286219820Sjeff "Invalid subscriber port guid: 0x%016" PRIx64 "\n", 287219820Sjeff cl_ntoh64(portguid)); 288219820Sjeff goto Exit; 289219820Sjeff } 290219820Sjeff 291219820Sjeff /* get the subscriber InformInfo physical port */ 292219820Sjeff p_subscriber_physp = p_subscriber_port->p_physp; 293219820Sjeff /* make sure that the requester and subscriber port can access each other 294219820Sjeff according to the current partitioning. */ 295219820Sjeff if (!osm_physp_share_pkey 296219820Sjeff (sa->p_log, p_req_physp, p_subscriber_physp)) { 297219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 298219820Sjeff "requester and subscriber ports don't share pkey\n"); 299219820Sjeff goto Exit; 300219820Sjeff } 301219820Sjeff 302219820Sjeff p_rec_item = malloc(sizeof(*p_rec_item)); 303219820Sjeff if (p_rec_item == NULL) { 304219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: " 305219820Sjeff "rec_item alloc failed\n"); 306219820Sjeff goto Exit; 307219820Sjeff } 308219820Sjeff 309219820Sjeff memcpy((void *)&p_rec_item->rec, (void *)&p_infr->inform_record, 310219820Sjeff sizeof(ib_inform_info_record_t)); 311219820Sjeff cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); 312219820Sjeff 313219820SjeffExit: 314219820Sjeff OSM_LOG_EXIT(sa->p_log); 315219820Sjeff} 316219820Sjeff 317219820Sjeff/********************************************************************** 318219820Sjeff **********************************************************************/ 319219820Sjeffstatic void 320219820Sjeff__osm_sa_inform_info_rec_by_comp_mask_cb(IN cl_list_item_t * const p_list_item, 321219820Sjeff IN void *context) 322219820Sjeff{ 323219820Sjeff const osm_infr_t *const p_infr = (osm_infr_t *) p_list_item; 324219820Sjeff osm_iir_search_ctxt_t *const p_ctxt = (osm_iir_search_ctxt_t *) context; 325219820Sjeff 326219820Sjeff __osm_sa_inform_info_rec_by_comp_mask(p_ctxt->sa, p_infr, p_ctxt); 327219820Sjeff} 328219820Sjeff 329219820Sjeff/********************************************************************** 330219820SjeffReceived a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD 331219820Sjeff**********************************************************************/ 332219820Sjeffstatic void 333219820Sjeffosm_infr_rcv_process_get_method(IN osm_sa_t * sa, 334219820Sjeff IN osm_madw_t * const p_madw) 335219820Sjeff{ 336219820Sjeff char gid_str[INET6_ADDRSTRLEN]; 337219820Sjeff ib_sa_mad_t *p_rcvd_mad; 338219820Sjeff const ib_inform_info_record_t *p_rcvd_rec; 339219820Sjeff cl_qlist_t rec_list; 340219820Sjeff osm_iir_search_ctxt_t context; 341219820Sjeff osm_physp_t *p_req_physp; 342219820Sjeff osm_iir_item_t *item; 343219820Sjeff 344219820Sjeff OSM_LOG_ENTER(sa->p_log); 345219820Sjeff 346219820Sjeff CL_ASSERT(p_madw); 347219820Sjeff p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); 348219820Sjeff p_rcvd_rec = 349219820Sjeff (ib_inform_info_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); 350219820Sjeff 351219820Sjeff /* update the requester physical port. */ 352219820Sjeff p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 353219820Sjeff osm_madw_get_mad_addr_ptr 354219820Sjeff (p_madw)); 355219820Sjeff if (p_req_physp == NULL) { 356219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4309: " 357219820Sjeff "Cannot find requester physical port\n"); 358219820Sjeff goto Exit; 359219820Sjeff } 360219820Sjeff 361219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 362219820Sjeff osm_dump_inform_info_record(sa->p_log, p_rcvd_rec, 363219820Sjeff OSM_LOG_DEBUG); 364219820Sjeff 365219820Sjeff cl_qlist_init(&rec_list); 366219820Sjeff 367219820Sjeff context.p_rcvd_rec = p_rcvd_rec; 368219820Sjeff context.p_list = &rec_list; 369219820Sjeff context.comp_mask = p_rcvd_mad->comp_mask; 370219820Sjeff context.subscriber_gid = p_rcvd_rec->subscriber_gid; 371219820Sjeff context.subscriber_enum = p_rcvd_rec->subscriber_enum; 372219820Sjeff context.sa = sa; 373219820Sjeff context.p_req_physp = p_req_physp; 374219820Sjeff 375219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 376219820Sjeff "Query Subscriber GID:%s(%02X) Enum:0x%X(%02X)\n", 377219820Sjeff inet_ntop(AF_INET6, p_rcvd_rec->subscriber_gid.raw, 378219820Sjeff gid_str, sizeof gid_str), 379219820Sjeff (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0, 380219820Sjeff cl_ntoh16(p_rcvd_rec->subscriber_enum), 381219820Sjeff (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0); 382219820Sjeff 383219820Sjeff cl_plock_acquire(sa->p_lock); 384219820Sjeff 385219820Sjeff cl_qlist_apply_func(&sa->p_subn->sa_infr_list, 386219820Sjeff __osm_sa_inform_info_rec_by_comp_mask_cb, &context); 387219820Sjeff 388219820Sjeff cl_plock_release(sa->p_lock); 389219820Sjeff 390219820Sjeff /* clear reserved and pad fields in InformInfoRecord */ 391219820Sjeff for (item = (osm_iir_item_t *) cl_qlist_head(&rec_list); 392219820Sjeff item != (osm_iir_item_t *) cl_qlist_end(&rec_list); 393219820Sjeff item = (osm_iir_item_t *)cl_qlist_next(&item->list_item)) { 394219820Sjeff memset(item->rec.reserved, 0, sizeof(item->rec.reserved)); 395219820Sjeff memset(item->rec.pad, 0, sizeof(item->rec.pad)); 396219820Sjeff } 397219820Sjeff 398219820Sjeff osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_record_t), &rec_list); 399219820Sjeff 400219820SjeffExit: 401219820Sjeff OSM_LOG_EXIT(sa->p_log); 402219820Sjeff} 403219820Sjeff 404219820Sjeff/********************************************************************* 405219820SjeffReceived a Set(InformInfo) MAD 406219820Sjeff**********************************************************************/ 407219820Sjeffstatic void 408219820Sjeffosm_infr_rcv_process_set_method(IN osm_sa_t * sa, 409219820Sjeff IN osm_madw_t * const p_madw) 410219820Sjeff{ 411219820Sjeff ib_sa_mad_t *p_sa_mad; 412219820Sjeff ib_inform_info_t *p_recvd_inform_info; 413219820Sjeff osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ 414219820Sjeff osm_infr_t *p_infr; 415219820Sjeff ib_net32_t qpn; 416219820Sjeff uint8_t resp_time_val; 417219820Sjeff ib_api_status_t res; 418219820Sjeff 419219820Sjeff OSM_LOG_ENTER(sa->p_log); 420219820Sjeff 421219820Sjeff CL_ASSERT(p_madw); 422219820Sjeff 423219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 424219820Sjeff p_recvd_inform_info = 425219820Sjeff (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 426219820Sjeff 427219820Sjeff#if 0 428219820Sjeff if (osm_log_is_active(sa->p_log, OSM_LOG_DEBUG)) 429219820Sjeff osm_dump_inform_info(sa->p_log, p_recvd_inform_info, 430219820Sjeff OSM_LOG_DEBUG); 431219820Sjeff#endif 432219820Sjeff 433219820Sjeff /* Grab the lock */ 434219820Sjeff cl_plock_excl_acquire(sa->p_lock); 435219820Sjeff 436219820Sjeff /* define the inform record */ 437219820Sjeff inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; 438219820Sjeff 439219820Sjeff /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ 440219820Sjeff inform_info_rec.report_addr = p_madw->mad_addr; 441219820Sjeff 442219820Sjeff /* we will need to know the mad srvc to send back through */ 443219820Sjeff inform_info_rec.h_bind = p_madw->h_bind; 444219820Sjeff inform_info_rec.sa = sa; 445219820Sjeff 446219820Sjeff /* update the subscriber GID according to mad address */ 447219820Sjeff res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr, 448219820Sjeff &inform_info_rec.inform_record. 449219820Sjeff subscriber_gid); 450219820Sjeff if (res != IB_SUCCESS) { 451219820Sjeff cl_plock_release(sa->p_lock); 452219820Sjeff 453219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " 454219820Sjeff "Subscribe Request from unknown LID: %u\n", 455219820Sjeff cl_ntoh16(p_madw->mad_addr.dest_lid)); 456219820Sjeff osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 457219820Sjeff goto Exit; 458219820Sjeff } 459219820Sjeff 460219820Sjeff /* HACK: enum is always 0 (currently) */ 461219820Sjeff inform_info_rec.inform_record.subscriber_enum = 0; 462219820Sjeff 463219820Sjeff /* Subscribe values above 1 are undefined */ 464219820Sjeff if (p_recvd_inform_info->subscribe > 1) { 465219820Sjeff cl_plock_release(sa->p_lock); 466219820Sjeff 467219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308 " 468219820Sjeff "Invalid subscribe: %d\n", 469219820Sjeff p_recvd_inform_info->subscribe); 470219820Sjeff osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 471219820Sjeff goto Exit; 472219820Sjeff } 473219820Sjeff 474219820Sjeff /* 475219820Sjeff * MODIFICATIONS DONE ON INCOMING REQUEST: 476219820Sjeff * 477219820Sjeff * QPN: 478219820Sjeff * Internally we keep the QPN field of the InformInfo updated 479219820Sjeff * so we can simply compare it in the record - when finding such. 480219820Sjeff */ 481219820Sjeff if (p_recvd_inform_info->subscribe) { 482219820Sjeff ib_inform_info_set_qpn(&inform_info_rec.inform_record. 483219820Sjeff inform_info, 484219820Sjeff inform_info_rec.report_addr.addr_type. 485219820Sjeff gsi.remote_qp); 486219820Sjeff 487219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 488219820Sjeff "Subscribe Request with QPN: 0x%06X\n", 489219820Sjeff cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi. 490219820Sjeff remote_qp)); 491219820Sjeff } else { 492219820Sjeff ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v. 493219820Sjeff generic.qpn_resp_time_val, 494219820Sjeff &qpn, &resp_time_val); 495219820Sjeff 496219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 497219820Sjeff "UnSubscribe Request with QPN: 0x%06X\n", 498219820Sjeff cl_ntoh32(qpn)); 499219820Sjeff } 500219820Sjeff 501219820Sjeff /* If record exists with matching InformInfo */ 502219820Sjeff p_infr = 503219820Sjeff osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec); 504219820Sjeff 505219820Sjeff /* check to see if the request was for subscribe */ 506219820Sjeff if (p_recvd_inform_info->subscribe) { 507219820Sjeff /* validate the request for a new or update InformInfo */ 508219820Sjeff if (__validate_infr(sa, &inform_info_rec) != TRUE) { 509219820Sjeff cl_plock_release(sa->p_lock); 510219820Sjeff 511219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: " 512219820Sjeff "Failed to validate a new inform object\n"); 513219820Sjeff 514219820Sjeff /* o13-13.1.1: we need to set the subscribe bit to 0 */ 515219820Sjeff p_recvd_inform_info->subscribe = 0; 516219820Sjeff osm_sa_send_error(sa, p_madw, 517219820Sjeff IB_SA_MAD_STATUS_REQ_INVALID); 518219820Sjeff goto Exit; 519219820Sjeff } 520219820Sjeff 521219820Sjeff /* ok - we can try and create a new entry */ 522219820Sjeff if (p_infr == NULL) { 523219820Sjeff /* Create the instance of the osm_infr_t object */ 524219820Sjeff p_infr = osm_infr_new(&inform_info_rec); 525219820Sjeff if (p_infr == NULL) { 526219820Sjeff cl_plock_release(sa->p_lock); 527219820Sjeff 528219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: " 529219820Sjeff "Failed to create a new inform object\n"); 530219820Sjeff 531219820Sjeff /* o13-13.1.1: we need to set the subscribe bit to 0 */ 532219820Sjeff p_recvd_inform_info->subscribe = 0; 533219820Sjeff osm_sa_send_error(sa, p_madw, 534219820Sjeff IB_SA_MAD_STATUS_NO_RESOURCES); 535219820Sjeff goto Exit; 536219820Sjeff } 537219820Sjeff 538219820Sjeff /* Add this new osm_infr_t object to subnet object */ 539219820Sjeff osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr); 540219820Sjeff } else 541219820Sjeff /* Update the old instance of the osm_infr_t object */ 542219820Sjeff p_infr->inform_record = inform_info_rec.inform_record; 543219820Sjeff /* We got an UnSubscribe request */ 544219820Sjeff } else if (p_infr == NULL) { 545219820Sjeff cl_plock_release(sa->p_lock); 546219820Sjeff 547219820Sjeff /* No Such Item - So Error */ 548219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: " 549219820Sjeff "Failed to UnSubscribe to non existing inform object\n"); 550219820Sjeff 551219820Sjeff /* o13-13.1.1: we need to set the subscribe bit to 0 */ 552219820Sjeff p_recvd_inform_info->subscribe = 0; 553219820Sjeff osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 554219820Sjeff goto Exit; 555219820Sjeff } else 556219820Sjeff /* Delete this object from the subnet list of informs */ 557219820Sjeff osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr); 558219820Sjeff 559219820Sjeff cl_plock_release(sa->p_lock); 560219820Sjeff 561219820Sjeff /* send the success response */ 562219820Sjeff __osm_infr_rcv_respond(sa, p_madw); 563219820Sjeff 564219820SjeffExit: 565219820Sjeff OSM_LOG_EXIT(sa->p_log); 566219820Sjeff} 567219820Sjeff 568219820Sjeff/********************************************************************* 569219820Sjeff**********************************************************************/ 570219820Sjeffvoid osm_infr_rcv_process(IN void *context, IN void *data) 571219820Sjeff{ 572219820Sjeff osm_sa_t *sa = context; 573219820Sjeff osm_madw_t *p_madw = data; 574219820Sjeff ib_sa_mad_t *p_sa_mad; 575219820Sjeff 576219820Sjeff OSM_LOG_ENTER(sa->p_log); 577219820Sjeff 578219820Sjeff CL_ASSERT(p_madw); 579219820Sjeff 580219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 581219820Sjeff 582219820Sjeff CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO); 583219820Sjeff 584219820Sjeff if (p_sa_mad->method != IB_MAD_METHOD_SET) { 585219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 586219820Sjeff "Unsupported Method (%s)\n", 587219820Sjeff ib_get_sa_method_str(p_sa_mad->method)); 588219820Sjeff osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 589219820Sjeff goto Exit; 590219820Sjeff } 591219820Sjeff 592219820Sjeff osm_infr_rcv_process_set_method(sa, p_madw); 593219820Sjeff 594219820SjeffExit: 595219820Sjeff OSM_LOG_EXIT(sa->p_log); 596219820Sjeff} 597219820Sjeff 598219820Sjeff/********************************************************************* 599219820Sjeff**********************************************************************/ 600219820Sjeffvoid osm_infir_rcv_process(IN void *context, IN void *data) 601219820Sjeff{ 602219820Sjeff osm_sa_t *sa = context; 603219820Sjeff osm_madw_t *p_madw = data; 604219820Sjeff ib_sa_mad_t *p_sa_mad; 605219820Sjeff 606219820Sjeff OSM_LOG_ENTER(sa->p_log); 607219820Sjeff 608219820Sjeff CL_ASSERT(p_madw); 609219820Sjeff 610219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 611219820Sjeff 612219820Sjeff CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD); 613219820Sjeff 614219820Sjeff if (p_sa_mad->method != IB_MAD_METHOD_GET && 615219820Sjeff p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { 616219820Sjeff OSM_LOG(sa->p_log, OSM_LOG_DEBUG, "Unsupported Method (%s)\n", 617219820Sjeff ib_get_sa_method_str(p_sa_mad->method)); 618219820Sjeff osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 619219820Sjeff goto Exit; 620219820Sjeff } 621219820Sjeff 622219820Sjeff osm_infr_rcv_process_get_method(sa, p_madw); 623219820Sjeff 624219820SjeffExit: 625219820Sjeff OSM_LOG_EXIT(sa->p_log); 626219820Sjeff} 627