1/* 2 * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 * 34 */ 35 36/* 37 * Abstract: 38 * Implementation of inform record functions. 39 */ 40 41#if HAVE_CONFIG_H 42# include <config.h> 43#endif /* HAVE_CONFIG_H */ 44 45#include <stdlib.h> 46#include <string.h> 47#include <arpa/inet.h> 48#include <complib/cl_debug.h> 49#include <opensm/osm_helper.h> 50#include <opensm/osm_inform.h> 51#include <vendor/osm_vendor_api.h> 52#include <opensm/osm_pkey.h> 53#include <opensm/osm_sa.h> 54#include <sys/socket.h> 55 56typedef struct osm_infr_match_ctxt { 57 cl_list_t *p_remove_infr_list; 58 ib_mad_notice_attr_t *p_ntc; 59} osm_infr_match_ctxt_t; 60 61/********************************************************************** 62 **********************************************************************/ 63void osm_infr_delete(IN osm_infr_t * const p_infr) 64{ 65 free(p_infr); 66} 67 68/********************************************************************** 69 **********************************************************************/ 70osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec) 71{ 72 osm_infr_t *p_infr; 73 74 CL_ASSERT(p_infr_rec); 75 76 p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t)); 77 if (p_infr) 78 memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t)); 79 80 return (p_infr); 81} 82 83/********************************************************************** 84 **********************************************************************/ 85static void dump_all_informs(IN osm_subn_t const *p_subn, IN osm_log_t * p_log) 86{ 87 cl_list_item_t *p_list_item; 88 89 if (!osm_log_is_active(p_log, OSM_LOG_DEBUG)) 90 return; 91 92 p_list_item = cl_qlist_head(&p_subn->sa_infr_list); 93 while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { 94 osm_dump_inform_info(p_log, 95 &((osm_infr_t *) p_list_item)-> 96 inform_record.inform_info, OSM_LOG_DEBUG); 97 p_list_item = cl_qlist_next(p_list_item); 98 } 99} 100 101/********************************************************************** 102 * Match an infr by the InformInfo and Address vector 103 **********************************************************************/ 104static cl_status_t 105__match_inf_rec(IN const cl_list_item_t * const p_list_item, IN void *context) 106{ 107 osm_infr_t *p_infr_rec = (osm_infr_t *) context; 108 osm_infr_t *p_infr = (osm_infr_t *) p_list_item; 109 osm_log_t *p_log = p_infr_rec->sa->p_log; 110 cl_status_t status = CL_NOT_FOUND; 111 ib_gid_t all_zero_gid; 112 113 OSM_LOG_ENTER(p_log); 114 115 if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr, 116 sizeof(p_infr_rec->report_addr))) { 117 OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n"); 118 goto Exit; 119 } 120 121 memset(&all_zero_gid, 0, sizeof(ib_gid_t)); 122 123 /* if inform_info.gid is not zero, ignore lid range */ 124 if (!memcmp(&p_infr_rec->inform_record.inform_info.gid, &all_zero_gid, 125 sizeof(p_infr_rec->inform_record.inform_info.gid))) { 126 if (memcmp(&p_infr->inform_record.inform_info.gid, 127 &p_infr_rec->inform_record.inform_info.gid, 128 sizeof(p_infr->inform_record.inform_info.gid))) { 129 OSM_LOG(p_log, OSM_LOG_DEBUG, 130 "Differ by InformInfo.gid\n"); 131 goto Exit; 132 } 133 } else { 134 if ((p_infr->inform_record.inform_info.lid_range_begin != 135 p_infr_rec->inform_record.inform_info.lid_range_begin) || 136 (p_infr->inform_record.inform_info.lid_range_end != 137 p_infr_rec->inform_record.inform_info.lid_range_end)) { 138 OSM_LOG(p_log, OSM_LOG_DEBUG, 139 "Differ by InformInfo.LIDRange\n"); 140 goto Exit; 141 } 142 } 143 144 if (p_infr->inform_record.inform_info.trap_type != 145 p_infr_rec->inform_record.inform_info.trap_type) { 146 OSM_LOG(p_log, OSM_LOG_DEBUG, 147 "Differ by InformInfo.TrapType\n"); 148 goto Exit; 149 } 150 151 if (p_infr->inform_record.inform_info.is_generic != 152 p_infr_rec->inform_record.inform_info.is_generic) { 153 OSM_LOG(p_log, OSM_LOG_DEBUG, 154 "Differ by InformInfo.IsGeneric\n"); 155 goto Exit; 156 } 157 158 if (p_infr->inform_record.inform_info.is_generic) { 159 if (p_infr->inform_record.inform_info.g_or_v.generic.trap_num != 160 p_infr_rec->inform_record.inform_info.g_or_v.generic. 161 trap_num) 162 OSM_LOG(p_log, OSM_LOG_DEBUG, 163 "Differ by InformInfo.Generic.TrapNumber\n"); 164 else if (p_infr->inform_record.inform_info.g_or_v.generic. 165 qpn_resp_time_val != 166 p_infr_rec->inform_record.inform_info.g_or_v.generic. 167 qpn_resp_time_val) 168 OSM_LOG(p_log, OSM_LOG_DEBUG, 169 "Differ by InformInfo.Generic.QPNRespTimeVal\n"); 170 else if (p_infr->inform_record.inform_info.g_or_v.generic. 171 node_type_msb != 172 p_infr_rec->inform_record.inform_info.g_or_v.generic. 173 node_type_msb) 174 OSM_LOG(p_log, OSM_LOG_DEBUG, 175 "Differ by InformInfo.Generic.NodeTypeMSB\n"); 176 else if (p_infr->inform_record.inform_info.g_or_v.generic. 177 node_type_lsb != 178 p_infr_rec->inform_record.inform_info.g_or_v.generic. 179 node_type_lsb) 180 OSM_LOG(p_log, OSM_LOG_DEBUG, 181 "Differ by InformInfo.Generic.NodeTypeLSB\n"); 182 else 183 status = CL_SUCCESS; 184 } else { 185 if (p_infr->inform_record.inform_info.g_or_v.vend.dev_id != 186 p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id) 187 OSM_LOG(p_log, OSM_LOG_DEBUG, 188 "Differ by InformInfo.Vendor.DeviceID\n"); 189 else if (p_infr->inform_record.inform_info.g_or_v.vend. 190 qpn_resp_time_val != 191 p_infr_rec->inform_record.inform_info.g_or_v.vend. 192 qpn_resp_time_val) 193 OSM_LOG(p_log, OSM_LOG_DEBUG, 194 "Differ by InformInfo.Vendor.QPNRespTimeVal\n"); 195 else if (p_infr->inform_record.inform_info.g_or_v.vend. 196 vendor_id_msb != 197 p_infr_rec->inform_record.inform_info.g_or_v.vend. 198 vendor_id_msb) 199 OSM_LOG(p_log, OSM_LOG_DEBUG, 200 "Differ by InformInfo.Vendor.VendorIdMSB\n"); 201 else if (p_infr->inform_record.inform_info.g_or_v.vend. 202 vendor_id_lsb != 203 p_infr_rec->inform_record.inform_info.g_or_v.vend. 204 vendor_id_lsb) 205 OSM_LOG(p_log, OSM_LOG_DEBUG, 206 "Differ by InformInfo.Vendor.VendorIdLSB\n"); 207 else 208 status = CL_SUCCESS; 209 } 210 211Exit: 212 OSM_LOG_EXIT(p_log); 213 return status; 214} 215 216/********************************************************************** 217 **********************************************************************/ 218osm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn, 219 IN osm_log_t * p_log, 220 IN osm_infr_t * const p_infr_rec) 221{ 222 cl_list_item_t *p_list_item; 223 224 OSM_LOG_ENTER(p_log); 225 226 dump_all_informs(p_subn, p_log); 227 228 OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n"); 229 osm_dump_inform_info(p_log, &(p_infr_rec->inform_record.inform_info), 230 OSM_LOG_DEBUG); 231 OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n", 232 cl_qlist_count(&p_subn->sa_infr_list)); 233 234 p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list, 235 __match_inf_rec, p_infr_rec); 236 237 if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list)) 238 p_list_item = NULL; 239 240 OSM_LOG_EXIT(p_log); 241 return (osm_infr_t *) p_list_item; 242} 243 244/********************************************************************** 245 **********************************************************************/ 246void 247osm_infr_insert_to_db(IN osm_subn_t * p_subn, 248 IN osm_log_t * p_log, IN osm_infr_t * p_infr) 249{ 250 OSM_LOG_ENTER(p_log); 251 252 OSM_LOG(p_log, OSM_LOG_DEBUG, 253 "Inserting new InformInfo Record into Database\n"); 254 OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n", 255 cl_qlist_count(&p_subn->sa_infr_list)); 256 dump_all_informs(p_subn, p_log); 257 258#if 0 259 osm_dump_inform_info(p_log, 260 &(p_infr->inform_record.inform_info), 261 OSM_LOG_DEBUG); 262#endif 263 264 cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item); 265 266 OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n", 267 cl_qlist_count(&p_subn->sa_infr_list)); 268 dump_all_informs(p_subn, p_log); 269 OSM_LOG_EXIT(p_log); 270} 271 272/********************************************************************** 273 **********************************************************************/ 274void 275osm_infr_remove_from_db(IN osm_subn_t * p_subn, 276 IN osm_log_t * p_log, IN osm_infr_t * p_infr) 277{ 278 char gid_str[INET6_ADDRSTRLEN]; 279 OSM_LOG_ENTER(p_log); 280 281 OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s" 282 " Enum:0x%X from Database\n", 283 inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw, 284 gid_str, sizeof gid_str), 285 p_infr->inform_record.subscriber_enum); 286 287 osm_dump_inform_info(p_log, &(p_infr->inform_record.inform_info), 288 OSM_LOG_DEBUG); 289 290 cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item); 291 292 osm_infr_delete(p_infr); 293 294 OSM_LOG_EXIT(p_log); 295} 296 297/********************************************************************** 298 * Send a report: 299 * Given a target address to send to and the notice. 300 * We need to send SubnAdmReport 301 **********************************************************************/ 302static ib_api_status_t __osm_send_report(IN osm_infr_t * p_infr_rec, /* the informinfo */ 303 IN ib_mad_notice_attr_t * p_ntc /* notice to send */ 304 ) 305{ 306 osm_madw_t *p_report_madw; 307 ib_mad_notice_attr_t *p_report_ntc; 308 ib_mad_t *p_mad; 309 ib_sa_mad_t *p_sa_mad; 310 static atomic32_t trap_fwd_trans_id = 0x02DAB000; 311 ib_api_status_t status = IB_SUCCESS; 312 osm_log_t *p_log = p_infr_rec->sa->p_log; 313 314 OSM_LOG_ENTER(p_log); 315 316 /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */ 317 318 /* it is better to use LIDs since the GIDs might not be there for SMI traps */ 319 OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID:%u" 320 " to InformInfo LID: %u TID:0x%X\n", 321 cl_ntoh16(p_ntc->issuer_lid), 322 cl_ntoh16(p_infr_rec->report_addr.dest_lid), trap_fwd_trans_id); 323 324 /* get the MAD to send */ 325 p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool, 326 p_infr_rec->h_bind, MAD_BLOCK_SIZE, 327 &(p_infr_rec->report_addr)); 328 329 p_report_madw->resp_expected = TRUE; 330 331 if (!p_report_madw) { 332 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203" 333 "osm_mad_pool_get failed\n"); 334 status = IB_ERROR; 335 goto Exit; 336 } 337 338 /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ 339 p_mad = osm_madw_get_mad_ptr(p_report_madw); 340 ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT, 341 cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id)), 342 IB_MAD_ATTR_NOTICE, 0); 343 344 p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw); 345 346 p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data); 347 348 /* copy the notice */ 349 *p_report_ntc = *p_ntc; 350 351 /* The TRUE is for: response is expected */ 352 osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE); 353 354Exit: 355 OSM_LOG_EXIT(p_log); 356 return (status); 357} 358 359/********************************************************************** 360 * This routine compares a given Notice and a ListItem of InformInfo type. 361 * PREREQUISITE: 362 * The Notice.GID should be pre-filled with the trap generator GID 363 **********************************************************************/ 364static void 365__match_notice_to_inf_rec(IN cl_list_item_t * const p_list_item, 366 IN void *context) 367{ 368 osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context; 369 ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; 370 cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list; 371 osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item; 372 ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); 373 cl_status_t status = CL_NOT_FOUND; 374 osm_log_t *p_log = p_infr_rec->sa->p_log; 375 osm_subn_t *p_subn = p_infr_rec->sa->p_subn; 376 ib_gid_t source_gid; 377 osm_port_t *p_src_port; 378 osm_port_t *p_dest_port; 379 380 OSM_LOG_ENTER(p_log); 381 382 /* matching rules 383 * InformInfo Notice 384 * GID IssuerGID if non zero must match the trap 385 * LIDRange IssuerLID apply only if GID=0 386 * IsGeneric IsGeneric is compulsory and must match the trap 387 * Type Type if not 0xFFFF must match 388 * TrapNumber TrapNumber if not 0xFFFF must match 389 * DeviceId DeviceID if not 0xFFFF must match 390 * QPN dont care 391 * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation 392 * VendorID VendorID match or 0xFFFFFF 393 */ 394 395 /* GID IssuerGID if non zero must match the trap */ 396 if (p_ii->gid.unicast.prefix != 0 397 || p_ii->gid.unicast.interface_id != 0) { 398 /* match by GID */ 399 if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), 400 sizeof(ib_gid_t))) { 401 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n"); 402 goto Exit; 403 } 404 } else { 405 /* LIDRange IssuerLID apply only if GID=0 */ 406 /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */ 407 if (p_ii->lid_range_begin != 0xFFFF) { 408 /* a real lid range is given - check it */ 409 if ((cl_hton16(p_ii->lid_range_begin) > 410 cl_hton16(p_ntc->issuer_lid)) 411 || (cl_hton16(p_ntc->issuer_lid) > 412 cl_hton16(p_ii->lid_range_end))) { 413 OSM_LOG(p_log, OSM_LOG_DEBUG, 414 "Mismatch by LID Range. Needed: %u <= %u <= %u\n", 415 cl_hton16(p_ii->lid_range_begin), 416 cl_hton16(p_ntc->issuer_lid), 417 cl_hton16(p_ii->lid_range_end)); 418 goto Exit; 419 } 420 } 421 } 422 423 /* IsGeneric IsGeneric is compulsory and must match the trap */ 424 if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) || 425 (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) { 426 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n"); 427 goto Exit; 428 } 429 430 /* Type Type if not 0xFFFF must match */ 431 if ((p_ii->trap_type != 0xFFFF) && 432 (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) { 433 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n"); 434 goto Exit; 435 } 436 437 /* based on generic type */ 438 if (p_ii->is_generic) { 439 /* TrapNumber TrapNumber if not 0xFFFF must match */ 440 if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) && 441 (p_ii->g_or_v.generic.trap_num != 442 p_ntc->g_or_v.generic.trap_num)) { 443 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n"); 444 goto Exit; 445 } 446 447 /* ProducerType ProducerType match or 0xFFFFFF */ 448 if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF) 449 && (ib_inform_info_get_prod_type(p_ii) != 450 ib_notice_get_prod_type(p_ntc))) { 451 OSM_LOG(p_log, OSM_LOG_DEBUG, 452 "Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n", 453 cl_ntoh32(ib_inform_info_get_prod_type(p_ii)), 454 ib_get_producer_type_str 455 (ib_inform_info_get_prod_type(p_ii)), 456 cl_ntoh32(ib_notice_get_prod_type(p_ntc)), 457 ib_get_producer_type_str(ib_notice_get_prod_type 458 (p_ntc))); 459 goto Exit; 460 } 461 } else { 462 /* DeviceId DeviceID if not 0xFFFF must match */ 463 if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) && 464 (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) { 465 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n"); 466 goto Exit; 467 } 468 469 /* VendorID VendorID match or 0xFFFFFF */ 470 if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) && 471 (ib_inform_info_get_vend_id(p_ii) != 472 ib_notice_get_vend_id(p_ntc))) { 473 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Vendor ID\n"); 474 goto Exit; 475 } 476 } 477 478 /* Check if there is a pkey match. o13-17.1.1 */ 479 /* Check if the issuer of the trap is the SM. If it is, then the gid 480 comparison should be done on the trap source (saved as the gid in the 481 data details field). 482 If the issuer gid is not the SM - then it is the guid of the trap 483 source */ 484 if ((cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == 485 p_subn->opt.subnet_prefix) 486 && (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == 487 p_subn->sm_port_guid)) 488 /* The issuer is the SM then this is trap 64-67 - compare the gid 489 with the gid saved on the data details */ 490 source_gid = p_ntc->data_details.ntc_64_67.gid; 491 else 492 source_gid = p_ntc->issuer_gid; 493 494 p_src_port = 495 osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id); 496 if (!p_src_port) { 497 OSM_LOG(p_log, OSM_LOG_INFO, 498 "Cannot find source port with GUID:0x%016" PRIx64 "\n", 499 cl_ntoh64(source_gid.unicast.interface_id)); 500 goto Exit; 501 } 502 503 p_dest_port = 504 cl_ptr_vector_get(&p_subn->port_lid_tbl, 505 cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 506 if (!p_dest_port) { 507 OSM_LOG(p_log, OSM_LOG_INFO, 508 "Cannot find destination port with LID:%u\n", 509 cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 510 goto Exit; 511 } 512 513 if (osm_port_share_pkey(p_log, p_src_port, p_dest_port) == FALSE) { 514 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n"); 515 /* According to o13-17.1.2 - If this informInfo does not have 516 lid_range_begin of 0xFFFF, then this informInfo request 517 should be removed from database */ 518 if (p_ii->lid_range_begin != 0xFFFF) { 519 OSM_LOG(p_log, OSM_LOG_VERBOSE, 520 "Pkey mismatch on lid_range_begin != 0xFFFF. " 521 "Need to remove this informInfo from db\n"); 522 /* add the informInfo record to the remove_infr list */ 523 cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec); 524 } 525 goto Exit; 526 } 527 528 /* send the report to the address provided in the inform record */ 529 OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n"); 530 __osm_send_report(p_infr_rec, p_ntc); 531 status = CL_SUCCESS; 532 533Exit: 534 OSM_LOG_EXIT(p_log); 535} 536 537/********************************************************************** 538 * Once a Trap was received by osm_trap_rcv, or a Trap sourced by 539 * the SM was sent (Traps 64-67), this routine is called with a copy of 540 * the notice data. 541 * Given a notice attribute - compare and see if it matches the InformInfo 542 * element and if it does - call the Report(Notice) for the 543 * target QP registered by the address stored in the InformInfo element 544 **********************************************************************/ 545ib_api_status_t 546osm_report_notice(IN osm_log_t * const p_log, 547 IN osm_subn_t * p_subn, IN ib_mad_notice_attr_t * p_ntc) 548{ 549 char gid_str[INET6_ADDRSTRLEN]; 550 osm_infr_match_ctxt_t context; 551 cl_list_t infr_to_remove_list; 552 osm_infr_t *p_infr_rec; 553 osm_infr_t *p_next_infr_rec; 554 555 OSM_LOG_ENTER(p_log); 556 557 /* 558 * we must make sure we are ready for this... 559 * note that the trap receivers might be initialized before 560 * the osm_infr_init call is performed. 561 */ 562 if (p_subn->sa_infr_list.state != CL_INITIALIZED) { 563 OSM_LOG(p_log, OSM_LOG_DEBUG, 564 "Ignoring Notice Reports since Inform List is not initialized yet!\n"); 565 return (IB_ERROR); 566 } 567 568 /* an official Event information log */ 569 if (ib_notice_is_generic(p_ntc)) 570 OSM_LOG(p_log, OSM_LOG_INFO, 571 "Reporting Generic Notice type:%u num:%u (%s)" 572 " from LID:%u GID:%s\n", 573 ib_notice_get_type(p_ntc), 574 cl_ntoh16(p_ntc->g_or_v.generic.trap_num), 575 ib_get_trap_str(p_ntc->g_or_v.generic.trap_num), 576 cl_ntoh16(p_ntc->issuer_lid), 577 inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str, 578 sizeof gid_str)); 579 else 580 OSM_LOG(p_log, OSM_LOG_INFO, 581 "Reporting Vendor Notice type:%u vend:%u dev:%u" 582 " from LID:%u GID:%s\n", 583 ib_notice_get_type(p_ntc), 584 cl_ntoh32(ib_notice_get_vend_id(p_ntc)), 585 cl_ntoh16(p_ntc->g_or_v.vend.dev_id), 586 cl_ntoh16(p_ntc->issuer_lid), 587 inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str, 588 sizeof gid_str)); 589 590 /* Create a list that will hold all the infr records that should 591 be removed due to violation. o13-17.1.2 */ 592 cl_list_construct(&infr_to_remove_list); 593 cl_list_init(&infr_to_remove_list, 5); 594 context.p_remove_infr_list = &infr_to_remove_list; 595 context.p_ntc = p_ntc; 596 597 /* go over all inform info available at the subnet */ 598 /* try match to the given notice and send if match */ 599 cl_qlist_apply_func(&(p_subn->sa_infr_list), 600 __match_notice_to_inf_rec, &context); 601 602 /* If we inserted items into the infr_to_remove_list - we need to 603 remove them */ 604 p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 605 while (p_infr_rec != NULL) { 606 p_next_infr_rec = 607 (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 608 osm_infr_remove_from_db(p_subn, p_log, p_infr_rec); 609 p_infr_rec = p_next_infr_rec; 610 } 611 cl_list_destroy(&infr_to_remove_list); 612 613 OSM_LOG_EXIT(p_log); 614 615 return (IB_SUCCESS); 616} 617