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 inform record functions. 39219820Sjeff */ 40219820Sjeff 41219820Sjeff#if HAVE_CONFIG_H 42219820Sjeff# include <config.h> 43219820Sjeff#endif /* HAVE_CONFIG_H */ 44219820Sjeff 45219820Sjeff#include <stdlib.h> 46219820Sjeff#include <string.h> 47219820Sjeff#include <arpa/inet.h> 48219820Sjeff#include <complib/cl_debug.h> 49219820Sjeff#include <opensm/osm_helper.h> 50219820Sjeff#include <opensm/osm_inform.h> 51219820Sjeff#include <vendor/osm_vendor_api.h> 52219820Sjeff#include <opensm/osm_pkey.h> 53219820Sjeff#include <opensm/osm_sa.h> 54219820Sjeff#include <sys/socket.h> 55219820Sjeff 56219820Sjefftypedef struct osm_infr_match_ctxt { 57219820Sjeff cl_list_t *p_remove_infr_list; 58219820Sjeff ib_mad_notice_attr_t *p_ntc; 59219820Sjeff} osm_infr_match_ctxt_t; 60219820Sjeff 61219820Sjeff/********************************************************************** 62219820Sjeff **********************************************************************/ 63219820Sjeffvoid osm_infr_delete(IN osm_infr_t * const p_infr) 64219820Sjeff{ 65219820Sjeff free(p_infr); 66219820Sjeff} 67219820Sjeff 68219820Sjeff/********************************************************************** 69219820Sjeff **********************************************************************/ 70219820Sjeffosm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec) 71219820Sjeff{ 72219820Sjeff osm_infr_t *p_infr; 73219820Sjeff 74219820Sjeff CL_ASSERT(p_infr_rec); 75219820Sjeff 76219820Sjeff p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t)); 77219820Sjeff if (p_infr) 78219820Sjeff memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t)); 79219820Sjeff 80219820Sjeff return (p_infr); 81219820Sjeff} 82219820Sjeff 83219820Sjeff/********************************************************************** 84219820Sjeff **********************************************************************/ 85219820Sjeffstatic void dump_all_informs(IN osm_subn_t const *p_subn, IN osm_log_t * p_log) 86219820Sjeff{ 87219820Sjeff cl_list_item_t *p_list_item; 88219820Sjeff 89219820Sjeff if (!osm_log_is_active(p_log, OSM_LOG_DEBUG)) 90219820Sjeff return; 91219820Sjeff 92219820Sjeff p_list_item = cl_qlist_head(&p_subn->sa_infr_list); 93219820Sjeff while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { 94219820Sjeff osm_dump_inform_info(p_log, 95219820Sjeff &((osm_infr_t *) p_list_item)-> 96219820Sjeff inform_record.inform_info, OSM_LOG_DEBUG); 97219820Sjeff p_list_item = cl_qlist_next(p_list_item); 98219820Sjeff } 99219820Sjeff} 100219820Sjeff 101219820Sjeff/********************************************************************** 102219820Sjeff * Match an infr by the InformInfo and Address vector 103219820Sjeff **********************************************************************/ 104219820Sjeffstatic cl_status_t 105219820Sjeff__match_inf_rec(IN const cl_list_item_t * const p_list_item, IN void *context) 106219820Sjeff{ 107219820Sjeff osm_infr_t *p_infr_rec = (osm_infr_t *) context; 108219820Sjeff osm_infr_t *p_infr = (osm_infr_t *) p_list_item; 109219820Sjeff osm_log_t *p_log = p_infr_rec->sa->p_log; 110219820Sjeff cl_status_t status = CL_NOT_FOUND; 111219820Sjeff ib_gid_t all_zero_gid; 112219820Sjeff 113219820Sjeff OSM_LOG_ENTER(p_log); 114219820Sjeff 115219820Sjeff if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr, 116219820Sjeff sizeof(p_infr_rec->report_addr))) { 117219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n"); 118219820Sjeff goto Exit; 119219820Sjeff } 120219820Sjeff 121219820Sjeff memset(&all_zero_gid, 0, sizeof(ib_gid_t)); 122219820Sjeff 123219820Sjeff /* if inform_info.gid is not zero, ignore lid range */ 124219820Sjeff if (!memcmp(&p_infr_rec->inform_record.inform_info.gid, &all_zero_gid, 125219820Sjeff sizeof(p_infr_rec->inform_record.inform_info.gid))) { 126219820Sjeff if (memcmp(&p_infr->inform_record.inform_info.gid, 127219820Sjeff &p_infr_rec->inform_record.inform_info.gid, 128219820Sjeff sizeof(p_infr->inform_record.inform_info.gid))) { 129219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 130219820Sjeff "Differ by InformInfo.gid\n"); 131219820Sjeff goto Exit; 132219820Sjeff } 133219820Sjeff } else { 134219820Sjeff if ((p_infr->inform_record.inform_info.lid_range_begin != 135219820Sjeff p_infr_rec->inform_record.inform_info.lid_range_begin) || 136219820Sjeff (p_infr->inform_record.inform_info.lid_range_end != 137219820Sjeff p_infr_rec->inform_record.inform_info.lid_range_end)) { 138219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 139219820Sjeff "Differ by InformInfo.LIDRange\n"); 140219820Sjeff goto Exit; 141219820Sjeff } 142219820Sjeff } 143219820Sjeff 144219820Sjeff if (p_infr->inform_record.inform_info.trap_type != 145219820Sjeff p_infr_rec->inform_record.inform_info.trap_type) { 146219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 147219820Sjeff "Differ by InformInfo.TrapType\n"); 148219820Sjeff goto Exit; 149219820Sjeff } 150219820Sjeff 151219820Sjeff if (p_infr->inform_record.inform_info.is_generic != 152219820Sjeff p_infr_rec->inform_record.inform_info.is_generic) { 153219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 154219820Sjeff "Differ by InformInfo.IsGeneric\n"); 155219820Sjeff goto Exit; 156219820Sjeff } 157219820Sjeff 158219820Sjeff if (p_infr->inform_record.inform_info.is_generic) { 159219820Sjeff if (p_infr->inform_record.inform_info.g_or_v.generic.trap_num != 160219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.generic. 161219820Sjeff trap_num) 162219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 163219820Sjeff "Differ by InformInfo.Generic.TrapNumber\n"); 164219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.generic. 165219820Sjeff qpn_resp_time_val != 166219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.generic. 167219820Sjeff qpn_resp_time_val) 168219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 169219820Sjeff "Differ by InformInfo.Generic.QPNRespTimeVal\n"); 170219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.generic. 171219820Sjeff node_type_msb != 172219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.generic. 173219820Sjeff node_type_msb) 174219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 175219820Sjeff "Differ by InformInfo.Generic.NodeTypeMSB\n"); 176219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.generic. 177219820Sjeff node_type_lsb != 178219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.generic. 179219820Sjeff node_type_lsb) 180219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 181219820Sjeff "Differ by InformInfo.Generic.NodeTypeLSB\n"); 182219820Sjeff else 183219820Sjeff status = CL_SUCCESS; 184219820Sjeff } else { 185219820Sjeff if (p_infr->inform_record.inform_info.g_or_v.vend.dev_id != 186219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id) 187219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 188219820Sjeff "Differ by InformInfo.Vendor.DeviceID\n"); 189219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.vend. 190219820Sjeff qpn_resp_time_val != 191219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.vend. 192219820Sjeff qpn_resp_time_val) 193219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 194219820Sjeff "Differ by InformInfo.Vendor.QPNRespTimeVal\n"); 195219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.vend. 196219820Sjeff vendor_id_msb != 197219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.vend. 198219820Sjeff vendor_id_msb) 199219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 200219820Sjeff "Differ by InformInfo.Vendor.VendorIdMSB\n"); 201219820Sjeff else if (p_infr->inform_record.inform_info.g_or_v.vend. 202219820Sjeff vendor_id_lsb != 203219820Sjeff p_infr_rec->inform_record.inform_info.g_or_v.vend. 204219820Sjeff vendor_id_lsb) 205219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 206219820Sjeff "Differ by InformInfo.Vendor.VendorIdLSB\n"); 207219820Sjeff else 208219820Sjeff status = CL_SUCCESS; 209219820Sjeff } 210219820Sjeff 211219820SjeffExit: 212219820Sjeff OSM_LOG_EXIT(p_log); 213219820Sjeff return status; 214219820Sjeff} 215219820Sjeff 216219820Sjeff/********************************************************************** 217219820Sjeff **********************************************************************/ 218219820Sjeffosm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn, 219219820Sjeff IN osm_log_t * p_log, 220219820Sjeff IN osm_infr_t * const p_infr_rec) 221219820Sjeff{ 222219820Sjeff cl_list_item_t *p_list_item; 223219820Sjeff 224219820Sjeff OSM_LOG_ENTER(p_log); 225219820Sjeff 226219820Sjeff dump_all_informs(p_subn, p_log); 227219820Sjeff 228219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n"); 229219820Sjeff osm_dump_inform_info(p_log, &(p_infr_rec->inform_record.inform_info), 230219820Sjeff OSM_LOG_DEBUG); 231219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n", 232219820Sjeff cl_qlist_count(&p_subn->sa_infr_list)); 233219820Sjeff 234219820Sjeff p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list, 235219820Sjeff __match_inf_rec, p_infr_rec); 236219820Sjeff 237219820Sjeff if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list)) 238219820Sjeff p_list_item = NULL; 239219820Sjeff 240219820Sjeff OSM_LOG_EXIT(p_log); 241219820Sjeff return (osm_infr_t *) p_list_item; 242219820Sjeff} 243219820Sjeff 244219820Sjeff/********************************************************************** 245219820Sjeff **********************************************************************/ 246219820Sjeffvoid 247219820Sjeffosm_infr_insert_to_db(IN osm_subn_t * p_subn, 248219820Sjeff IN osm_log_t * p_log, IN osm_infr_t * p_infr) 249219820Sjeff{ 250219820Sjeff OSM_LOG_ENTER(p_log); 251219820Sjeff 252219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 253219820Sjeff "Inserting new InformInfo Record into Database\n"); 254219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n", 255219820Sjeff cl_qlist_count(&p_subn->sa_infr_list)); 256219820Sjeff dump_all_informs(p_subn, p_log); 257219820Sjeff 258219820Sjeff#if 0 259219820Sjeff osm_dump_inform_info(p_log, 260219820Sjeff &(p_infr->inform_record.inform_info), 261219820Sjeff OSM_LOG_DEBUG); 262219820Sjeff#endif 263219820Sjeff 264219820Sjeff cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item); 265219820Sjeff 266219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n", 267219820Sjeff cl_qlist_count(&p_subn->sa_infr_list)); 268219820Sjeff dump_all_informs(p_subn, p_log); 269219820Sjeff OSM_LOG_EXIT(p_log); 270219820Sjeff} 271219820Sjeff 272219820Sjeff/********************************************************************** 273219820Sjeff **********************************************************************/ 274219820Sjeffvoid 275219820Sjeffosm_infr_remove_from_db(IN osm_subn_t * p_subn, 276219820Sjeff IN osm_log_t * p_log, IN osm_infr_t * p_infr) 277219820Sjeff{ 278219820Sjeff char gid_str[INET6_ADDRSTRLEN]; 279219820Sjeff OSM_LOG_ENTER(p_log); 280219820Sjeff 281219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s" 282219820Sjeff " Enum:0x%X from Database\n", 283219820Sjeff inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw, 284219820Sjeff gid_str, sizeof gid_str), 285219820Sjeff p_infr->inform_record.subscriber_enum); 286219820Sjeff 287219820Sjeff osm_dump_inform_info(p_log, &(p_infr->inform_record.inform_info), 288219820Sjeff OSM_LOG_DEBUG); 289219820Sjeff 290219820Sjeff cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item); 291219820Sjeff 292219820Sjeff osm_infr_delete(p_infr); 293219820Sjeff 294219820Sjeff OSM_LOG_EXIT(p_log); 295219820Sjeff} 296219820Sjeff 297219820Sjeff/********************************************************************** 298219820Sjeff * Send a report: 299219820Sjeff * Given a target address to send to and the notice. 300219820Sjeff * We need to send SubnAdmReport 301219820Sjeff **********************************************************************/ 302219820Sjeffstatic ib_api_status_t __osm_send_report(IN osm_infr_t * p_infr_rec, /* the informinfo */ 303219820Sjeff IN ib_mad_notice_attr_t * p_ntc /* notice to send */ 304219820Sjeff ) 305219820Sjeff{ 306219820Sjeff osm_madw_t *p_report_madw; 307219820Sjeff ib_mad_notice_attr_t *p_report_ntc; 308219820Sjeff ib_mad_t *p_mad; 309219820Sjeff ib_sa_mad_t *p_sa_mad; 310219820Sjeff static atomic32_t trap_fwd_trans_id = 0x02DAB000; 311219820Sjeff ib_api_status_t status = IB_SUCCESS; 312219820Sjeff osm_log_t *p_log = p_infr_rec->sa->p_log; 313219820Sjeff 314219820Sjeff OSM_LOG_ENTER(p_log); 315219820Sjeff 316219820Sjeff /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */ 317219820Sjeff 318219820Sjeff /* it is better to use LIDs since the GIDs might not be there for SMI traps */ 319219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID:%u" 320219820Sjeff " to InformInfo LID: %u TID:0x%X\n", 321219820Sjeff cl_ntoh16(p_ntc->issuer_lid), 322219820Sjeff cl_ntoh16(p_infr_rec->report_addr.dest_lid), trap_fwd_trans_id); 323219820Sjeff 324219820Sjeff /* get the MAD to send */ 325219820Sjeff p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool, 326219820Sjeff p_infr_rec->h_bind, MAD_BLOCK_SIZE, 327219820Sjeff &(p_infr_rec->report_addr)); 328219820Sjeff 329219820Sjeff p_report_madw->resp_expected = TRUE; 330219820Sjeff 331219820Sjeff if (!p_report_madw) { 332219820Sjeff OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203" 333219820Sjeff "osm_mad_pool_get failed\n"); 334219820Sjeff status = IB_ERROR; 335219820Sjeff goto Exit; 336219820Sjeff } 337219820Sjeff 338219820Sjeff /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ 339219820Sjeff p_mad = osm_madw_get_mad_ptr(p_report_madw); 340219820Sjeff ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT, 341219820Sjeff cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id)), 342219820Sjeff IB_MAD_ATTR_NOTICE, 0); 343219820Sjeff 344219820Sjeff p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw); 345219820Sjeff 346219820Sjeff p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data); 347219820Sjeff 348219820Sjeff /* copy the notice */ 349219820Sjeff *p_report_ntc = *p_ntc; 350219820Sjeff 351219820Sjeff /* The TRUE is for: response is expected */ 352219820Sjeff osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE); 353219820Sjeff 354219820SjeffExit: 355219820Sjeff OSM_LOG_EXIT(p_log); 356219820Sjeff return (status); 357219820Sjeff} 358219820Sjeff 359219820Sjeff/********************************************************************** 360219820Sjeff * This routine compares a given Notice and a ListItem of InformInfo type. 361219820Sjeff * PREREQUISITE: 362219820Sjeff * The Notice.GID should be pre-filled with the trap generator GID 363219820Sjeff **********************************************************************/ 364219820Sjeffstatic void 365219820Sjeff__match_notice_to_inf_rec(IN cl_list_item_t * const p_list_item, 366219820Sjeff IN void *context) 367219820Sjeff{ 368219820Sjeff osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context; 369219820Sjeff ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; 370219820Sjeff cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list; 371219820Sjeff osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item; 372219820Sjeff ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); 373219820Sjeff cl_status_t status = CL_NOT_FOUND; 374219820Sjeff osm_log_t *p_log = p_infr_rec->sa->p_log; 375219820Sjeff osm_subn_t *p_subn = p_infr_rec->sa->p_subn; 376219820Sjeff ib_gid_t source_gid; 377219820Sjeff osm_port_t *p_src_port; 378219820Sjeff osm_port_t *p_dest_port; 379219820Sjeff 380219820Sjeff OSM_LOG_ENTER(p_log); 381219820Sjeff 382219820Sjeff /* matching rules 383219820Sjeff * InformInfo Notice 384219820Sjeff * GID IssuerGID if non zero must match the trap 385219820Sjeff * LIDRange IssuerLID apply only if GID=0 386219820Sjeff * IsGeneric IsGeneric is compulsory and must match the trap 387219820Sjeff * Type Type if not 0xFFFF must match 388219820Sjeff * TrapNumber TrapNumber if not 0xFFFF must match 389219820Sjeff * DeviceId DeviceID if not 0xFFFF must match 390219820Sjeff * QPN dont care 391219820Sjeff * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation 392219820Sjeff * VendorID VendorID match or 0xFFFFFF 393219820Sjeff */ 394219820Sjeff 395219820Sjeff /* GID IssuerGID if non zero must match the trap */ 396219820Sjeff if (p_ii->gid.unicast.prefix != 0 397219820Sjeff || p_ii->gid.unicast.interface_id != 0) { 398219820Sjeff /* match by GID */ 399219820Sjeff if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), 400219820Sjeff sizeof(ib_gid_t))) { 401219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n"); 402219820Sjeff goto Exit; 403219820Sjeff } 404219820Sjeff } else { 405219820Sjeff /* LIDRange IssuerLID apply only if GID=0 */ 406219820Sjeff /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */ 407219820Sjeff if (p_ii->lid_range_begin != 0xFFFF) { 408219820Sjeff /* a real lid range is given - check it */ 409219820Sjeff if ((cl_hton16(p_ii->lid_range_begin) > 410219820Sjeff cl_hton16(p_ntc->issuer_lid)) 411219820Sjeff || (cl_hton16(p_ntc->issuer_lid) > 412219820Sjeff cl_hton16(p_ii->lid_range_end))) { 413219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 414219820Sjeff "Mismatch by LID Range. Needed: %u <= %u <= %u\n", 415219820Sjeff cl_hton16(p_ii->lid_range_begin), 416219820Sjeff cl_hton16(p_ntc->issuer_lid), 417219820Sjeff cl_hton16(p_ii->lid_range_end)); 418219820Sjeff goto Exit; 419219820Sjeff } 420219820Sjeff } 421219820Sjeff } 422219820Sjeff 423219820Sjeff /* IsGeneric IsGeneric is compulsory and must match the trap */ 424219820Sjeff if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) || 425219820Sjeff (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) { 426219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n"); 427219820Sjeff goto Exit; 428219820Sjeff } 429219820Sjeff 430219820Sjeff /* Type Type if not 0xFFFF must match */ 431219820Sjeff if ((p_ii->trap_type != 0xFFFF) && 432219820Sjeff (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) { 433219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n"); 434219820Sjeff goto Exit; 435219820Sjeff } 436219820Sjeff 437219820Sjeff /* based on generic type */ 438219820Sjeff if (p_ii->is_generic) { 439219820Sjeff /* TrapNumber TrapNumber if not 0xFFFF must match */ 440219820Sjeff if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) && 441219820Sjeff (p_ii->g_or_v.generic.trap_num != 442219820Sjeff p_ntc->g_or_v.generic.trap_num)) { 443219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n"); 444219820Sjeff goto Exit; 445219820Sjeff } 446219820Sjeff 447219820Sjeff /* ProducerType ProducerType match or 0xFFFFFF */ 448219820Sjeff if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF) 449219820Sjeff && (ib_inform_info_get_prod_type(p_ii) != 450219820Sjeff ib_notice_get_prod_type(p_ntc))) { 451219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 452219820Sjeff "Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n", 453219820Sjeff cl_ntoh32(ib_inform_info_get_prod_type(p_ii)), 454219820Sjeff ib_get_producer_type_str 455219820Sjeff (ib_inform_info_get_prod_type(p_ii)), 456219820Sjeff cl_ntoh32(ib_notice_get_prod_type(p_ntc)), 457219820Sjeff ib_get_producer_type_str(ib_notice_get_prod_type 458219820Sjeff (p_ntc))); 459219820Sjeff goto Exit; 460219820Sjeff } 461219820Sjeff } else { 462219820Sjeff /* DeviceId DeviceID if not 0xFFFF must match */ 463219820Sjeff if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) && 464219820Sjeff (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) { 465219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n"); 466219820Sjeff goto Exit; 467219820Sjeff } 468219820Sjeff 469219820Sjeff /* VendorID VendorID match or 0xFFFFFF */ 470219820Sjeff if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) && 471219820Sjeff (ib_inform_info_get_vend_id(p_ii) != 472219820Sjeff ib_notice_get_vend_id(p_ntc))) { 473219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Vendor ID\n"); 474219820Sjeff goto Exit; 475219820Sjeff } 476219820Sjeff } 477219820Sjeff 478219820Sjeff /* Check if there is a pkey match. o13-17.1.1 */ 479219820Sjeff /* Check if the issuer of the trap is the SM. If it is, then the gid 480219820Sjeff comparison should be done on the trap source (saved as the gid in the 481219820Sjeff data details field). 482219820Sjeff If the issuer gid is not the SM - then it is the guid of the trap 483219820Sjeff source */ 484219820Sjeff if ((cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) == 485219820Sjeff p_subn->opt.subnet_prefix) 486219820Sjeff && (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) == 487219820Sjeff p_subn->sm_port_guid)) 488219820Sjeff /* The issuer is the SM then this is trap 64-67 - compare the gid 489219820Sjeff with the gid saved on the data details */ 490219820Sjeff source_gid = p_ntc->data_details.ntc_64_67.gid; 491219820Sjeff else 492219820Sjeff source_gid = p_ntc->issuer_gid; 493219820Sjeff 494219820Sjeff p_src_port = 495219820Sjeff osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id); 496219820Sjeff if (!p_src_port) { 497219820Sjeff OSM_LOG(p_log, OSM_LOG_INFO, 498219820Sjeff "Cannot find source port with GUID:0x%016" PRIx64 "\n", 499219820Sjeff cl_ntoh64(source_gid.unicast.interface_id)); 500219820Sjeff goto Exit; 501219820Sjeff } 502219820Sjeff 503219820Sjeff p_dest_port = 504219820Sjeff cl_ptr_vector_get(&p_subn->port_lid_tbl, 505219820Sjeff cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 506219820Sjeff if (!p_dest_port) { 507219820Sjeff OSM_LOG(p_log, OSM_LOG_INFO, 508219820Sjeff "Cannot find destination port with LID:%u\n", 509219820Sjeff cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 510219820Sjeff goto Exit; 511219820Sjeff } 512219820Sjeff 513219820Sjeff if (osm_port_share_pkey(p_log, p_src_port, p_dest_port) == FALSE) { 514219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n"); 515219820Sjeff /* According to o13-17.1.2 - If this informInfo does not have 516219820Sjeff lid_range_begin of 0xFFFF, then this informInfo request 517219820Sjeff should be removed from database */ 518219820Sjeff if (p_ii->lid_range_begin != 0xFFFF) { 519219820Sjeff OSM_LOG(p_log, OSM_LOG_VERBOSE, 520219820Sjeff "Pkey mismatch on lid_range_begin != 0xFFFF. " 521219820Sjeff "Need to remove this informInfo from db\n"); 522219820Sjeff /* add the informInfo record to the remove_infr list */ 523219820Sjeff cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec); 524219820Sjeff } 525219820Sjeff goto Exit; 526219820Sjeff } 527219820Sjeff 528219820Sjeff /* send the report to the address provided in the inform record */ 529219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n"); 530219820Sjeff __osm_send_report(p_infr_rec, p_ntc); 531219820Sjeff status = CL_SUCCESS; 532219820Sjeff 533219820SjeffExit: 534219820Sjeff OSM_LOG_EXIT(p_log); 535219820Sjeff} 536219820Sjeff 537219820Sjeff/********************************************************************** 538219820Sjeff * Once a Trap was received by osm_trap_rcv, or a Trap sourced by 539219820Sjeff * the SM was sent (Traps 64-67), this routine is called with a copy of 540219820Sjeff * the notice data. 541219820Sjeff * Given a notice attribute - compare and see if it matches the InformInfo 542219820Sjeff * element and if it does - call the Report(Notice) for the 543219820Sjeff * target QP registered by the address stored in the InformInfo element 544219820Sjeff **********************************************************************/ 545219820Sjeffib_api_status_t 546219820Sjeffosm_report_notice(IN osm_log_t * const p_log, 547219820Sjeff IN osm_subn_t * p_subn, IN ib_mad_notice_attr_t * p_ntc) 548219820Sjeff{ 549219820Sjeff char gid_str[INET6_ADDRSTRLEN]; 550219820Sjeff osm_infr_match_ctxt_t context; 551219820Sjeff cl_list_t infr_to_remove_list; 552219820Sjeff osm_infr_t *p_infr_rec; 553219820Sjeff osm_infr_t *p_next_infr_rec; 554219820Sjeff 555219820Sjeff OSM_LOG_ENTER(p_log); 556219820Sjeff 557219820Sjeff /* 558219820Sjeff * we must make sure we are ready for this... 559219820Sjeff * note that the trap receivers might be initialized before 560219820Sjeff * the osm_infr_init call is performed. 561219820Sjeff */ 562219820Sjeff if (p_subn->sa_infr_list.state != CL_INITIALIZED) { 563219820Sjeff OSM_LOG(p_log, OSM_LOG_DEBUG, 564219820Sjeff "Ignoring Notice Reports since Inform List is not initialized yet!\n"); 565219820Sjeff return (IB_ERROR); 566219820Sjeff } 567219820Sjeff 568219820Sjeff /* an official Event information log */ 569219820Sjeff if (ib_notice_is_generic(p_ntc)) 570219820Sjeff OSM_LOG(p_log, OSM_LOG_INFO, 571219820Sjeff "Reporting Generic Notice type:%u num:%u (%s)" 572219820Sjeff " from LID:%u GID:%s\n", 573219820Sjeff ib_notice_get_type(p_ntc), 574219820Sjeff cl_ntoh16(p_ntc->g_or_v.generic.trap_num), 575219820Sjeff ib_get_trap_str(p_ntc->g_or_v.generic.trap_num), 576219820Sjeff cl_ntoh16(p_ntc->issuer_lid), 577219820Sjeff inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str, 578219820Sjeff sizeof gid_str)); 579219820Sjeff else 580219820Sjeff OSM_LOG(p_log, OSM_LOG_INFO, 581219820Sjeff "Reporting Vendor Notice type:%u vend:%u dev:%u" 582219820Sjeff " from LID:%u GID:%s\n", 583219820Sjeff ib_notice_get_type(p_ntc), 584219820Sjeff cl_ntoh32(ib_notice_get_vend_id(p_ntc)), 585219820Sjeff cl_ntoh16(p_ntc->g_or_v.vend.dev_id), 586219820Sjeff cl_ntoh16(p_ntc->issuer_lid), 587219820Sjeff inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str, 588219820Sjeff sizeof gid_str)); 589219820Sjeff 590219820Sjeff /* Create a list that will hold all the infr records that should 591219820Sjeff be removed due to violation. o13-17.1.2 */ 592219820Sjeff cl_list_construct(&infr_to_remove_list); 593219820Sjeff cl_list_init(&infr_to_remove_list, 5); 594219820Sjeff context.p_remove_infr_list = &infr_to_remove_list; 595219820Sjeff context.p_ntc = p_ntc; 596219820Sjeff 597219820Sjeff /* go over all inform info available at the subnet */ 598219820Sjeff /* try match to the given notice and send if match */ 599219820Sjeff cl_qlist_apply_func(&(p_subn->sa_infr_list), 600219820Sjeff __match_notice_to_inf_rec, &context); 601219820Sjeff 602219820Sjeff /* If we inserted items into the infr_to_remove_list - we need to 603219820Sjeff remove them */ 604219820Sjeff p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 605219820Sjeff while (p_infr_rec != NULL) { 606219820Sjeff p_next_infr_rec = 607219820Sjeff (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 608219820Sjeff osm_infr_remove_from_db(p_subn, p_log, p_infr_rec); 609219820Sjeff p_infr_rec = p_next_infr_rec; 610219820Sjeff } 611219820Sjeff cl_list_destroy(&infr_to_remove_list); 612219820Sjeff 613219820Sjeff OSM_LOG_EXIT(p_log); 614219820Sjeff 615219820Sjeff return (IB_SUCCESS); 616219820Sjeff} 617