1/* 2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2006 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * Copyright (c) 2009 HNR Consulting. All rights reserved. 6 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. 7 * 8 * This software is available to you under a choice of one of two 9 * licenses. You may choose to be licensed under the terms of the GNU 10 * General Public License (GPL) Version 2, available from the file 11 * COPYING in the main directory of this source tree, or the 12 * OpenIB.org BSD license below: 13 * 14 * Redistribution and use in source and binary forms, with or 15 * without modification, are permitted provided that the following 16 * conditions are met: 17 * 18 * - Redistributions of source code must retain the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer. 21 * 22 * - Redistributions in binary form must reproduce the above 23 * copyright notice, this list of conditions and the following 24 * disclaimer in the documentation and/or other materials 25 * provided with the distribution. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 30 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 31 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 32 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 33 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 * SOFTWARE. 35 * 36 */ 37 38/* 39 * Abstract: 40 * Implementation of osm_infr_rcv_t. 41 * This object represents the InformInfo Receiver object. 42 * This object is part of the opensm family of objects. 43 */ 44 45#if HAVE_CONFIG_H 46# include <config.h> 47#endif /* HAVE_CONFIG_H */ 48 49#include <string.h> 50#include <iba/ib_types.h> 51#include <arpa/inet.h> 52#include <sys/socket.h> 53#include <complib/cl_qmap.h> 54#include <complib/cl_passivelock.h> 55#include <complib/cl_debug.h> 56#include <complib/cl_qlist.h> 57#include <opensm/osm_file_ids.h> 58#define FILE_ID OSM_FILE_SA_INFORMINFO_C 59#include <vendor/osm_vendor_api.h> 60#include <opensm/osm_port.h> 61#include <opensm/osm_node.h> 62#include <opensm/osm_switch.h> 63#include <opensm/osm_helper.h> 64#include <opensm/osm_sa.h> 65#include <opensm/osm_inform.h> 66#include <opensm/osm_pkey.h> 67 68#define SA_IIR_RESP_SIZE SA_ITEM_RESP_SIZE(inform_rec) 69#define SA_II_RESP_SIZE SA_ITEM_RESP_SIZE(inform) 70 71typedef struct osm_iir_search_ctxt { 72 const ib_inform_info_record_t *p_rcvd_rec; 73 ib_net64_t comp_mask; 74 cl_qlist_t *p_list; 75 ib_gid_t subscriber_gid; 76 ib_net16_t subscriber_enum; 77 osm_sa_t *sa; 78 osm_physp_t *p_req_physp; 79 ib_net64_t sm_key; 80} osm_iir_search_ctxt_t; 81 82/********************************************************************** 83o13-14.1.1: Except for Set(InformInfo) requests with Inform- 84Info:LIDRangeBegin=0xFFFF, managers that support event forwarding 85shall, upon receiving a Set(InformInfo), verify that the requester 86originating the Set(InformInfo) and a Trap() source identified by Inform- 87can access each other - can use path record to verify that. 88**********************************************************************/ 89static boolean_t validate_ports_access_rights(IN osm_sa_t * sa, 90 IN osm_infr_t * p_infr_rec) 91{ 92 boolean_t valid = TRUE; 93 osm_physp_t *p_requester_physp; 94 osm_port_t *p_port; 95 ib_net64_t portguid; 96 uint16_t lid_range_begin, lid_range_end, lid; 97 98 OSM_LOG_ENTER(sa->p_log); 99 100 /* get the requester physp from the request address */ 101 p_requester_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 102 &p_infr_rec->report_addr); 103 104 if (ib_gid_is_notzero(&p_infr_rec->inform_record.inform_info.gid)) { 105 /* a gid is defined */ 106 portguid = 107 p_infr_rec->inform_record.inform_info.gid.unicast. 108 interface_id; 109 110 p_port = osm_get_port_by_guid(sa->p_subn, portguid); 111 if (p_port == NULL) { 112 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4301: " 113 "Invalid port guid: 0x%016" PRIx64 "\n", 114 cl_ntoh64(portguid)); 115 valid = FALSE; 116 goto Exit; 117 } 118 119 /* make sure that the requester and destination port can access 120 each other according to the current partitioning. */ 121 if (!osm_physp_share_pkey 122 (sa->p_log, p_port->p_physp, p_requester_physp, 123 sa->p_subn->opt.allow_both_pkeys)) { 124 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 125 "port and requester don't share pkey\n"); 126 valid = FALSE; 127 goto Exit; 128 } 129 } else { 130 size_t lids_size; 131 132 /* gid is zero - check if LID range is defined */ 133 lid_range_begin = 134 cl_ntoh16(p_infr_rec->inform_record.inform_info. 135 lid_range_begin); 136 /* if lid is 0xFFFF - meaning all endports managed by the manager */ 137 if (lid_range_begin == 0xFFFF) 138 goto Exit; 139 140 lid_range_end = 141 cl_ntoh16(p_infr_rec->inform_record.inform_info. 142 lid_range_end); 143 144 lids_size = cl_ptr_vector_get_size(&sa->p_subn->port_lid_tbl); 145 146 /* lid_range_end is set to zero if no range desired. In this 147 case - just make it equal to the lid_range_begin. */ 148 if (lid_range_end == 0) 149 lid_range_end = lid_range_begin; 150 else if (lid_range_end >= lids_size) 151 lid_range_end = lids_size - 1; 152 153 if (lid_range_begin >= lids_size) { 154 /* requested lids are out of range */ 155 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4302: " 156 "Given LIDs (%u-%u) are out of range (%zu)\n", 157 lid_range_begin, lid_range_end, lids_size); 158 valid = FALSE; 159 goto Exit; 160 } 161 162 /* go over all defined lids within the range and make sure that the 163 requester port can access them according to current partitioning. */ 164 for (lid = lid_range_begin; lid <= lid_range_end; lid++) { 165 p_port = osm_get_port_by_lid_ho(sa->p_subn, lid); 166 if (p_port == NULL) 167 continue; 168 169 /* make sure that the requester and destination port can access 170 each other according to the current partitioning. */ 171 if (!osm_physp_share_pkey 172 (sa->p_log, p_port->p_physp, p_requester_physp, 173 sa->p_subn->opt.allow_both_pkeys)) { 174 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 175 "port and requester don't share pkey\n"); 176 valid = FALSE; 177 goto Exit; 178 } 179 } 180 } 181 182Exit: 183 OSM_LOG_EXIT(sa->p_log); 184 return valid; 185} 186 187static boolean_t validate_infr(IN osm_sa_t * sa, IN osm_infr_t * p_infr_rec) 188{ 189 boolean_t valid = TRUE; 190 191 OSM_LOG_ENTER(sa->p_log); 192 193 valid = validate_ports_access_rights(sa, p_infr_rec); 194 if (!valid) { 195 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 196 "Invalid Access for InformInfo\n"); 197 valid = FALSE; 198 } 199 200 OSM_LOG_EXIT(sa->p_log); 201 return valid; 202} 203 204/********************************************************************** 205o13-12.1.1: Confirm a valid request for event subscription by responding 206with an InformInfo attribute that is a copy of the data in the 207Set(InformInfo) request. 208**********************************************************************/ 209static void infr_rcv_respond(IN osm_sa_t * sa, IN osm_madw_t * p_madw) 210{ 211 cl_qlist_t rec_list; 212 osm_sa_item_t *item; 213 214 OSM_LOG_ENTER(sa->p_log); 215 216 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 217 "Generating successful InformInfo response\n"); 218 219 item = malloc(SA_II_RESP_SIZE); 220 if (!item) { 221 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4303: " 222 "rec_item alloc failed\n"); 223 goto Exit; 224 } 225 226 memcpy(&item->resp.inform, 227 ib_sa_mad_get_payload_ptr(osm_madw_get_sa_mad_ptr(p_madw)), 228 sizeof(ib_inform_info_t)); 229 230 cl_qlist_init(&rec_list); 231 cl_qlist_insert_tail(&rec_list, &item->list_item); 232 233 osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_t), &rec_list); 234 235Exit: 236 OSM_LOG_EXIT(sa->p_log); 237} 238 239static void sa_inform_info_rec_by_comp_mask(IN osm_sa_t * sa, 240 IN const osm_infr_t * p_infr, 241 osm_iir_search_ctxt_t * p_ctxt) 242{ 243 ib_net64_t comp_mask; 244 ib_net64_t portguid; 245 osm_port_t *p_subscriber_port; 246 osm_physp_t *p_subscriber_physp; 247 const osm_physp_t *p_req_physp; 248 osm_sa_item_t *p_rec_item; 249 250 OSM_LOG_ENTER(sa->p_log); 251 252 comp_mask = p_ctxt->comp_mask; 253 p_req_physp = p_ctxt->p_req_physp; 254 255 if (comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID && 256 memcmp(&p_infr->inform_record.subscriber_gid, 257 &p_ctxt->subscriber_gid, 258 sizeof(p_infr->inform_record.subscriber_gid))) 259 goto Exit; 260 261 if (comp_mask & IB_IIR_COMPMASK_ENUM && 262 p_infr->inform_record.subscriber_enum != p_ctxt->subscriber_enum) 263 goto Exit; 264 265 /* Implement any other needed search cases */ 266 267 /* Ensure pkey is shared before returning any records */ 268 portguid = p_infr->inform_record.subscriber_gid.unicast.interface_id; 269 p_subscriber_port = osm_get_port_by_guid(sa->p_subn, portguid); 270 if (p_subscriber_port == NULL) { 271 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430D: " 272 "Invalid subscriber port guid: 0x%016" PRIx64 "\n", 273 cl_ntoh64(portguid)); 274 goto Exit; 275 } 276 277 /* get the subscriber InformInfo physical port */ 278 p_subscriber_physp = p_subscriber_port->p_physp; 279 /* make sure that the requester and subscriber port can access each 280 other according to the current partitioning. */ 281 if (!osm_physp_share_pkey(sa->p_log, p_req_physp, p_subscriber_physp, 282 sa->p_subn->opt.allow_both_pkeys)) { 283 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 284 "requester and subscriber ports don't share pkey\n"); 285 goto Exit; 286 } 287 288 p_rec_item = malloc(SA_IIR_RESP_SIZE); 289 if (p_rec_item == NULL) { 290 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430E: " 291 "rec_item alloc failed\n"); 292 goto Exit; 293 } 294 295 memcpy(&p_rec_item->resp.inform_rec, &p_infr->inform_record, 296 sizeof(ib_inform_info_record_t)); 297 298 /* 299 * Per C15-0.2-1.16, InformInfoRecords shall always be 300 * provided with the QPN set to 0, except for the case 301 * of a trusted request, in which case the actual 302 * subscriber QPN shall be returned. 303 */ 304 if (p_ctxt->sm_key == 0) 305 ib_inform_info_set_qpn(&p_rec_item->resp.inform_rec.inform_info, 0); 306 307 cl_qlist_insert_tail(p_ctxt->p_list, &p_rec_item->list_item); 308 309Exit: 310 OSM_LOG_EXIT(sa->p_log); 311} 312 313static void sa_inform_info_rec_by_comp_mask_cb(IN cl_list_item_t * p_list_item, 314 IN void *context) 315{ 316 const osm_infr_t *p_infr = (osm_infr_t *) p_list_item; 317 osm_iir_search_ctxt_t *p_ctxt = context; 318 319 sa_inform_info_rec_by_comp_mask(p_ctxt->sa, p_infr, p_ctxt); 320} 321 322/********************************************************************** 323Received a Get(InformInfoRecord) or GetTable(InformInfoRecord) MAD 324**********************************************************************/ 325static void infr_rcv_process_get_method(osm_sa_t * sa, IN osm_madw_t * p_madw) 326{ 327 char gid_str[INET6_ADDRSTRLEN]; 328 ib_sa_mad_t *p_rcvd_mad; 329 const ib_inform_info_record_t *p_rcvd_rec; 330 cl_qlist_t rec_list; 331 osm_iir_search_ctxt_t context; 332 osm_physp_t *p_req_physp; 333 osm_sa_item_t *item; 334 335 OSM_LOG_ENTER(sa->p_log); 336 337 CL_ASSERT(p_madw); 338 p_rcvd_mad = osm_madw_get_sa_mad_ptr(p_madw); 339 p_rcvd_rec = 340 (ib_inform_info_record_t *) ib_sa_mad_get_payload_ptr(p_rcvd_mad); 341 342 cl_plock_acquire(sa->p_lock); 343 344 /* update the requester physical port */ 345 p_req_physp = osm_get_physp_by_mad_addr(sa->p_log, sa->p_subn, 346 osm_madw_get_mad_addr_ptr 347 (p_madw)); 348 if (p_req_physp == NULL) { 349 cl_plock_release(sa->p_lock); 350 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4309: " 351 "Cannot find requester physical port\n"); 352 goto Exit; 353 } 354 355 if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) { 356 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 357 "Requester port GUID 0x%" PRIx64 "\n", 358 cl_ntoh64(osm_physp_get_port_guid(p_req_physp))); 359 osm_dump_inform_info_record_v2(sa->p_log, p_rcvd_rec, 360 FILE_ID, OSM_LOG_DEBUG); 361 } 362 363 cl_qlist_init(&rec_list); 364 365 context.p_rcvd_rec = p_rcvd_rec; 366 context.p_list = &rec_list; 367 context.comp_mask = p_rcvd_mad->comp_mask; 368 context.subscriber_gid = p_rcvd_rec->subscriber_gid; 369 context.subscriber_enum = p_rcvd_rec->subscriber_enum; 370 context.sa = sa; 371 context.p_req_physp = p_req_physp; 372 context.sm_key = p_rcvd_mad->sm_key; 373 374 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 375 "Query Subscriber GID:%s(%02X) Enum:0x%X(%02X)\n", 376 inet_ntop(AF_INET6, p_rcvd_rec->subscriber_gid.raw, 377 gid_str, sizeof gid_str), 378 (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_SUBSCRIBERGID) != 0, 379 cl_ntoh16(p_rcvd_rec->subscriber_enum), 380 (p_rcvd_mad->comp_mask & IB_IIR_COMPMASK_ENUM) != 0); 381 382 cl_qlist_apply_func(&sa->p_subn->sa_infr_list, 383 sa_inform_info_rec_by_comp_mask_cb, &context); 384 385 /* clear reserved and pad fields in InformInfoRecord */ 386 for (item = (osm_sa_item_t *) cl_qlist_head(&rec_list); 387 item != (osm_sa_item_t *) cl_qlist_end(&rec_list); 388 item = (osm_sa_item_t *) cl_qlist_next(&item->list_item)) { 389 memset(item->resp.inform_rec.reserved, 0, sizeof(item->resp.inform_rec.reserved)); 390 memset(item->resp.inform_rec.pad, 0, sizeof(item->resp.inform_rec.pad)); 391 } 392 393 cl_plock_release(sa->p_lock); 394 395 osm_sa_respond(sa, p_madw, sizeof(ib_inform_info_record_t), &rec_list); 396 397Exit: 398 OSM_LOG_EXIT(sa->p_log); 399} 400 401/********************************************************************* 402Received a Set(InformInfo) MAD 403**********************************************************************/ 404static void infr_rcv_process_set_method(osm_sa_t * sa, IN osm_madw_t * p_madw) 405{ 406 ib_sa_mad_t *p_sa_mad; 407 ib_inform_info_t *p_recvd_inform_info; 408 osm_infr_t inform_info_rec; /* actual inform record to be stored for reports */ 409 osm_infr_t *p_infr; 410 ib_net32_t qpn; 411 uint8_t resp_time_val; 412 ib_api_status_t res; 413 414 OSM_LOG_ENTER(sa->p_log); 415 416 CL_ASSERT(p_madw); 417 418 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 419 p_recvd_inform_info = 420 (ib_inform_info_t *) ib_sa_mad_get_payload_ptr(p_sa_mad); 421 422#if 0 423 if (OSM_LOG_IS_ACTIVE_V2(sa->p_log, OSM_LOG_DEBUG)) 424 osm_dump_inform_info_v2(sa->p_log, p_recvd_inform_info, 425 FILE_ID, OSM_LOG_DEBUG); 426#endif 427 428 /* Grab the lock */ 429 cl_plock_excl_acquire(sa->p_lock); 430 431 /* define the inform record */ 432 inform_info_rec.inform_record.inform_info = *p_recvd_inform_info; 433 434 /* following C13-32.1.2 Tbl 120: we only copy the source address vector */ 435 inform_info_rec.report_addr = p_madw->mad_addr; 436 437 /* we will need to know the mad srvc to send back through */ 438 inform_info_rec.h_bind = p_madw->h_bind; 439 inform_info_rec.sa = sa; 440 441 /* update the subscriber GID according to mad address */ 442 res = osm_get_gid_by_mad_addr(sa->p_log, sa->p_subn, &p_madw->mad_addr, 443 &inform_info_rec.inform_record. 444 subscriber_gid); 445 if (res != IB_SUCCESS) { 446 cl_plock_release(sa->p_lock); 447 448 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4308: " 449 "Subscribe Request from unknown LID: %u\n", 450 cl_ntoh16(p_madw->mad_addr.dest_lid)); 451 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 452 goto Exit; 453 } 454 455 /* HACK: enum is always 0 (currently) */ 456 inform_info_rec.inform_record.subscriber_enum = 0; 457 458 /* Subscribe values above 1 are undefined */ 459 if (p_recvd_inform_info->subscribe > 1) { 460 cl_plock_release(sa->p_lock); 461 462 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430A: " 463 "Invalid subscribe: %d\n", 464 p_recvd_inform_info->subscribe); 465 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 466 goto Exit; 467 } 468 469 /* 470 * Per C15-0.2-1.16, SubnAdmSet(InformInfo) subscriptions for 471 * SM security traps shall be provided only if they come from a 472 * trusted source. 473 */ 474 if ((p_sa_mad->sm_key == 0) && p_recvd_inform_info->is_generic && 475 ((cl_ntoh16(p_recvd_inform_info->g_or_v.generic.trap_num) >= SM_BAD_MKEY_TRAP) && 476 (cl_ntoh16(p_recvd_inform_info->g_or_v.generic.trap_num) <= SM_BAD_SWITCH_PKEY_TRAP))) { 477 cl_plock_release(sa->p_lock); 478 479 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 430B " 480 "Request for security trap from non-trusted requester: " 481 "Given SM_Key:0x%016" PRIx64 "\n", 482 cl_ntoh64(p_sa_mad->sm_key)); 483 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 484 goto Exit; 485 } 486 487 /* 488 * MODIFICATIONS DONE ON INCOMING REQUEST: 489 * 490 * QPN: 491 * Internally we keep the QPN field of the InformInfo updated 492 * so we can simply compare it in the record - when finding such. 493 */ 494 if (p_recvd_inform_info->subscribe) { 495 ib_inform_info_set_qpn(&inform_info_rec.inform_record. 496 inform_info, 497 inform_info_rec.report_addr.addr_type. 498 gsi.remote_qp); 499 500 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 501 "Subscribe Request with QPN: 0x%06X\n", 502 cl_ntoh32(inform_info_rec.report_addr.addr_type.gsi. 503 remote_qp)); 504 } else { 505 ib_inform_info_get_qpn_resp_time(p_recvd_inform_info->g_or_v. 506 generic.qpn_resp_time_val, 507 &qpn, &resp_time_val); 508 509 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 510 "UnSubscribe Request with QPN: 0x%06X\n", 511 cl_ntoh32(qpn)); 512 } 513 514 /* If record exists with matching InformInfo */ 515 p_infr = osm_infr_get_by_rec(sa->p_subn, sa->p_log, &inform_info_rec); 516 517 /* check to see if the request was for subscribe */ 518 if (p_recvd_inform_info->subscribe) { 519 /* validate the request for a new or update InformInfo */ 520 if (validate_infr(sa, &inform_info_rec) != TRUE) { 521 cl_plock_release(sa->p_lock); 522 523 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4305: " 524 "Failed to validate a new inform object\n"); 525 526 /* o13-13.1.1: we need to set the subscribe bit to 0 */ 527 p_recvd_inform_info->subscribe = 0; 528 osm_sa_send_error(sa, p_madw, 529 IB_SA_MAD_STATUS_REQ_INVALID); 530 goto Exit; 531 } 532 533 /* ok - we can try and create a new entry */ 534 if (p_infr == NULL) { 535 /* Create the instance of the osm_infr_t object */ 536 p_infr = osm_infr_new(&inform_info_rec); 537 if (p_infr == NULL) { 538 cl_plock_release(sa->p_lock); 539 540 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4306: " 541 "Failed to create a new inform object\n"); 542 543 /* o13-13.1.1: we need to set the subscribe bit to 0 */ 544 p_recvd_inform_info->subscribe = 0; 545 osm_sa_send_error(sa, p_madw, 546 IB_SA_MAD_STATUS_NO_RESOURCES); 547 goto Exit; 548 } 549 550 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 551 "Adding event subscription for port 0x%" PRIx64 "\n", 552 cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.interface_id)); 553 554 /* Add this new osm_infr_t object to subnet object */ 555 osm_infr_insert_to_db(sa->p_subn, sa->p_log, p_infr); 556 } else 557 /* Update the old instance of the osm_infr_t object */ 558 p_infr->inform_record = inform_info_rec.inform_record; 559 /* We got an UnSubscribe request */ 560 } else if (p_infr == NULL) { 561 cl_plock_release(sa->p_lock); 562 563 /* No Such Item - So Error */ 564 OSM_LOG(sa->p_log, OSM_LOG_ERROR, "ERR 4307: " 565 "Failed to UnSubscribe to non existing inform object\n"); 566 567 /* o13-13.1.1: we need to set the subscribe bit to 0 */ 568 p_recvd_inform_info->subscribe = 0; 569 osm_sa_send_error(sa, p_madw, IB_SA_MAD_STATUS_REQ_INVALID); 570 goto Exit; 571 } else { 572 /* Delete this object from the subnet list of informs */ 573 OSM_LOG(sa->p_log, OSM_LOG_VERBOSE, 574 "Removing event subscription for port 0x%" PRIx64 "\n", 575 cl_ntoh64(inform_info_rec.inform_record.subscriber_gid.unicast.interface_id)); 576 osm_infr_remove_from_db(sa->p_subn, sa->p_log, p_infr); 577 } 578 579 cl_plock_release(sa->p_lock); 580 581 /* send the success response */ 582 infr_rcv_respond(sa, p_madw); 583 584Exit: 585 OSM_LOG_EXIT(sa->p_log); 586} 587 588void osm_infr_rcv_process(IN void *context, IN void *data) 589{ 590 osm_sa_t *sa = context; 591 osm_madw_t *p_madw = data; 592 ib_sa_mad_t *p_sa_mad; 593 594 OSM_LOG_ENTER(sa->p_log); 595 596 CL_ASSERT(p_madw); 597 598 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 599 600 CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO); 601 602 if (p_sa_mad->method != IB_MAD_METHOD_SET) { 603 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 604 "Unsupported Method (%s) for InformInfo\n", 605 ib_get_sa_method_str(p_sa_mad->method)); 606 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 607 goto Exit; 608 } 609 610 infr_rcv_process_set_method(sa, p_madw); 611 612Exit: 613 OSM_LOG_EXIT(sa->p_log); 614} 615 616void osm_infir_rcv_process(IN void *context, IN void *data) 617{ 618 osm_sa_t *sa = context; 619 osm_madw_t *p_madw = data; 620 ib_sa_mad_t *p_sa_mad; 621 622 OSM_LOG_ENTER(sa->p_log); 623 624 CL_ASSERT(p_madw); 625 626 p_sa_mad = osm_madw_get_sa_mad_ptr(p_madw); 627 628 CL_ASSERT(p_sa_mad->attr_id == IB_MAD_ATTR_INFORM_INFO_RECORD); 629 630 if (p_sa_mad->method != IB_MAD_METHOD_GET && 631 p_sa_mad->method != IB_MAD_METHOD_GETTABLE) { 632 OSM_LOG(sa->p_log, OSM_LOG_DEBUG, 633 "Unsupported Method (%s) for InformInfoRecord\n", 634 ib_get_sa_method_str(p_sa_mad->method)); 635 osm_sa_send_error(sa, p_madw, IB_MAD_STATUS_UNSUP_METHOD_ATTR); 636 goto Exit; 637 } 638 639 infr_rcv_process_get_method(sa, p_madw); 640 641Exit: 642 OSM_LOG_EXIT(sa->p_log); 643} 644