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
osm_infr_delete(IN osm_infr_t * p_infr)66 void osm_infr_delete(IN osm_infr_t * p_infr)
67 {
68 free(p_infr);
69 }
70
osm_infr_new(IN const osm_infr_t * p_infr_rec)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
dump_all_informs(IN const osm_subn_t * p_subn,IN osm_log_t * p_log)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 **********************************************************************/
match_inf_rec(IN const cl_list_item_t * p_list_item,IN void * context)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
osm_infr_get_by_rec(IN osm_subn_t const * p_subn,IN osm_log_t * p_log,IN osm_infr_t * p_infr_rec)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
osm_infr_insert_to_db(IN osm_subn_t * p_subn,IN osm_log_t * p_log,IN osm_infr_t * p_infr)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
osm_infr_remove_from_db(IN osm_subn_t * p_subn,IN osm_log_t * p_log,IN osm_infr_t * p_infr)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
osm_infr_remove_subscriptions(IN osm_subn_t * p_subn,IN osm_log_t * p_log,IN ib_net64_t port_guid)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 **********************************************************************/
send_report(IN osm_infr_t * p_infr_rec,IN ib_mad_notice_attr_t * p_ntc)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
is_access_permitted(osm_infr_t * p_infr_rec,osm_infr_match_ctxt_t * p_infr_match)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 **********************************************************************/
match_notice_to_inf_rec(IN cl_list_item_t * p_list_item,IN void * context)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 **********************************************************************/
log_notice(osm_log_t * log,osm_log_level_t level,ib_mad_notice_attr_t * ntc)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
osm_report_notice(IN osm_log_t * p_log,IN osm_subn_t * p_subn,IN ib_mad_notice_attr_t * p_ntc)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