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
56 typedef 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 **********************************************************************/
osm_infr_delete(IN osm_infr_t * const p_infr)63 void osm_infr_delete(IN osm_infr_t * const p_infr)
64 {
65 free(p_infr);
66 }
67
68 /**********************************************************************
69 **********************************************************************/
osm_infr_new(IN const osm_infr_t * p_infr_rec)70 osm_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 **********************************************************************/
dump_all_informs(IN osm_subn_t const * p_subn,IN osm_log_t * p_log)85 static 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 **********************************************************************/
104 static cl_status_t
__match_inf_rec(IN const cl_list_item_t * const p_list_item,IN void * context)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
211 Exit:
212 OSM_LOG_EXIT(p_log);
213 return status;
214 }
215
216 /**********************************************************************
217 **********************************************************************/
osm_infr_get_by_rec(IN osm_subn_t const * p_subn,IN osm_log_t * p_log,IN osm_infr_t * const p_infr_rec)218 osm_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 **********************************************************************/
246 void
osm_infr_insert_to_db(IN osm_subn_t * p_subn,IN osm_log_t * p_log,IN osm_infr_t * p_infr)247 osm_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 **********************************************************************/
274 void
osm_infr_remove_from_db(IN osm_subn_t * p_subn,IN osm_log_t * p_log,IN osm_infr_t * p_infr)275 osm_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 **********************************************************************/
__osm_send_report(IN osm_infr_t * p_infr_rec,IN ib_mad_notice_attr_t * p_ntc)302 static 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
354 Exit:
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 **********************************************************************/
364 static void
__match_notice_to_inf_rec(IN cl_list_item_t * const p_list_item,IN void * context)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
533 Exit:
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 **********************************************************************/
545 ib_api_status_t
osm_report_notice(IN osm_log_t * const p_log,IN osm_subn_t * p_subn,IN ib_mad_notice_attr_t * p_ntc)546 osm_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