1321936Shselasky/*
2321936Shselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3321936Shselasky * Copyright (c) 2002-2015 Mellanox Technologies LTD. All rights reserved.
4321936Shselasky * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5321936Shselasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
6321936Shselasky * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
7321936Shselasky *
8321936Shselasky * This software is available to you under a choice of one of two
9321936Shselasky * licenses.  You may choose to be licensed under the terms of the GNU
10321936Shselasky * General Public License (GPL) Version 2, available from the file
11321936Shselasky * COPYING in the main directory of this source tree, or the
12321936Shselasky * OpenIB.org BSD license below:
13321936Shselasky *
14321936Shselasky *     Redistribution and use in source and binary forms, with or
15321936Shselasky *     without modification, are permitted provided that the following
16321936Shselasky *     conditions are met:
17321936Shselasky *
18321936Shselasky *      - Redistributions of source code must retain the above
19321936Shselasky *        copyright notice, this list of conditions and the following
20321936Shselasky *        disclaimer.
21321936Shselasky *
22321936Shselasky *      - Redistributions in binary form must reproduce the above
23321936Shselasky *        copyright notice, this list of conditions and the following
24321936Shselasky *        disclaimer in the documentation and/or other materials
25321936Shselasky *        provided with the distribution.
26321936Shselasky *
27321936Shselasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28321936Shselasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29321936Shselasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30321936Shselasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
31321936Shselasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
32321936Shselasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
33321936Shselasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34321936Shselasky * SOFTWARE.
35321936Shselasky *
36321936Shselasky */
37321936Shselasky
38321936Shselasky/*
39321936Shselasky * Abstract:
40321936Shselasky *    Implementation of inform record functions.
41321936Shselasky */
42321936Shselasky
43321936Shselasky#if HAVE_CONFIG_H
44321936Shselasky#  include <config.h>
45321936Shselasky#endif				/* HAVE_CONFIG_H */
46321936Shselasky
47321936Shselasky#include <stdlib.h>
48321936Shselasky#include <string.h>
49321936Shselasky#include <arpa/inet.h>
50321936Shselasky#include <sys/socket.h>
51321936Shselasky#include <complib/cl_debug.h>
52321936Shselasky#include <opensm/osm_file_ids.h>
53321936Shselasky#define FILE_ID OSM_FILE_INFORM_C
54321936Shselasky#include <opensm/osm_helper.h>
55321936Shselasky#include <opensm/osm_inform.h>
56321936Shselasky#include <vendor/osm_vendor_api.h>
57321936Shselasky#include <opensm/osm_pkey.h>
58321936Shselasky#include <opensm/osm_sa.h>
59321936Shselasky#include <opensm/osm_opensm.h>
60321936Shselasky
61321936Shselaskytypedef struct osm_infr_match_ctxt {
62321936Shselasky	cl_list_t *p_remove_infr_list;
63321936Shselasky	ib_mad_notice_attr_t *p_ntc;
64321936Shselasky} osm_infr_match_ctxt_t;
65321936Shselasky
66321936Shselaskyvoid osm_infr_delete(IN osm_infr_t * p_infr)
67321936Shselasky{
68321936Shselasky	free(p_infr);
69321936Shselasky}
70321936Shselasky
71321936Shselaskyosm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec)
72321936Shselasky{
73321936Shselasky	osm_infr_t *p_infr;
74321936Shselasky
75321936Shselasky	CL_ASSERT(p_infr_rec);
76321936Shselasky
77321936Shselasky	p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t));
78321936Shselasky	if (p_infr)
79321936Shselasky		memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t));
80321936Shselasky
81321936Shselasky	return p_infr;
82321936Shselasky}
83321936Shselasky
84321936Shselaskystatic void dump_all_informs(IN const osm_subn_t * p_subn, IN osm_log_t * p_log)
85321936Shselasky{
86321936Shselasky	cl_list_item_t *p_list_item;
87321936Shselasky
88321936Shselasky	if (!OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_DEBUG))
89321936Shselasky		return;
90321936Shselasky
91321936Shselasky	p_list_item = cl_qlist_head(&p_subn->sa_infr_list);
92321936Shselasky	while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) {
93321936Shselasky		osm_dump_inform_info_v2(p_log,
94321936Shselasky				        &((osm_infr_t *) p_list_item)->
95321936Shselasky				        inform_record.inform_info, FILE_ID, OSM_LOG_DEBUG);
96321936Shselasky		p_list_item = cl_qlist_next(p_list_item);
97321936Shselasky	}
98321936Shselasky}
99321936Shselasky
100321936Shselasky/**********************************************************************
101321936Shselasky * Match an infr by the InformInfo and Address vector
102321936Shselasky **********************************************************************/
103321936Shselaskystatic cl_status_t match_inf_rec(IN const cl_list_item_t * p_list_item,
104321936Shselasky				 IN void *context)
105321936Shselasky{
106321936Shselasky	osm_infr_t *p_infr_rec = (osm_infr_t *) context;
107321936Shselasky	osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
108321936Shselasky	ib_inform_info_t *p_ii_rec = &p_infr_rec->inform_record.inform_info;
109321936Shselasky	ib_inform_info_t *p_ii = &p_infr->inform_record.inform_info;
110321936Shselasky	osm_log_t *p_log = p_infr_rec->sa->p_log;
111321936Shselasky	cl_status_t status = CL_NOT_FOUND;
112321936Shselasky
113321936Shselasky	OSM_LOG_ENTER(p_log);
114321936Shselasky
115321936Shselasky	if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr,
116321936Shselasky		   sizeof(p_infr_rec->report_addr))) {
117321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n");
118321936Shselasky		goto Exit;
119321936Shselasky	}
120321936Shselasky
121321936Shselasky	/* if inform_info.gid is not zero, ignore lid range */
122321936Shselasky	if (ib_gid_is_notzero(&p_ii_rec->gid)) {
123321936Shselasky		if (memcmp(&p_ii->gid, &p_ii_rec->gid, sizeof(p_ii->gid))) {
124321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
125321936Shselasky				"Differ by InformInfo.gid\n");
126321936Shselasky			goto Exit;
127321936Shselasky		}
128321936Shselasky	} else {
129321936Shselasky		if ((p_ii->lid_range_begin != p_ii_rec->lid_range_begin) ||
130321936Shselasky		    (p_ii->lid_range_end != p_ii_rec->lid_range_end)) {
131321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
132321936Shselasky				"Differ by InformInfo.LIDRange\n");
133321936Shselasky			goto Exit;
134321936Shselasky		}
135321936Shselasky	}
136321936Shselasky
137321936Shselasky	if (p_ii->trap_type != p_ii_rec->trap_type) {
138321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG,
139321936Shselasky			"Differ by InformInfo.TrapType\n");
140321936Shselasky		goto Exit;
141321936Shselasky	}
142321936Shselasky
143321936Shselasky	if (p_ii->is_generic != p_ii_rec->is_generic) {
144321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG,
145321936Shselasky			"Differ by InformInfo.IsGeneric\n");
146321936Shselasky		goto Exit;
147321936Shselasky	}
148321936Shselasky
149321936Shselasky	if (p_ii->is_generic) {
150321936Shselasky		if (p_ii->g_or_v.generic.trap_num !=
151321936Shselasky		    p_ii_rec->g_or_v.generic.trap_num)
152321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
153321936Shselasky				"Differ by InformInfo.Generic.TrapNumber\n");
154321936Shselasky		else if (p_ii->g_or_v.generic.qpn_resp_time_val !=
155321936Shselasky			 p_ii_rec->g_or_v.generic.qpn_resp_time_val)
156321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
157321936Shselasky				"Differ by InformInfo.Generic.QPNRespTimeVal\n");
158321936Shselasky		else if (p_ii->g_or_v.generic.node_type_msb !=
159321936Shselasky			 p_ii_rec->g_or_v.generic.node_type_msb)
160321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
161321936Shselasky				"Differ by InformInfo.Generic.NodeTypeMSB\n");
162321936Shselasky		else if (p_ii->g_or_v.generic.node_type_lsb !=
163321936Shselasky			 p_ii_rec->g_or_v.generic.node_type_lsb)
164321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
165321936Shselasky				"Differ by InformInfo.Generic.NodeTypeLSB\n");
166321936Shselasky		else
167321936Shselasky			status = CL_SUCCESS;
168321936Shselasky	} else {
169321936Shselasky		if (p_ii->g_or_v.vend.dev_id != p_ii_rec->g_or_v.vend.dev_id)
170321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
171321936Shselasky				"Differ by InformInfo.Vendor.DeviceID\n");
172321936Shselasky		else if (p_ii->g_or_v.vend.qpn_resp_time_val !=
173321936Shselasky			 p_ii_rec->g_or_v.vend.qpn_resp_time_val)
174321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
175321936Shselasky				"Differ by InformInfo.Vendor.QPNRespTimeVal\n");
176321936Shselasky		else if (p_ii->g_or_v.vend.vendor_id_msb !=
177321936Shselasky			 p_ii_rec->g_or_v.vend.vendor_id_msb)
178321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
179321936Shselasky				"Differ by InformInfo.Vendor.VendorIdMSB\n");
180321936Shselasky		else if (p_ii->g_or_v.vend.vendor_id_lsb !=
181321936Shselasky			 p_ii_rec->g_or_v.vend.vendor_id_lsb)
182321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
183321936Shselasky				"Differ by InformInfo.Vendor.VendorIdLSB\n");
184321936Shselasky		else
185321936Shselasky			status = CL_SUCCESS;
186321936Shselasky	}
187321936Shselasky
188321936ShselaskyExit:
189321936Shselasky	OSM_LOG_EXIT(p_log);
190321936Shselasky	return status;
191321936Shselasky}
192321936Shselasky
193321936Shselaskyosm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn,
194321936Shselasky				IN osm_log_t * p_log,
195321936Shselasky				IN osm_infr_t * p_infr_rec)
196321936Shselasky{
197321936Shselasky	cl_list_item_t *p_list_item;
198321936Shselasky
199321936Shselasky	OSM_LOG_ENTER(p_log);
200321936Shselasky
201321936Shselasky	dump_all_informs(p_subn, p_log);
202321936Shselasky
203321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n");
204321936Shselasky	osm_dump_inform_info_v2(p_log, &(p_infr_rec->inform_record.inform_info),
205321936Shselasky			        FILE_ID, OSM_LOG_DEBUG);
206321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n",
207321936Shselasky		cl_qlist_count(&p_subn->sa_infr_list));
208321936Shselasky
209321936Shselasky	p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list,
210321936Shselasky					      match_inf_rec, p_infr_rec);
211321936Shselasky
212321936Shselasky	if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list))
213321936Shselasky		p_list_item = NULL;
214321936Shselasky
215321936Shselasky	OSM_LOG_EXIT(p_log);
216321936Shselasky	return (osm_infr_t *) p_list_item;
217321936Shselasky}
218321936Shselasky
219321936Shselaskyvoid osm_infr_insert_to_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log,
220321936Shselasky			   IN osm_infr_t * p_infr)
221321936Shselasky{
222321936Shselasky	OSM_LOG_ENTER(p_log);
223321936Shselasky
224321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG,
225321936Shselasky		"Inserting new InformInfo Record into Database\n");
226321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n",
227321936Shselasky		cl_qlist_count(&p_subn->sa_infr_list));
228321936Shselasky	dump_all_informs(p_subn, p_log);
229321936Shselasky
230321936Shselasky#if 0
231321936Shselasky	osm_dump_inform_info_v2(p_log,
232321936Shselasky			        &(p_infr->inform_record.inform_info),
233321936Shselasky			        FILE_ID, OSM_LOG_DEBUG);
234321936Shselasky#endif
235321936Shselasky
236321936Shselasky	cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item);
237321936Shselasky	p_subn->p_osm->sa.dirty = TRUE;
238321936Shselasky
239321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n",
240321936Shselasky		cl_qlist_count(&p_subn->sa_infr_list));
241321936Shselasky	dump_all_informs(p_subn, p_log);
242321936Shselasky	OSM_LOG_EXIT(p_log);
243321936Shselasky}
244321936Shselasky
245321936Shselaskyvoid osm_infr_remove_from_db(IN osm_subn_t * p_subn, IN osm_log_t * p_log,
246321936Shselasky			     IN osm_infr_t * p_infr)
247321936Shselasky{
248321936Shselasky	char gid_str[INET6_ADDRSTRLEN];
249321936Shselasky	OSM_LOG_ENTER(p_log);
250321936Shselasky
251321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s"
252321936Shselasky		" Enum:0x%X from Database\n",
253321936Shselasky		inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw,
254321936Shselasky			  gid_str, sizeof gid_str),
255321936Shselasky		p_infr->inform_record.subscriber_enum);
256321936Shselasky
257321936Shselasky	osm_dump_inform_info_v2(p_log, &(p_infr->inform_record.inform_info),
258321936Shselasky			        FILE_ID, OSM_LOG_DEBUG);
259321936Shselasky
260321936Shselasky	cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item);
261321936Shselasky	p_subn->p_osm->sa.dirty = TRUE;
262321936Shselasky
263321936Shselasky	osm_infr_delete(p_infr);
264321936Shselasky
265321936Shselasky	OSM_LOG_EXIT(p_log);
266321936Shselasky}
267321936Shselasky
268321936Shselaskyib_api_status_t osm_infr_remove_subscriptions(IN osm_subn_t * p_subn,
269321936Shselasky					      IN osm_log_t * p_log,
270321936Shselasky					      IN ib_net64_t port_guid)
271321936Shselasky{
272321936Shselasky	cl_list_item_t *p_list_item;
273321936Shselasky	osm_infr_t *p_infr;
274321936Shselasky	ib_api_status_t status = CL_NOT_FOUND;
275321936Shselasky
276321936Shselasky	OSM_LOG_ENTER(p_log);
277321936Shselasky
278321936Shselasky	/* go over all inform info available at the subnet */
279321936Shselasky	/* match to the given GID and delete subscriptions if match */
280321936Shselasky	p_list_item = cl_qlist_head(&p_subn->sa_infr_list);
281321936Shselasky	while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) {
282321936Shselasky
283321936Shselasky		p_infr = (osm_infr_t *)p_list_item;
284321936Shselasky		p_list_item = cl_qlist_next(p_list_item);
285321936Shselasky
286321936Shselasky		if (port_guid != p_infr->inform_record.subscriber_gid.unicast.interface_id)
287321936Shselasky			continue;
288321936Shselasky
289321936Shselasky		/* Remove this event subscription */
290321936Shselasky		osm_infr_remove_from_db(p_subn, p_log, p_infr);
291321936Shselasky
292321936Shselasky		status = CL_SUCCESS;
293321936Shselasky	}
294321936Shselasky
295321936Shselasky	OSM_LOG_EXIT(p_log);
296321936Shselasky	return (status);
297321936Shselasky}
298321936Shselasky
299321936Shselasky/**********************************************************************
300321936Shselasky * Send a report:
301321936Shselasky * Given a target address to send to and the notice.
302321936Shselasky * We need to send SubnAdmReport
303321936Shselasky **********************************************************************/
304321936Shselaskystatic ib_api_status_t send_report(IN osm_infr_t * p_infr_rec,	/* the informinfo */
305321936Shselasky				   IN ib_mad_notice_attr_t * p_ntc	/* notice to send */
306321936Shselasky    )
307321936Shselasky{
308321936Shselasky	osm_madw_t *p_report_madw;
309321936Shselasky	ib_mad_notice_attr_t *p_report_ntc;
310321936Shselasky	ib_mad_t *p_mad;
311321936Shselasky	ib_sa_mad_t *p_sa_mad;
312321936Shselasky	static atomic32_t trap_fwd_trans_id = 0x02DAB000;
313321936Shselasky	ib_api_status_t status = IB_SUCCESS;
314321936Shselasky	osm_log_t *p_log = p_infr_rec->sa->p_log;
315321936Shselasky	ib_net64_t tid;
316321936Shselasky
317321936Shselasky	OSM_LOG_ENTER(p_log);
318321936Shselasky
319321936Shselasky	/* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */
320321936Shselasky
321321936Shselasky	/* it is better to use LIDs since the GIDs might not be there for SMI traps */
322321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID %u"
323321936Shselasky		" to InformInfo LID %u GUID 0x%" PRIx64 ", TID 0x%X\n",
324321936Shselasky		cl_ntoh16(p_ntc->issuer_lid),
325321936Shselasky		cl_ntoh16(p_infr_rec->report_addr.dest_lid),
326321936Shselasky		cl_ntoh64(p_infr_rec->inform_record.subscriber_gid.unicast.interface_id),
327321936Shselasky		trap_fwd_trans_id);
328321936Shselasky
329321936Shselasky	/* get the MAD to send */
330321936Shselasky	p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool,
331321936Shselasky					 p_infr_rec->h_bind, MAD_BLOCK_SIZE,
332321936Shselasky					 &(p_infr_rec->report_addr));
333321936Shselasky
334321936Shselasky	if (!p_report_madw) {
335321936Shselasky		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203: "
336321936Shselasky			"Cannot send report to LID %u, osm_mad_pool_get failed\n",
337321936Shselasky			cl_ntoh16(p_infr_rec->report_addr.dest_lid));
338321936Shselasky		status = IB_ERROR;
339321936Shselasky		goto Exit;
340321936Shselasky	}
341321936Shselasky
342321936Shselasky	p_report_madw->resp_expected = TRUE;
343321936Shselasky
344321936Shselasky	/* advance trap trans id (cant simply ++ on some systems inside ntoh) */
345321936Shselasky	tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) &
346321936Shselasky			(uint64_t) (0xFFFFFFFF));
347321936Shselasky	if (trap_fwd_trans_id == 0)
348321936Shselasky		tid = cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id) &
349321936Shselasky				(uint64_t) (0xFFFFFFFF));
350321936Shselasky	p_mad = osm_madw_get_mad_ptr(p_report_madw);
351321936Shselasky	ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT,
352321936Shselasky			tid, IB_MAD_ATTR_NOTICE, 0);
353321936Shselasky
354321936Shselasky	p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw);
355321936Shselasky
356321936Shselasky	p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data);
357321936Shselasky
358321936Shselasky	/* copy the notice */
359321936Shselasky	*p_report_ntc = *p_ntc;
360321936Shselasky
361321936Shselasky	/* The TRUE is for: response is expected */
362321936Shselasky	osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE);
363321936Shselasky
364321936ShselaskyExit:
365321936Shselasky	OSM_LOG_EXIT(p_log);
366321936Shselasky	return status;
367321936Shselasky}
368321936Shselasky
369321936Shselaskystatic int is_access_permitted(osm_infr_t *p_infr_rec,
370321936Shselasky			       osm_infr_match_ctxt_t *p_infr_match )
371321936Shselasky{
372321936Shselasky	cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list;
373321936Shselasky	ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info);
374321936Shselasky	ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc;
375321936Shselasky	uint16_t trap_num = cl_ntoh16(p_ntc->g_or_v.generic.trap_num);
376321936Shselasky	osm_subn_t *p_subn = p_infr_rec->sa->p_subn;
377321936Shselasky	osm_log_t *p_log = p_infr_rec->sa->p_log;
378321936Shselasky	osm_mgrp_t *p_mgrp;
379321936Shselasky	ib_gid_t source_gid;
380321936Shselasky	osm_port_t *p_src_port;
381321936Shselasky	osm_port_t *p_dest_port;
382321936Shselasky
383321936Shselasky	/* In case of SM_GID_IN_SERVICE_TRAP(64) or SM_GID_OUT_OF_SERVICE_TRAP(65) traps
384321936Shselasky	   the source gid comparison should be done on the trap source (saved
385321936Shselasky	   as the gid in the data details field).
386321936Shselasky	   For traps SM_MGID_CREATED_TRAP(66) or SM_MGID_DESTROYED_TRAP(67)
387321936Shselasky	   the data details gid is the MGID.
388321936Shselasky	   We need to check whether the subscriber has a compatible
389321936Shselasky	   pkey with MC group.
390321936Shselasky	   In all other cases the issuer gid is the trap source.
391321936Shselasky	*/
392321936Shselasky	if (trap_num >= SM_GID_IN_SERVICE_TRAP &&
393321936Shselasky	    trap_num <= SM_MGID_DESTROYED_TRAP)
394321936Shselasky		/* The issuer of these traps is the SM so source_gid
395321936Shselasky		   is the gid saved on the data details */
396321936Shselasky		source_gid = p_ntc->data_details.ntc_64_67.gid;
397321936Shselasky	else
398321936Shselasky		source_gid = p_ntc->issuer_gid;
399321936Shselasky
400321936Shselasky	p_dest_port = osm_get_port_by_lid(p_subn,
401321936Shselasky					  p_infr_rec->report_addr.dest_lid);
402321936Shselasky	if (!p_dest_port) {
403321936Shselasky		OSM_LOG(p_log, OSM_LOG_INFO,
404321936Shselasky			"Cannot find destination port with LID:%u\n",
405321936Shselasky			cl_ntoh16(p_infr_rec->report_addr.dest_lid));
406321936Shselasky		goto Exit;
407321936Shselasky	}
408321936Shselasky
409321936Shselasky	/* Check if there is a pkey match. o13-17.1.1 */
410321936Shselasky	switch (trap_num) {
411321936Shselasky		case SM_MGID_CREATED_TRAP:
412321936Shselasky		case SM_MGID_DESTROYED_TRAP:
413321936Shselasky			p_mgrp = osm_get_mgrp_by_mgid(p_subn, &source_gid);
414321936Shselasky			if (!p_mgrp) {
415321936Shselasky				char gid_str[INET6_ADDRSTRLEN];
416321936Shselasky				OSM_LOG(p_log, OSM_LOG_INFO,
417321936Shselasky					"Cannot find MGID %s\n",
418321936Shselasky					inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str));
419321936Shselasky				goto Exit;
420321936Shselasky			}
421321936Shselasky
422321936Shselasky			if (!osm_physp_has_pkey(p_log,
423321936Shselasky						p_mgrp->mcmember_rec.pkey,
424321936Shselasky						p_dest_port->p_physp)) {
425321936Shselasky				char gid_str[INET6_ADDRSTRLEN];
426321936Shselasky				OSM_LOG(p_log, OSM_LOG_INFO,
427321936Shselasky					"MGID %s and port GUID:0x%016" PRIx64 " do not share same pkey\n",
428321936Shselasky					inet_ntop(AF_INET6, source_gid.raw, gid_str, sizeof gid_str),
429321936Shselasky					cl_ntoh64(p_dest_port->guid));
430321936Shselasky				goto Exit;
431321936Shselasky			}
432321936Shselasky			break;
433321936Shselasky
434321936Shselasky		default:
435321936Shselasky			p_src_port =
436321936Shselasky			    osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id);
437321936Shselasky			if (!p_src_port) {
438321936Shselasky				OSM_LOG(p_log, OSM_LOG_INFO,
439321936Shselasky					"Cannot find source port with GUID:0x%016" PRIx64 "\n",
440321936Shselasky					cl_ntoh64(source_gid.unicast.interface_id));
441321936Shselasky				goto Exit;
442321936Shselasky			}
443321936Shselasky
444321936Shselasky
445321936Shselasky			if (osm_port_share_pkey(p_log, p_src_port, p_dest_port,
446321936Shselasky						p_subn->opt.allow_both_pkeys) == FALSE) {
447321936Shselasky				OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n");
448321936Shselasky				/* According to o13-17.1.2 - If this informInfo
449321936Shselasky				   does not have lid_range_begin of 0xFFFF,
450321936Shselasky				   then this informInfo request should be
451321936Shselasky				   removed from database */
452321936Shselasky				if (p_ii->lid_range_begin != 0xFFFF) {
453321936Shselasky					OSM_LOG(p_log, OSM_LOG_VERBOSE,
454321936Shselasky						"Pkey mismatch on lid_range_begin != 0xFFFF. "
455321936Shselasky						"Need to remove this informInfo from db\n");
456321936Shselasky					/* add the informInfo record to the remove_infr list */
457321936Shselasky					cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec);
458321936Shselasky				}
459321936Shselasky				goto Exit;
460321936Shselasky			}
461321936Shselasky			break;
462321936Shselasky	}
463321936Shselasky
464321936Shselasky	return 1;
465321936ShselaskyExit:
466321936Shselasky	return 0;
467321936Shselasky}
468321936Shselasky
469321936Shselasky
470321936Shselasky/**********************************************************************
471321936Shselasky * This routine compares a given Notice and a ListItem of InformInfo type.
472321936Shselasky * PREREQUISITE:
473321936Shselasky * The Notice.GID should be pre-filled with the trap generator GID
474321936Shselasky **********************************************************************/
475321936Shselaskystatic void match_notice_to_inf_rec(IN cl_list_item_t * p_list_item,
476321936Shselasky				    IN void *context)
477321936Shselasky{
478321936Shselasky	osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context;
479321936Shselasky	ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc;
480321936Shselasky	osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item;
481321936Shselasky	ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info);
482321936Shselasky	osm_log_t *p_log = p_infr_rec->sa->p_log;
483321936Shselasky
484321936Shselasky	OSM_LOG_ENTER(p_log);
485321936Shselasky
486321936Shselasky	/* matching rules
487321936Shselasky	 * InformInfo   Notice
488321936Shselasky	 * GID          IssuerGID    if non zero must match the trap
489321936Shselasky	 * LIDRange     IssuerLID    apply only if GID=0
490321936Shselasky	 * IsGeneric    IsGeneric    is compulsory and must match the trap
491321936Shselasky	 * Type         Type         if not 0xFFFF must match
492321936Shselasky	 * TrapNumber   TrapNumber   if not 0xFFFF must match
493321936Shselasky	 * DeviceId     DeviceID     if not 0xFFFF must match
494321936Shselasky	 * QPN dont care
495321936Shselasky	 * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation
496321936Shselasky	 * VendorID     VendorID     match or 0xFFFFFF
497321936Shselasky	 */
498321936Shselasky
499321936Shselasky	/* GID          IssuerGID    if non zero must match the trap  */
500321936Shselasky	if (p_ii->gid.unicast.prefix != 0
501321936Shselasky	    || p_ii->gid.unicast.interface_id != 0) {
502321936Shselasky		/* match by GID */
503321936Shselasky		if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid),
504321936Shselasky			   sizeof(ib_gid_t))) {
505321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n");
506321936Shselasky			goto Exit;
507321936Shselasky		}
508321936Shselasky	} else {
509321936Shselasky		/* LIDRange     IssuerLID    apply only if GID=0 */
510321936Shselasky		/* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */
511321936Shselasky		if (p_ii->lid_range_begin != 0xFFFF) {
512321936Shselasky			/* a real lid range is given - check it */
513321936Shselasky			if ((cl_hton16(p_ii->lid_range_begin) >
514321936Shselasky			     cl_hton16(p_ntc->issuer_lid))
515321936Shselasky			    || (cl_hton16(p_ntc->issuer_lid) >
516321936Shselasky				cl_hton16(p_ii->lid_range_end))) {
517321936Shselasky				OSM_LOG(p_log, OSM_LOG_DEBUG,
518321936Shselasky					"Mismatch by LID Range. Needed: %u <= %u <= %u\n",
519321936Shselasky					cl_hton16(p_ii->lid_range_begin),
520321936Shselasky					cl_hton16(p_ntc->issuer_lid),
521321936Shselasky					cl_hton16(p_ii->lid_range_end));
522321936Shselasky				goto Exit;
523321936Shselasky			}
524321936Shselasky		}
525321936Shselasky	}
526321936Shselasky
527321936Shselasky	/* IsGeneric    IsGeneric    is compulsory and must match the trap  */
528321936Shselasky	if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) ||
529321936Shselasky	    (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) {
530321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n");
531321936Shselasky		goto Exit;
532321936Shselasky	}
533321936Shselasky
534321936Shselasky	/* Type         Type         if not 0xFFFF must match */
535321936Shselasky	if ((p_ii->trap_type != 0xFFFF) &&
536321936Shselasky	    (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) {
537321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n");
538321936Shselasky		goto Exit;
539321936Shselasky	}
540321936Shselasky
541321936Shselasky	/* based on generic type */
542321936Shselasky	if (p_ii->is_generic) {
543321936Shselasky		/* TrapNumber   TrapNumber   if not 0xFFFF must match */
544321936Shselasky		if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) &&
545321936Shselasky		    (p_ii->g_or_v.generic.trap_num !=
546321936Shselasky		     p_ntc->g_or_v.generic.trap_num)) {
547321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n");
548321936Shselasky			goto Exit;
549321936Shselasky		}
550321936Shselasky
551321936Shselasky		/* ProducerType ProducerType match or 0xFFFFFF  */
552321936Shselasky		if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF)
553321936Shselasky		    && (ib_inform_info_get_prod_type(p_ii) !=
554321936Shselasky			ib_notice_get_prod_type(p_ntc))) {
555321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
556321936Shselasky				"Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n",
557321936Shselasky				cl_ntoh32(ib_inform_info_get_prod_type(p_ii)),
558321936Shselasky				ib_get_producer_type_str
559321936Shselasky				(ib_inform_info_get_prod_type(p_ii)),
560321936Shselasky				cl_ntoh32(ib_notice_get_prod_type(p_ntc)),
561321936Shselasky				ib_get_producer_type_str(ib_notice_get_prod_type
562321936Shselasky							 (p_ntc)));
563321936Shselasky			goto Exit;
564321936Shselasky		}
565321936Shselasky	} else {
566321936Shselasky		/* DeviceId     DeviceID     if not 0xFFFF must match */
567321936Shselasky		if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) &&
568321936Shselasky		    (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) {
569321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n");
570321936Shselasky			goto Exit;
571321936Shselasky		}
572321936Shselasky
573321936Shselasky		/* VendorID     VendorID     match or 0xFFFFFF  */
574321936Shselasky		if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) &&
575321936Shselasky		    (ib_inform_info_get_vend_id(p_ii) !=
576321936Shselasky		     ib_notice_get_vend_id(p_ntc))) {
577321936Shselasky			OSM_LOG(p_log, OSM_LOG_DEBUG,
578321936Shselasky				"Mismatch by Vendor ID\n");
579321936Shselasky			goto Exit;
580321936Shselasky		}
581321936Shselasky	}
582321936Shselasky
583321936Shselasky	if (!is_access_permitted(p_infr_rec, p_infr_match))
584321936Shselasky		goto Exit;
585321936Shselasky
586321936Shselasky	/* send the report to the address provided in the inform record */
587321936Shselasky	OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n");
588321936Shselasky	send_report(p_infr_rec, p_ntc);
589321936Shselasky
590321936ShselaskyExit:
591321936Shselasky	OSM_LOG_EXIT(p_log);
592321936Shselasky}
593321936Shselasky
594321936Shselasky/**********************************************************************
595321936Shselasky * Once a Trap was received by osm_trap_rcv, or a Trap sourced by
596321936Shselasky * the SM was sent (Traps 64-67), this routine is called with a copy of
597321936Shselasky * the notice data.
598321936Shselasky * Given a notice attribute - compare and see if it matches the InformInfo
599321936Shselasky * element and if it does - call the Report(Notice) for the
600321936Shselasky * target QP registered by the address stored in the InformInfo element
601321936Shselasky **********************************************************************/
602321936Shselaskystatic void log_notice(osm_log_t * log, osm_log_level_t level,
603321936Shselasky		       ib_mad_notice_attr_t * ntc)
604321936Shselasky{
605321936Shselasky	char gid_str[INET6_ADDRSTRLEN], gid_str2[INET6_ADDRSTRLEN];
606321936Shselasky	ib_gid_t *gid;
607321936Shselasky	ib_gid_t *gid1, *gid2;
608321936Shselasky
609321936Shselasky	/* an official Event information log */
610321936Shselasky	if (ib_notice_is_generic(ntc)) {
611321936Shselasky		if ((ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_IN_SERVICE_TRAP)) ||
612321936Shselasky		    (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_GID_OUT_OF_SERVICE_TRAP)) ||
613321936Shselasky		    (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_CREATED_TRAP)) ||
614321936Shselasky		    (ntc->g_or_v.generic.trap_num == CL_HTON16(SM_MGID_DESTROYED_TRAP)))
615321936Shselasky			gid = &ntc->data_details.ntc_64_67.gid;
616321936Shselasky		else
617321936Shselasky			gid = &ntc->issuer_gid;
618321936Shselasky
619321936Shselasky		switch (cl_ntoh16(ntc->g_or_v.generic.trap_num)) {
620321936Shselasky		case SM_GID_IN_SERVICE_TRAP:
621321936Shselasky		case SM_GID_OUT_OF_SERVICE_TRAP:
622321936Shselasky			OSM_LOG(log, level,
623321936Shselasky				"Reporting Informational Notice \"%s\", GID:%s\n",
624321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
625321936Shselasky				inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str));
626321936Shselasky			break;
627321936Shselasky		case SM_MGID_CREATED_TRAP:
628321936Shselasky		case SM_MGID_DESTROYED_TRAP:
629321936Shselasky			OSM_LOG(log, level,
630321936Shselasky				"Reporting Informational Notice \"%s\", MGID:%s\n",
631321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
632321936Shselasky				inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str));
633321936Shselasky			break;
634321936Shselasky		case SM_UNPATH_TRAP:
635321936Shselasky		case SM_REPATH_TRAP:
636321936Shselasky			/* TODO: Fill in details once SM starts to use these traps */
637321936Shselasky			OSM_LOG(log, level,
638321936Shselasky				"Reporting Informational Notice \"%s\"n",
639321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num));
640321936Shselasky			break;
641321936Shselasky		case SM_LINK_STATE_CHANGED_TRAP:
642321936Shselasky			OSM_LOG(log, level,
643321936Shselasky				"Reporting Urgent Notice \"%s\" from switch LID %u, "
644321936Shselasky				"GUID 0x%016" PRIx64 "\n",
645321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
646321936Shselasky				cl_ntoh16(ntc->issuer_lid),
647321936Shselasky				cl_ntoh64(gid->unicast.interface_id));
648321936Shselasky			break;
649321936Shselasky		case SM_LINK_INTEGRITY_THRESHOLD_TRAP:
650321936Shselasky		case SM_BUFFER_OVERRUN_THRESHOLD_TRAP:
651321936Shselasky		case SM_WATCHDOG_TIMER_EXPIRED_TRAP:
652321936Shselasky			OSM_LOG(log, level,
653321936Shselasky				"Reporting Urgent Notice \"%s\" from LID %u, "
654321936Shselasky				"GUID 0x%016" PRIx64 ", port %u\n",
655321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
656321936Shselasky				cl_ntoh16(ntc->issuer_lid),
657321936Shselasky				cl_ntoh64(gid->unicast.interface_id),
658321936Shselasky				ntc->data_details.ntc_129_131.port_num);
659321936Shselasky			break;
660321936Shselasky		case SM_LOCAL_CHANGES_TRAP:
661321936Shselasky			if (ntc->data_details.ntc_144.local_changes == 1)
662321936Shselasky				OSM_LOG(log, level,
663321936Shselasky					"Reporting Informational Notice \"%s\" from LID %u, "
664321936Shselasky					"GUID 0x%016" PRIx64 ", ChangeFlags 0x%04x, "
665321936Shselasky					"CapabilityMask2 0x%04x\n",
666321936Shselasky					ib_get_trap_str(ntc->g_or_v.generic.trap_num),
667321936Shselasky					cl_ntoh16(ntc->issuer_lid),
668321936Shselasky					cl_ntoh64(gid->unicast.interface_id),
669321936Shselasky					cl_ntoh16(ntc->data_details.ntc_144.change_flgs),
670321936Shselasky					cl_ntoh16(ntc->data_details.ntc_144.cap_mask2));
671321936Shselasky			else
672321936Shselasky				OSM_LOG(log, level,
673321936Shselasky					"Reporting Informational Notice \"%s\" from LID %u, "
674321936Shselasky					"GUID 0x%016" PRIx64 ", new CapabilityMask 0x%08x\n",
675321936Shselasky					ib_get_trap_str(ntc->g_or_v.generic.trap_num),
676321936Shselasky					cl_ntoh16(ntc->issuer_lid),
677321936Shselasky					cl_ntoh64(gid->unicast.interface_id),
678321936Shselasky					cl_ntoh32(ntc->data_details.ntc_144.new_cap_mask));
679321936Shselasky			break;
680321936Shselasky		case SM_SYS_IMG_GUID_CHANGED_TRAP:
681321936Shselasky			OSM_LOG(log, level,
682321936Shselasky				"Reporting Informational Notice \"%s\" from LID %u, "
683321936Shselasky				"GUID 0x%016" PRIx64 ", new SysImageGUID 0x%016" PRIx64 "\n",
684321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
685321936Shselasky				cl_ntoh16(ntc->issuer_lid),
686321936Shselasky				cl_ntoh64(gid->unicast.interface_id),
687321936Shselasky				cl_ntoh64(ntc->data_details.ntc_145.new_sys_guid));
688321936Shselasky			break;
689321936Shselasky		case SM_BAD_MKEY_TRAP:
690321936Shselasky			OSM_LOG(log, level,
691321936Shselasky				"Reporting Security Notice \"%s\" from LID %u, "
692321936Shselasky				"GUID 0x%016" PRIx64 ", Method 0x%x, Attribute 0x%x, "
693321936Shselasky				"AttrMod 0x%x, M_Key 0x%016" PRIx64 "\n",
694321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
695321936Shselasky				cl_ntoh16(ntc->issuer_lid),
696321936Shselasky				cl_ntoh64(gid->unicast.interface_id),
697321936Shselasky				ntc->data_details.ntc_256.method,
698321936Shselasky				cl_ntoh16(ntc->data_details.ntc_256.attr_id),
699321936Shselasky				cl_ntoh32(ntc->data_details.ntc_256.attr_mod),
700321936Shselasky				cl_ntoh64(ntc->data_details.ntc_256.mkey));
701321936Shselasky			break;
702321936Shselasky		case SM_BAD_PKEY_TRAP:
703321936Shselasky		case SM_BAD_QKEY_TRAP:
704321936Shselasky			gid1 = &ntc->data_details.ntc_257_258.gid1;
705321936Shselasky			gid2 = &ntc->data_details.ntc_257_258.gid2;
706321936Shselasky			OSM_LOG(log, level,
707321936Shselasky				"Reporting Security Notice \"%s\" from LID %u, "
708321936Shselasky				"GUID 0x%016" PRIx64 " : LID1 %u, LID2 %u, %s 0x%x, "
709321936Shselasky				"SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n",
710321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
711321936Shselasky				cl_ntoh16(ntc->issuer_lid),
712321936Shselasky				cl_ntoh64(gid->unicast.interface_id),
713321936Shselasky				cl_ntoh16(ntc->data_details.ntc_257_258.lid1),
714321936Shselasky				cl_ntoh16(ntc->data_details.ntc_257_258.lid2),
715321936Shselasky				cl_ntoh16(ntc->g_or_v.generic.trap_num) == SM_BAD_QKEY_TRAP ?
716321936Shselasky					"Q_Key" : "P_Key",
717321936Shselasky				cl_ntoh32(ntc->data_details.ntc_257_258.key),
718321936Shselasky				cl_ntoh32(ntc->data_details.ntc_257_258.qp1) >> 28,
719321936Shselasky				cl_ntoh32(ntc->data_details.ntc_257_258.qp1) & 0xffffff,
720321936Shselasky				cl_ntoh32(ntc->data_details.ntc_257_258.qp2) & 0xffffff,
721321936Shselasky				inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str),
722321936Shselasky				inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2));
723321936Shselasky			break;
724321936Shselasky		case SM_BAD_SWITCH_PKEY_TRAP:
725321936Shselasky			gid1 = &ntc->data_details.ntc_259.gid1;
726321936Shselasky			gid2 = &ntc->data_details.ntc_259.gid2;
727321936Shselasky			OSM_LOG(log, level,
728321936Shselasky				"Reporting Security Notice \"%s\" from switch LID %u, "
729321936Shselasky				"GUID 0x%016" PRIx64 " port %d : data_valid 0x%04x, "
730321936Shselasky				"LID1 %u, LID2 %u, PKey 0x%04x, "
731321936Shselasky				"SL %d, QP1 0x%x, QP2 0x%x, GID1 %s, GID2 %s\n",
732321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
733321936Shselasky				cl_ntoh16(ntc->issuer_lid),
734321936Shselasky				cl_ntoh64(gid->unicast.interface_id),
735321936Shselasky				ntc->data_details.ntc_259.port_no,
736321936Shselasky				cl_ntoh16(ntc->data_details.ntc_259.data_valid),
737321936Shselasky				cl_ntoh16(ntc->data_details.ntc_259.lid1),
738321936Shselasky				cl_ntoh16(ntc->data_details.ntc_259.lid2),
739321936Shselasky				cl_ntoh16(ntc->data_details.ntc_257_258.key),
740321936Shselasky				cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) >> 28,
741321936Shselasky				cl_ntoh32(ntc->data_details.ntc_259.sl_qp1) & 0xffffff,
742321936Shselasky				cl_ntoh32(ntc->data_details.ntc_259.qp2),
743321936Shselasky				inet_ntop(AF_INET6, gid1->raw, gid_str, sizeof gid_str),
744321936Shselasky				inet_ntop(AF_INET6, gid2->raw, gid_str2, sizeof gid_str2));
745321936Shselasky			break;
746321936Shselasky		default:
747321936Shselasky			OSM_LOG(log, level,
748321936Shselasky				"Reporting Generic Notice type:%u num:%u (%s)"
749321936Shselasky				" from LID:%u GID:%s\n",
750321936Shselasky				ib_notice_get_type(ntc),
751321936Shselasky				cl_ntoh16(ntc->g_or_v.generic.trap_num),
752321936Shselasky				ib_get_trap_str(ntc->g_or_v.generic.trap_num),
753321936Shselasky				cl_ntoh16(ntc->issuer_lid),
754321936Shselasky				inet_ntop(AF_INET6, gid->raw, gid_str, sizeof gid_str));
755321936Shselasky			break;
756321936Shselasky		}
757321936Shselasky	} else
758321936Shselasky		OSM_LOG(log, level,
759321936Shselasky			"Reporting Vendor Notice type:%u vend:%u dev:%u"
760321936Shselasky			" from LID:%u GID:%s\n",
761321936Shselasky			ib_notice_get_type(ntc),
762321936Shselasky			cl_ntoh32(ib_notice_get_vend_id(ntc)),
763321936Shselasky			cl_ntoh16(ntc->g_or_v.vend.dev_id),
764321936Shselasky			cl_ntoh16(ntc->issuer_lid),
765321936Shselasky			inet_ntop(AF_INET6, ntc->issuer_gid.raw, gid_str,
766321936Shselasky				  sizeof gid_str));
767321936Shselasky}
768321936Shselasky
769321936Shselaskyib_api_status_t osm_report_notice(IN osm_log_t * p_log, IN osm_subn_t * p_subn,
770321936Shselasky				  IN ib_mad_notice_attr_t * p_ntc)
771321936Shselasky{
772321936Shselasky	osm_infr_match_ctxt_t context;
773321936Shselasky	cl_list_t infr_to_remove_list;
774321936Shselasky	osm_infr_t *p_infr_rec;
775321936Shselasky	osm_infr_t *p_next_infr_rec;
776321936Shselasky
777321936Shselasky	OSM_LOG_ENTER(p_log);
778321936Shselasky
779321936Shselasky	/*
780321936Shselasky	 * we must make sure we are ready for this...
781321936Shselasky	 * note that the trap receivers might be initialized before
782321936Shselasky	 * the osm_infr_init call is performed.
783321936Shselasky	 */
784321936Shselasky	if (p_subn->sa_infr_list.state != CL_INITIALIZED) {
785321936Shselasky		OSM_LOG(p_log, OSM_LOG_DEBUG,
786321936Shselasky			"Ignoring Notice Reports since Inform List is not initialized yet!\n");
787321936Shselasky		return IB_ERROR;
788321936Shselasky	}
789321936Shselasky
790321936Shselasky	if (OSM_LOG_IS_ACTIVE_V2(p_log, OSM_LOG_INFO))
791321936Shselasky		log_notice(p_log, OSM_LOG_INFO, p_ntc);
792321936Shselasky
793321936Shselasky	/* Create a list that will hold all the infr records that should
794321936Shselasky	   be removed due to violation. o13-17.1.2 */
795321936Shselasky	cl_list_construct(&infr_to_remove_list);
796321936Shselasky	cl_list_init(&infr_to_remove_list, 5);
797321936Shselasky	context.p_remove_infr_list = &infr_to_remove_list;
798321936Shselasky	context.p_ntc = p_ntc;
799321936Shselasky
800321936Shselasky	/* go over all inform info available at the subnet */
801321936Shselasky	/* try match to the given notice and send if match */
802321936Shselasky	cl_qlist_apply_func(&p_subn->sa_infr_list, match_notice_to_inf_rec,
803321936Shselasky			    &context);
804321936Shselasky
805321936Shselasky	/* If we inserted items into the infr_to_remove_list - we need to
806321936Shselasky	   remove them */
807321936Shselasky	p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list);
808321936Shselasky	while (p_infr_rec != NULL) {
809321936Shselasky		p_next_infr_rec =
810321936Shselasky		    (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list);
811321936Shselasky		osm_infr_remove_from_db(p_subn, p_log, p_infr_rec);
812321936Shselasky		p_infr_rec = p_next_infr_rec;
813321936Shselasky	}
814321936Shselasky	cl_list_destroy(&infr_to_remove_list);
815321936Shselasky
816321936Shselasky	/* report IB traps to plugin */
817321936Shselasky	osm_opensm_report_event(p_subn->p_osm, OSM_EVENT_ID_TRAP, p_ntc);
818321936Shselasky
819321936Shselasky	OSM_LOG_EXIT(p_log);
820321936Shselasky
821321936Shselasky	return IB_SUCCESS;
822321936Shselasky}
823