1 /* 2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2015 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 inform record functions. 41 */ 42 43 #if HAVE_CONFIG_H 44 # include <config.h> 45 #endif /* HAVE_CONFIG_H */ 46 47 #include <stdlib.h> 48 #include <string.h> 49 #include <arpa/inet.h> 50 #include <sys/socket.h> 51 #include <complib/cl_debug.h> 52 #include <opensm/osm_file_ids.h> 53 #define FILE_ID OSM_FILE_INFORM_C 54 #include <opensm/osm_helper.h> 55 #include <opensm/osm_inform.h> 56 #include <vendor/osm_vendor_api.h> 57 #include <opensm/osm_pkey.h> 58 #include <opensm/osm_sa.h> 59 #include <opensm/osm_opensm.h> 60 61 typedef struct osm_infr_match_ctxt { 62 cl_list_t *p_remove_infr_list; 63 ib_mad_notice_attr_t *p_ntc; 64 } osm_infr_match_ctxt_t; 65 66 void osm_infr_delete(IN osm_infr_t * p_infr) 67 { 68 free(p_infr); 69 } 70 71 osm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec) 72 { 73 osm_infr_t *p_infr; 74 75 CL_ASSERT(p_infr_rec); 76 77 p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t)); 78 if (p_infr) 79 memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t)); 80 81 return p_infr; 82 } 83 84 static void dump_all_informs(IN const osm_subn_t * p_subn, IN osm_log_t * p_log) 85 { 86 cl_list_item_t *p_list_item; 87 88 if (!OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_DEBUG)) 89 return; 90 91 p_list_item = cl_qlist_head(&p_subn->sa_infr_list); 92 while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { 93 osm_dump_inform_info_v2(p_log, 94 &((osm_infr_t *) p_list_item)-> 95 inform_record.inform_info, FILE_ID, OSM_LOG_DEBUG); 96 p_list_item = cl_qlist_next(p_list_item); 97 } 98 } 99 100 /********************************************************************** 101 * Match an infr by the InformInfo and Address vector 102 **********************************************************************/ 103 static cl_status_t match_inf_rec(IN const cl_list_item_t * p_list_item, 104 IN void *context) 105 { 106 osm_infr_t *p_infr_rec = (osm_infr_t *) context; 107 osm_infr_t *p_infr = (osm_infr_t *) p_list_item; 108 ib_inform_info_t *p_ii_rec = &p_infr_rec->inform_record.inform_info; 109 ib_inform_info_t *p_ii = &p_infr->inform_record.inform_info; 110 osm_log_t *p_log = p_infr_rec->sa->p_log; 111 cl_status_t status = CL_NOT_FOUND; 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 /* if inform_info.gid is not zero, ignore lid range */ 122 if (ib_gid_is_notzero(&p_ii_rec->gid)) { 123 if (memcmp(&p_ii->gid, &p_ii_rec->gid, sizeof(p_ii->gid))) { 124 OSM_LOG(p_log, OSM_LOG_DEBUG, 125 "Differ by InformInfo.gid\n"); 126 goto Exit; 127 } 128 } else { 129 if ((p_ii->lid_range_begin != p_ii_rec->lid_range_begin) || 130 (p_ii->lid_range_end != p_ii_rec->lid_range_end)) { 131 OSM_LOG(p_log, OSM_LOG_DEBUG, 132 "Differ by InformInfo.LIDRange\n"); 133 goto Exit; 134 } 135 } 136 137 if (p_ii->trap_type != p_ii_rec->trap_type) { 138 OSM_LOG(p_log, OSM_LOG_DEBUG, 139 "Differ by InformInfo.TrapType\n"); 140 goto Exit; 141 } 142 143 if (p_ii->is_generic != p_ii_rec->is_generic) { 144 OSM_LOG(p_log, OSM_LOG_DEBUG, 145 "Differ by InformInfo.IsGeneric\n"); 146 goto Exit; 147 } 148 149 if (p_ii->is_generic) { 150 if (p_ii->g_or_v.generic.trap_num != 151 p_ii_rec->g_or_v.generic.trap_num) 152 OSM_LOG(p_log, OSM_LOG_DEBUG, 153 "Differ by InformInfo.Generic.TrapNumber\n"); 154 else if (p_ii->g_or_v.generic.qpn_resp_time_val != 155 p_ii_rec->g_or_v.generic.qpn_resp_time_val) 156 OSM_LOG(p_log, OSM_LOG_DEBUG, 157 "Differ by InformInfo.Generic.QPNRespTimeVal\n"); 158 else if (p_ii->g_or_v.generic.node_type_msb != 159 p_ii_rec->g_or_v.generic.node_type_msb) 160 OSM_LOG(p_log, OSM_LOG_DEBUG, 161 "Differ by InformInfo.Generic.NodeTypeMSB\n"); 162 else if (p_ii->g_or_v.generic.node_type_lsb != 163 p_ii_rec->g_or_v.generic.node_type_lsb) 164 OSM_LOG(p_log, OSM_LOG_DEBUG, 165 "Differ by InformInfo.Generic.NodeTypeLSB\n"); 166 else 167 status = CL_SUCCESS; 168 } else { 169 if (p_ii->g_or_v.vend.dev_id != p_ii_rec->g_or_v.vend.dev_id) 170 OSM_LOG(p_log, OSM_LOG_DEBUG, 171 "Differ by InformInfo.Vendor.DeviceID\n"); 172 else if (p_ii->g_or_v.vend.qpn_resp_time_val != 173 p_ii_rec->g_or_v.vend.qpn_resp_time_val) 174 OSM_LOG(p_log, OSM_LOG_DEBUG, 175 "Differ by InformInfo.Vendor.QPNRespTimeVal\n"); 176 else if (p_ii->g_or_v.vend.vendor_id_msb != 177 p_ii_rec->g_or_v.vend.vendor_id_msb) 178 OSM_LOG(p_log, OSM_LOG_DEBUG, 179 "Differ by InformInfo.Vendor.VendorIdMSB\n"); 180 else if (p_ii->g_or_v.vend.vendor_id_lsb != 181 p_ii_rec->g_or_v.vend.vendor_id_lsb) 182 OSM_LOG(p_log, OSM_LOG_DEBUG, 183 "Differ by InformInfo.Vendor.VendorIdLSB\n"); 184 else 185 status = CL_SUCCESS; 186 } 187 188 Exit: 189 OSM_LOG_EXIT(p_log); 190 return status; 191 } 192 193 osm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn, 194 IN osm_log_t * p_log, 195 IN osm_infr_t * p_infr_rec) 196 { 197 cl_list_item_t *p_list_item; 198 199 OSM_LOG_ENTER(p_log); 200 201 dump_all_informs(p_subn, p_log); 202 203 OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n"); 204 osm_dump_inform_info_v2(p_log, &(p_infr_rec->inform_record.inform_info), 205 FILE_ID, OSM_LOG_DEBUG); 206 OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n", 207 cl_qlist_count(&p_subn->sa_infr_list)); 208 209 p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list, 210 match_inf_rec, p_infr_rec); 211 212 if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list)) 213 p_list_item = NULL; 214 215 OSM_LOG_EXIT(p_log); 216 return (osm_infr_t *) p_list_item; 217 } 218 219 void osm_infr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, 220 IN osm_infr_t * p_infr) 221 { 222 OSM_LOG_ENTER(p_log); 223 224 OSM_LOG(p_log, OSM_LOG_DEBUG, 225 "Inserting new InformInfo Record into Database\n"); 226 OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n", 227 cl_qlist_count(&p_subn->sa_infr_list)); 228 dump_all_informs(p_subn, p_log); 229 230 #if 0 231 osm_dump_inform_info_v2(p_log, 232 &(p_infr->inform_record.inform_info), 233 FILE_ID, OSM_LOG_DEBUG); 234 #endif 235 236 cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item); 237 p_subn->p_osm->sa.dirty = TRUE; 238 239 OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n", 240 cl_qlist_count(&p_subn->sa_infr_list)); 241 dump_all_informs(p_subn, p_log); 242 OSM_LOG_EXIT(p_log); 243 } 244 245 void osm_infr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log, 246 IN osm_infr_t * p_infr) 247 { 248 char gid_str[INET6_ADDRSTRLEN]; 249 OSM_LOG_ENTER(p_log); 250 251 OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s" 252 " Enum:0x%X from Database\n", 253 inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw, 254 gid_str, sizeof gid_str), 255 p_infr->inform_record.subscriber_enum); 256 257 osm_dump_inform_info_v2(p_log, &(p_infr->inform_record.inform_info), 258 FILE_ID, OSM_LOG_DEBUG); 259 260 cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item); 261 p_subn->p_osm->sa.dirty = TRUE; 262 263 osm_infr_delete(p_infr); 264 265 OSM_LOG_EXIT(p_log); 266 } 267 268 ib_api_status_t osm_infr_remove_subscriptions(IN osm_subn_t * p_subn, 269 IN osm_log_t * p_log, 270 IN ib_net64_t port_guid) 271 { 272 cl_list_item_t *p_list_item; 273 osm_infr_t *p_infr; 274 ib_api_status_t status = CL_NOT_FOUND; 275 276 OSM_LOG_ENTER(p_log); 277 278 /* go over all inform info available at the subnet */ 279 /* match to the given GID and delete subscriptions if match */ 280 p_list_item = cl_qlist_head(&p_subn->sa_infr_list); 281 while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) { 282 283 p_infr = (osm_infr_t *)p_list_item; 284 p_list_item = cl_qlist_next(p_list_item); 285 286 if (port_guid != p_infr->inform_record.subscriber_gid.unicast.interface_id) 287 continue; 288 289 /* Remove this event subscription */ 290 osm_infr_remove_from_db(p_subn, p_log, p_infr); 291 292 status = CL_SUCCESS; 293 } 294 295 OSM_LOG_EXIT(p_log); 296 return (status); 297 } 298 299 /********************************************************************** 300 * Send a report: 301 * Given a target address to send to and the notice. 302 * We need to send SubnAdmReport 303 **********************************************************************/ 304 static ib_api_status_t send_report(IN osm_infr_t * p_infr_rec, /* the informinfo */ 305 IN ib_mad_notice_attr_t * p_ntc /* notice to send */ 306 ) 307 { 308 osm_madw_t *p_report_madw; 309 ib_mad_notice_attr_t *p_report_ntc; 310 ib_mad_t *p_mad; 311 ib_sa_mad_t *p_sa_mad; 312 static atomic32_t trap_fwd_trans_id = 0x02DAB000; 313 ib_api_status_t status = IB_SUCCESS; 314 osm_log_t *p_log = p_infr_rec->sa->p_log; 315 ib_net64_t tid; 316 317 OSM_LOG_ENTER(p_log); 318 319 /* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */ 320 321 /* it is better to use LIDs since the GIDs might not be there for SMI traps */ 322 OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID %u" 323 " to InformInfo LID %u GUID 0x%" PRIx64 ", TID 0x%X\n", 324 cl_ntoh16(p_ntc->issuer_lid), 325 cl_ntoh16(p_infr_rec->report_addr.dest_lid), 326 cl_ntoh64(p_infr_rec->inform_record.subscriber_gid.unicast.interface_id), 327 trap_fwd_trans_id); 328 329 /* get the MAD to send */ 330 p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool, 331 p_infr_rec->h_bind, MAD_BLOCK_SIZE, 332 &(p_infr_rec->report_addr)); 333 334 if (!p_report_madw) { 335 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203: " 336 "Cannot send report to LID %u, osm_mad_pool_get failed\n", 337 cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 338 status = IB_ERROR; 339 goto Exit; 340 } 341 342 p_report_madw->resp_expected = TRUE; 343 344 /* advance trap trans id (cant simply ++ on some systems inside ntoh) */ 345 tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) & 346 (uint64_t) (0xFFFFFFFF)); 347 if (trap_fwd_trans_id == 0) 348 tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) & 349 (uint64_t) (0xFFFFFFFF)); 350 p_mad = osm_madw_get_mad_ptr(p_report_madw); 351 ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT, 352 tid, IB_MAD_ATTR_NOTICE, 0); 353 354 p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw); 355 356 p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data); 357 358 /* copy the notice */ 359 *p_report_ntc = *p_ntc; 360 361 /* The TRUE is for: response is expected */ 362 osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE); 363 364 Exit: 365 OSM_LOG_EXIT(p_log); 366 return status; 367 } 368 369 static int is_access_permitted(osm_infr_t *p_infr_rec, 370 osm_infr_match_ctxt_t *p_infr_match ) 371 { 372 cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list; 373 ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); 374 ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; 375 uint16_t trap_num = cl_ntoh16(p_ntc->g_or_v.generic.trap_num); 376 osm_subn_t *p_subn = p_infr_rec->sa->p_subn; 377 osm_log_t *p_log = p_infr_rec->sa->p_log; 378 osm_mgrp_t *p_mgrp; 379 ib_gid_t source_gid; 380 osm_port_t *p_src_port; 381 osm_port_t *p_dest_port; 382 383 /* In case of SM_GID_IN_SERVICE_TRAP(64) or SM_GID_OUT_OF_SERVICE_TRAP(65) traps 384 the source gid comparison should be done on the trap source (saved 385 as the gid in the data details field). 386 For traps SM_MGID_CREATED_TRAP(66) or SM_MGID_DESTROYED_TRAP(67) 387 the data details gid is the MGID. 388 We need to check whether the subscriber has a compatible 389 pkey with MC group. 390 In all other cases the issuer gid is the trap source. 391 */ 392 if (trap_num >= SM_GID_IN_SERVICE_TRAP && 393 trap_num <= SM_MGID_DESTROYED_TRAP) 394 /* The issuer of these traps is the SM so source_gid 395 is the gid saved on the data details */ 396 source_gid = p_ntc->data_details.ntc_64_67.gid; 397 else 398 source_gid = p_ntc->issuer_gid; 399 400 p_dest_port = osm_get_port_by_lid(p_subn, 401 p_infr_rec->report_addr.dest_lid); 402 if (!p_dest_port) { 403 OSM_LOG(p_log, OSM_LOG_INFO, 404 "Cannot find destination port with LID:%u\n", 405 cl_ntoh16(p_infr_rec->report_addr.dest_lid)); 406 goto Exit; 407 } 408 409 /* Check if there is a pkey match. o13-17.1.1 */ 410 switch (trap_num) { 411 case SM_MGID_CREATED_TRAP: 412 case SM_MGID_DESTROYED_TRAP: 413 p_mgrp = osm_get_mgrp_by_mgid(p_subn, &source_gid); 414 if (!p_mgrp) { 415 char gid_str[INET6_ADDRSTRLEN]; 416 OSM_LOG(p_log, OSM_LOG_INFO, 417 "Cannot find MGID %s\n", 418 inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str)); 419 goto Exit; 420 } 421 422 if (!osm_physp_has_pkey(p_log, 423 p_mgrp->mcmember_rec.pkey, 424 p_dest_port->p_physp)) { 425 char gid_str[INET6_ADDRSTRLEN]; 426 OSM_LOG(p_log, OSM_LOG_INFO, 427 "MGID %s and port GUID:0x%016" PRIx64 " do not share same pkey\n", 428 inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str), 429 cl_ntoh64(p_dest_port->guid)); 430 goto Exit; 431 } 432 break; 433 434 default: 435 p_src_port = 436 osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id); 437 if (!p_src_port) { 438 OSM_LOG(p_log, OSM_LOG_INFO, 439 "Cannot find source port with GUID:0x%016" PRIx64 "\n", 440 cl_ntoh64(source_gid.unicast.interface_id)); 441 goto Exit; 442 } 443 444 445 if (osm_port_share_pkey(p_log, p_src_port, p_dest_port, 446 p_subn->opt.allow_both_pkeys) == FALSE) { 447 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n"); 448 /* According to o13-17.1.2 - If this informInfo 449 does not have lid_range_begin of 0xFFFF, 450 then this informInfo request should be 451 removed from database */ 452 if (p_ii->lid_range_begin != 0xFFFF) { 453 OSM_LOG(p_log, OSM_LOG_VERBOSE, 454 "Pkey mismatch on lid_range_begin != 0xFFFF. " 455 "Need to remove this informInfo from db\n"); 456 /* add the informInfo record to the remove_infr list */ 457 cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec); 458 } 459 goto Exit; 460 } 461 break; 462 } 463 464 return 1; 465 Exit: 466 return 0; 467 } 468 469 470 /********************************************************************** 471 * This routine compares a given Notice and a ListItem of InformInfo type. 472 * PREREQUISITE: 473 * The Notice.GID should be pre-filled with the trap generator GID 474 **********************************************************************/ 475 static void match_notice_to_inf_rec(IN cl_list_item_t * p_list_item, 476 IN void *context) 477 { 478 osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context; 479 ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc; 480 osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item; 481 ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info); 482 osm_log_t *p_log = p_infr_rec->sa->p_log; 483 484 OSM_LOG_ENTER(p_log); 485 486 /* matching rules 487 * InformInfo Notice 488 * GID IssuerGID if non zero must match the trap 489 * LIDRange IssuerLID apply only if GID=0 490 * IsGeneric IsGeneric is compulsory and must match the trap 491 * Type Type if not 0xFFFF must match 492 * TrapNumber TrapNumber if not 0xFFFF must match 493 * DeviceId DeviceID if not 0xFFFF must match 494 * QPN dont care 495 * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation 496 * VendorID VendorID match or 0xFFFFFF 497 */ 498 499 /* GID IssuerGID if non zero must match the trap */ 500 if (p_ii->gid.unicast.prefix != 0 501 || p_ii->gid.unicast.interface_id != 0) { 502 /* match by GID */ 503 if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid), 504 sizeof(ib_gid_t))) { 505 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n"); 506 goto Exit; 507 } 508 } else { 509 /* LIDRange IssuerLID apply only if GID=0 */ 510 /* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */ 511 if (p_ii->lid_range_begin != 0xFFFF) { 512 /* a real lid range is given - check it */ 513 if ((cl_hton16(p_ii->lid_range_begin) > 514 cl_hton16(p_ntc->issuer_lid)) 515 || (cl_hton16(p_ntc->issuer_lid) > 516 cl_hton16(p_ii->lid_range_end))) { 517 OSM_LOG(p_log, OSM_LOG_DEBUG, 518 "Mismatch by LID Range. Needed: %u <= %u <= %u\n", 519 cl_hton16(p_ii->lid_range_begin), 520 cl_hton16(p_ntc->issuer_lid), 521 cl_hton16(p_ii->lid_range_end)); 522 goto Exit; 523 } 524 } 525 } 526 527 /* IsGeneric IsGeneric is compulsory and must match the trap */ 528 if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) || 529 (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) { 530 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n"); 531 goto Exit; 532 } 533 534 /* Type Type if not 0xFFFF must match */ 535 if ((p_ii->trap_type != 0xFFFF) && 536 (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) { 537 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n"); 538 goto Exit; 539 } 540 541 /* based on generic type */ 542 if (p_ii->is_generic) { 543 /* TrapNumber TrapNumber if not 0xFFFF must match */ 544 if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) && 545 (p_ii->g_or_v.generic.trap_num != 546 p_ntc->g_or_v.generic.trap_num)) { 547 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n"); 548 goto Exit; 549 } 550 551 /* ProducerType ProducerType match or 0xFFFFFF */ 552 if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF) 553 && (ib_inform_info_get_prod_type(p_ii) != 554 ib_notice_get_prod_type(p_ntc))) { 555 OSM_LOG(p_log, OSM_LOG_DEBUG, 556 "Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n", 557 cl_ntoh32(ib_inform_info_get_prod_type(p_ii)), 558 ib_get_producer_type_str 559 (ib_inform_info_get_prod_type(p_ii)), 560 cl_ntoh32(ib_notice_get_prod_type(p_ntc)), 561 ib_get_producer_type_str(ib_notice_get_prod_type 562 (p_ntc))); 563 goto Exit; 564 } 565 } else { 566 /* DeviceId DeviceID if not 0xFFFF must match */ 567 if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) && 568 (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) { 569 OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n"); 570 goto Exit; 571 } 572 573 /* VendorID VendorID match or 0xFFFFFF */ 574 if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) && 575 (ib_inform_info_get_vend_id(p_ii) != 576 ib_notice_get_vend_id(p_ntc))) { 577 OSM_LOG(p_log, OSM_LOG_DEBUG, 578 "Mismatch by Vendor ID\n"); 579 goto Exit; 580 } 581 } 582 583 if (!is_access_permitted(p_infr_rec, p_infr_match)) 584 goto Exit; 585 586 /* send the report to the address provided in the inform record */ 587 OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n"); 588 send_report(p_infr_rec, p_ntc); 589 590 Exit: 591 OSM_LOG_EXIT(p_log); 592 } 593 594 /********************************************************************** 595 * Once a Trap was received by osm_trap_rcv, or a Trap sourced by 596 * the SM was sent (Traps 64-67), this routine is called with a copy of 597 * the notice data. 598 * Given a notice attribute - compare and see if it matches the InformInfo 599 * element and if it does - call the Report(Notice) for the 600 * target QP registered by the address stored in the InformInfo element 601 **********************************************************************/ 602 static void log_notice(osm_log_t * log, osm_log_level_t level, 603 ib_mad_notice_attr_t * ntc) 604 { 605 char gid_str[INET6_ADDRSTRLEN], gid_str2[INET6_ADDRSTRLEN]; 606 ib_gid_t *gid; 607 ib_gid_t *gid1, *gid2; 608 609 /* an official Event information log */ 610 if (ib_notice_is_generic(ntc)) { 611 if ((ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_IN_SERVICE_TRAP)) || 612 (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_OUT_OF_SERVICE_TRAP)) || 613 (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_CREATED_TRAP)) || 614 (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_DESTROYED_TRAP))) 615 gid = &ntc->data_details.ntc_64_67.gid; 616 else 617 gid = &ntc->issuer_gid; 618 619 switch (cl_ntoh16(ntc->g_or_v.generic.trap_num)) { 620 case SM_GID_IN_SERVICE_TRAP: 621 case SM_GID_OUT_OF_SERVICE_TRAP: 622 OSM_LOG(log, level, 623 "Reporting Informational Notice \"%s\", GID:%s\n", 624 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 625 inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); 626 break; 627 case SM_MGID_CREATED_TRAP: 628 case SM_MGID_DESTROYED_TRAP: 629 OSM_LOG(log, level, 630 "Reporting Informational Notice \"%s\", MGID:%s\n", 631 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 632 inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); 633 break; 634 case SM_UNPATH_TRAP: 635 case SM_REPATH_TRAP: 636 /* TODO: Fill in details once SM starts to use these traps */ 637 OSM_LOG(log, level, 638 "Reporting Informational Notice \"%s\"n", 639 ib_get_trap_str(ntc->g_or_v.generic.trap_num)); 640 break; 641 case SM_LINK_STATE_CHANGED_TRAP: 642 OSM_LOG(log, level, 643 "Reporting Urgent Notice \"%s\" from switch LID %u, " 644 "GUID 0x%016" PRIx64 "\n", 645 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 646 cl_ntoh16(ntc->issuer_lid), 647 cl_ntoh64(gid->unicast.interface_id)); 648 break; 649 case SM_LINK_INTEGRITY_THRESHOLD_TRAP: 650 case SM_BUFFER_OVERRUN_THRESHOLD_TRAP: 651 case SM_WATCHDOG_TIMER_EXPIRED_TRAP: 652 OSM_LOG(log, level, 653 "Reporting Urgent Notice \"%s\" from LID %u, " 654 "GUID 0x%016" PRIx64 ", port %u\n", 655 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 656 cl_ntoh16(ntc->issuer_lid), 657 cl_ntoh64(gid->unicast.interface_id), 658 ntc->data_details.ntc_129_131.port_num); 659 break; 660 case SM_LOCAL_CHANGES_TRAP: 661 if (ntc->data_details.ntc_144.local_changes == 1) 662 OSM_LOG(log, level, 663 "Reporting Informational Notice \"%s\" from LID %u, " 664 "GUID 0x%016" PRIx64 ", ChangeFlags 0x%04x, " 665 "CapabilityMask2 0x%04x\n", 666 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 667 cl_ntoh16(ntc->issuer_lid), 668 cl_ntoh64(gid->unicast.interface_id), 669 cl_ntoh16(ntc->data_details.ntc_144.change_flgs), 670 cl_ntoh16(ntc->data_details.ntc_144.cap_mask2)); 671 else 672 OSM_LOG(log, level, 673 "Reporting Informational Notice \"%s\" from LID %u, " 674 "GUID 0x%016" PRIx64 ", new CapabilityMask 0x%08x\n", 675 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 676 cl_ntoh16(ntc->issuer_lid), 677 cl_ntoh64(gid->unicast.interface_id), 678 cl_ntoh32(ntc->data_details.ntc_144.new_cap_mask)); 679 break; 680 case SM_SYS_IMG_GUID_CHANGED_TRAP: 681 OSM_LOG(log, level, 682 "Reporting Informational Notice \"%s\" from LID %u, " 683 "GUID 0x%016" PRIx64 ", new SysImageGUID 0x%016" PRIx64 "\n", 684 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 685 cl_ntoh16(ntc->issuer_lid), 686 cl_ntoh64(gid->unicast.interface_id), 687 cl_ntoh64(ntc->data_details.ntc_145.new_sys_guid)); 688 break; 689 case SM_BAD_MKEY_TRAP: 690 OSM_LOG(log, level, 691 "Reporting Security Notice \"%s\" from LID %u, " 692 "GUID 0x%016" PRIx64 ", Method 0x%x, Attribute 0x%x, " 693 "AttrMod 0x%x, M_Key 0x%016" PRIx64 "\n", 694 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 695 cl_ntoh16(ntc->issuer_lid), 696 cl_ntoh64(gid->unicast.interface_id), 697 ntc->data_details.ntc_256.method, 698 cl_ntoh16(ntc->data_details.ntc_256.attr_id), 699 cl_ntoh32(ntc->data_details.ntc_256.attr_mod), 700 cl_ntoh64(ntc->data_details.ntc_256.mkey)); 701 break; 702 case SM_BAD_PKEY_TRAP: 703 case SM_BAD_QKEY_TRAP: 704 gid1 = &ntc->data_details.ntc_257_258.gid1; 705 gid2 = &ntc->data_details.ntc_257_258.gid2; 706 OSM_LOG(log, level, 707 "Reporting Security Notice \"%s\" from LID %u, " 708 "GUID 0x%016" PRIx64 " : LID1 %u, LID2 %u, %s 0x%x, " 709 "SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n", 710 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 711 cl_ntoh16(ntc->issuer_lid), 712 cl_ntoh64(gid->unicast.interface_id), 713 cl_ntoh16(ntc->data_details.ntc_257_258.lid1), 714 cl_ntoh16(ntc->data_details.ntc_257_258.lid2), 715 cl_ntoh16(ntc->g_or_v.generic.trap_num) == SM_BAD_QKEY_TRAP ? 716 "Q_Key" : "P_Key", 717 cl_ntoh32(ntc->data_details.ntc_257_258.key), 718 cl_ntoh32(ntc->data_details.ntc_257_258.qp1) >> 28, 719 cl_ntoh32(ntc->data_details.ntc_257_258.qp1) & 0xffffff, 720 cl_ntoh32(ntc->data_details.ntc_257_258.qp2) & 0xffffff, 721 inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str), 722 inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2)); 723 break; 724 case SM_BAD_SWITCH_PKEY_TRAP: 725 gid1 = &ntc->data_details.ntc_259.gid1; 726 gid2 = &ntc->data_details.ntc_259.gid2; 727 OSM_LOG(log, level, 728 "Reporting Security Notice \"%s\" from switch LID %u, " 729 "GUID 0x%016" PRIx64 " port %d : data_valid 0x%04x, " 730 "LID1 %u, LID2 %u, PKey 0x%04x, " 731 "SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n", 732 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 733 cl_ntoh16(ntc->issuer_lid), 734 cl_ntoh64(gid->unicast.interface_id), 735 ntc->data_details.ntc_259.port_no, 736 cl_ntoh16(ntc->data_details.ntc_259.data_valid), 737 cl_ntoh16(ntc->data_details.ntc_259.lid1), 738 cl_ntoh16(ntc->data_details.ntc_259.lid2), 739 cl_ntoh16(ntc->data_details.ntc_257_258.key), 740 cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) >> 28, 741 cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) & 0xffffff, 742 cl_ntoh32(ntc->data_details.ntc_259.qp2), 743 inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str), 744 inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2)); 745 break; 746 default: 747 OSM_LOG(log, level, 748 "Reporting Generic Notice type:%u num:%u (%s)" 749 " from LID:%u GID:%s\n", 750 ib_notice_get_type(ntc), 751 cl_ntoh16(ntc->g_or_v.generic.trap_num), 752 ib_get_trap_str(ntc->g_or_v.generic.trap_num), 753 cl_ntoh16(ntc->issuer_lid), 754 inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str)); 755 break; 756 } 757 } else 758 OSM_LOG(log, level, 759 "Reporting Vendor Notice type:%u vend:%u dev:%u" 760 " from LID:%u GID:%s\n", 761 ib_notice_get_type(ntc), 762 cl_ntoh32(ib_notice_get_vend_id(ntc)), 763 cl_ntoh16(ntc->g_or_v.vend.dev_id), 764 cl_ntoh16(ntc->issuer_lid), 765 inet_ntop(AF_INET6, ntc->issuer_gid.raw, gid_str, 766 sizeof gid_str)); 767 } 768 769 ib_api_status_t osm_report_notice(IN osm_log_t * p_log, IN osm_subn_t * p_subn, 770 IN ib_mad_notice_attr_t * p_ntc) 771 { 772 osm_infr_match_ctxt_t context; 773 cl_list_t infr_to_remove_list; 774 osm_infr_t *p_infr_rec; 775 osm_infr_t *p_next_infr_rec; 776 777 OSM_LOG_ENTER(p_log); 778 779 /* 780 * we must make sure we are ready for this... 781 * note that the trap receivers might be initialized before 782 * the osm_infr_init call is performed. 783 */ 784 if (p_subn->sa_infr_list.state != CL_INITIALIZED) { 785 OSM_LOG(p_log, OSM_LOG_DEBUG, 786 "Ignoring Notice Reports since Inform List is not initialized yet!\n"); 787 return IB_ERROR; 788 } 789 790 if (OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_INFO)) 791 log_notice(p_log, OSM_LOG_INFO, p_ntc); 792 793 /* Create a list that will hold all the infr records that should 794 be removed due to violation. o13-17.1.2 */ 795 cl_list_construct(&infr_to_remove_list); 796 cl_list_init(&infr_to_remove_list, 5); 797 context.p_remove_infr_list = &infr_to_remove_list; 798 context.p_ntc = p_ntc; 799 800 /* go over all inform info available at the subnet */ 801 /* try match to the given notice and send if match */ 802 cl_qlist_apply_func(&p_subn->sa_infr_list, match_notice_to_inf_rec, 803 &context); 804 805 /* If we inserted items into the infr_to_remove_list - we need to 806 remove them */ 807 p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 808 while (p_infr_rec != NULL) { 809 p_next_infr_rec = 810 (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list); 811 osm_infr_remove_from_db(p_subn, p_log, p_infr_rec); 812 p_infr_rec = p_next_infr_rec; 813 } 814 cl_list_destroy(&infr_to_remove_list); 815 816 /* report IB traps to plugin */ 817 osm_opensm_report_event(p_subn->p_osm, OSM_EVENT_ID_TRAP, p_ntc); 818 819 OSM_LOG_EXIT(p_log); 820 821 return IB_SUCCESS; 822 } 823