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