1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff/*
37219820Sjeff * Abstract:
38219820Sjeff *    Implementation of inform record functions.
39219820Sjeff */
40219820Sjeff
41219820Sjeff#if HAVE_CONFIG_H
42219820Sjeff#  include <config.h>
43219820Sjeff#endif				/* HAVE_CONFIG_H */
44219820Sjeff
45219820Sjeff#include <stdlib.h>
46219820Sjeff#include <string.h>
47219820Sjeff#include <arpa/inet.h>
48219820Sjeff#include <complib/cl_debug.h>
49219820Sjeff#include <opensm/osm_helper.h>
50219820Sjeff#include <opensm/osm_inform.h>
51219820Sjeff#include <vendor/osm_vendor_api.h>
52219820Sjeff#include <opensm/osm_pkey.h>
53219820Sjeff#include <opensm/osm_sa.h>
54219820Sjeff#include <sys/socket.h>
55219820Sjeff
56219820Sjefftypedef struct osm_infr_match_ctxt {
57219820Sjeff	cl_list_t *p_remove_infr_list;
58219820Sjeff	ib_mad_notice_attr_t *p_ntc;
59219820Sjeff} osm_infr_match_ctxt_t;
60219820Sjeff
61219820Sjeff/**********************************************************************
62219820Sjeff **********************************************************************/
63219820Sjeffvoid osm_infr_delete(IN osm_infr_t * const p_infr)
64219820Sjeff{
65219820Sjeff	free(p_infr);
66219820Sjeff}
67219820Sjeff
68219820Sjeff/**********************************************************************
69219820Sjeff **********************************************************************/
70219820Sjeffosm_infr_t *osm_infr_new(IN const osm_infr_t * p_infr_rec)
71219820Sjeff{
72219820Sjeff	osm_infr_t *p_infr;
73219820Sjeff
74219820Sjeff	CL_ASSERT(p_infr_rec);
75219820Sjeff
76219820Sjeff	p_infr = (osm_infr_t *) malloc(sizeof(osm_infr_t));
77219820Sjeff	if (p_infr)
78219820Sjeff		memcpy(p_infr, p_infr_rec, sizeof(osm_infr_t));
79219820Sjeff
80219820Sjeff	return (p_infr);
81219820Sjeff}
82219820Sjeff
83219820Sjeff/**********************************************************************
84219820Sjeff **********************************************************************/
85219820Sjeffstatic void dump_all_informs(IN osm_subn_t const *p_subn, IN osm_log_t * p_log)
86219820Sjeff{
87219820Sjeff	cl_list_item_t *p_list_item;
88219820Sjeff
89219820Sjeff	if (!osm_log_is_active(p_log, OSM_LOG_DEBUG))
90219820Sjeff		return;
91219820Sjeff
92219820Sjeff	p_list_item = cl_qlist_head(&p_subn->sa_infr_list);
93219820Sjeff	while (p_list_item != cl_qlist_end(&p_subn->sa_infr_list)) {
94219820Sjeff		osm_dump_inform_info(p_log,
95219820Sjeff				     &((osm_infr_t *) p_list_item)->
96219820Sjeff				     inform_record.inform_info, OSM_LOG_DEBUG);
97219820Sjeff		p_list_item = cl_qlist_next(p_list_item);
98219820Sjeff	}
99219820Sjeff}
100219820Sjeff
101219820Sjeff/**********************************************************************
102219820Sjeff * Match an infr by the InformInfo and Address vector
103219820Sjeff **********************************************************************/
104219820Sjeffstatic cl_status_t
105219820Sjeff__match_inf_rec(IN const cl_list_item_t * const p_list_item, IN void *context)
106219820Sjeff{
107219820Sjeff	osm_infr_t *p_infr_rec = (osm_infr_t *) context;
108219820Sjeff	osm_infr_t *p_infr = (osm_infr_t *) p_list_item;
109219820Sjeff	osm_log_t *p_log = p_infr_rec->sa->p_log;
110219820Sjeff	cl_status_t status = CL_NOT_FOUND;
111219820Sjeff	ib_gid_t all_zero_gid;
112219820Sjeff
113219820Sjeff	OSM_LOG_ENTER(p_log);
114219820Sjeff
115219820Sjeff	if (memcmp(&p_infr->report_addr, &p_infr_rec->report_addr,
116219820Sjeff		   sizeof(p_infr_rec->report_addr))) {
117219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG, "Differ by Address\n");
118219820Sjeff		goto Exit;
119219820Sjeff	}
120219820Sjeff
121219820Sjeff	memset(&all_zero_gid, 0, sizeof(ib_gid_t));
122219820Sjeff
123219820Sjeff	/* if inform_info.gid is not zero, ignore lid range */
124219820Sjeff	if (!memcmp(&p_infr_rec->inform_record.inform_info.gid, &all_zero_gid,
125219820Sjeff		    sizeof(p_infr_rec->inform_record.inform_info.gid))) {
126219820Sjeff		if (memcmp(&p_infr->inform_record.inform_info.gid,
127219820Sjeff			   &p_infr_rec->inform_record.inform_info.gid,
128219820Sjeff			   sizeof(p_infr->inform_record.inform_info.gid))) {
129219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
130219820Sjeff				"Differ by InformInfo.gid\n");
131219820Sjeff			goto Exit;
132219820Sjeff		}
133219820Sjeff	} else {
134219820Sjeff		if ((p_infr->inform_record.inform_info.lid_range_begin !=
135219820Sjeff		     p_infr_rec->inform_record.inform_info.lid_range_begin) ||
136219820Sjeff		    (p_infr->inform_record.inform_info.lid_range_end !=
137219820Sjeff		     p_infr_rec->inform_record.inform_info.lid_range_end)) {
138219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
139219820Sjeff				"Differ by InformInfo.LIDRange\n");
140219820Sjeff			goto Exit;
141219820Sjeff		}
142219820Sjeff	}
143219820Sjeff
144219820Sjeff	if (p_infr->inform_record.inform_info.trap_type !=
145219820Sjeff	    p_infr_rec->inform_record.inform_info.trap_type) {
146219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG,
147219820Sjeff			"Differ by InformInfo.TrapType\n");
148219820Sjeff		goto Exit;
149219820Sjeff	}
150219820Sjeff
151219820Sjeff	if (p_infr->inform_record.inform_info.is_generic !=
152219820Sjeff	    p_infr_rec->inform_record.inform_info.is_generic) {
153219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG,
154219820Sjeff			"Differ by InformInfo.IsGeneric\n");
155219820Sjeff		goto Exit;
156219820Sjeff	}
157219820Sjeff
158219820Sjeff	if (p_infr->inform_record.inform_info.is_generic) {
159219820Sjeff		if (p_infr->inform_record.inform_info.g_or_v.generic.trap_num !=
160219820Sjeff		    p_infr_rec->inform_record.inform_info.g_or_v.generic.
161219820Sjeff		    trap_num)
162219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
163219820Sjeff				"Differ by InformInfo.Generic.TrapNumber\n");
164219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.generic.
165219820Sjeff			 qpn_resp_time_val !=
166219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.generic.
167219820Sjeff			 qpn_resp_time_val)
168219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
169219820Sjeff				"Differ by InformInfo.Generic.QPNRespTimeVal\n");
170219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.generic.
171219820Sjeff			 node_type_msb !=
172219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.generic.
173219820Sjeff			 node_type_msb)
174219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
175219820Sjeff				"Differ by InformInfo.Generic.NodeTypeMSB\n");
176219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.generic.
177219820Sjeff			 node_type_lsb !=
178219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.generic.
179219820Sjeff			 node_type_lsb)
180219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
181219820Sjeff				"Differ by InformInfo.Generic.NodeTypeLSB\n");
182219820Sjeff		else
183219820Sjeff			status = CL_SUCCESS;
184219820Sjeff	} else {
185219820Sjeff		if (p_infr->inform_record.inform_info.g_or_v.vend.dev_id !=
186219820Sjeff		    p_infr_rec->inform_record.inform_info.g_or_v.vend.dev_id)
187219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
188219820Sjeff				"Differ by InformInfo.Vendor.DeviceID\n");
189219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.vend.
190219820Sjeff			 qpn_resp_time_val !=
191219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.vend.
192219820Sjeff			 qpn_resp_time_val)
193219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
194219820Sjeff				"Differ by InformInfo.Vendor.QPNRespTimeVal\n");
195219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.vend.
196219820Sjeff			 vendor_id_msb !=
197219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.vend.
198219820Sjeff			 vendor_id_msb)
199219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
200219820Sjeff				"Differ by InformInfo.Vendor.VendorIdMSB\n");
201219820Sjeff		else if (p_infr->inform_record.inform_info.g_or_v.vend.
202219820Sjeff			 vendor_id_lsb !=
203219820Sjeff			 p_infr_rec->inform_record.inform_info.g_or_v.vend.
204219820Sjeff			 vendor_id_lsb)
205219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
206219820Sjeff				"Differ by InformInfo.Vendor.VendorIdLSB\n");
207219820Sjeff		else
208219820Sjeff			status = CL_SUCCESS;
209219820Sjeff	}
210219820Sjeff
211219820SjeffExit:
212219820Sjeff	OSM_LOG_EXIT(p_log);
213219820Sjeff	return status;
214219820Sjeff}
215219820Sjeff
216219820Sjeff/**********************************************************************
217219820Sjeff **********************************************************************/
218219820Sjeffosm_infr_t *osm_infr_get_by_rec(IN osm_subn_t const *p_subn,
219219820Sjeff				IN osm_log_t * p_log,
220219820Sjeff				IN osm_infr_t * const p_infr_rec)
221219820Sjeff{
222219820Sjeff	cl_list_item_t *p_list_item;
223219820Sjeff
224219820Sjeff	OSM_LOG_ENTER(p_log);
225219820Sjeff
226219820Sjeff	dump_all_informs(p_subn, p_log);
227219820Sjeff
228219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Looking for Inform Record\n");
229219820Sjeff	osm_dump_inform_info(p_log, &(p_infr_rec->inform_record.inform_info),
230219820Sjeff			     OSM_LOG_DEBUG);
231219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "InformInfo list size %d\n",
232219820Sjeff		cl_qlist_count(&p_subn->sa_infr_list));
233219820Sjeff
234219820Sjeff	p_list_item = cl_qlist_find_from_head(&p_subn->sa_infr_list,
235219820Sjeff					      __match_inf_rec, p_infr_rec);
236219820Sjeff
237219820Sjeff	if (p_list_item == cl_qlist_end(&p_subn->sa_infr_list))
238219820Sjeff		p_list_item = NULL;
239219820Sjeff
240219820Sjeff	OSM_LOG_EXIT(p_log);
241219820Sjeff	return (osm_infr_t *) p_list_item;
242219820Sjeff}
243219820Sjeff
244219820Sjeff/**********************************************************************
245219820Sjeff **********************************************************************/
246219820Sjeffvoid
247219820Sjeffosm_infr_insert_to_db(IN osm_subn_t * p_subn,
248219820Sjeff		      IN osm_log_t * p_log, IN osm_infr_t * p_infr)
249219820Sjeff{
250219820Sjeff	OSM_LOG_ENTER(p_log);
251219820Sjeff
252219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG,
253219820Sjeff		"Inserting new InformInfo Record into Database\n");
254219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump before insertion (size %d)\n",
255219820Sjeff		cl_qlist_count(&p_subn->sa_infr_list));
256219820Sjeff	dump_all_informs(p_subn, p_log);
257219820Sjeff
258219820Sjeff#if 0
259219820Sjeff	osm_dump_inform_info(p_log,
260219820Sjeff			     &(p_infr->inform_record.inform_info),
261219820Sjeff			     OSM_LOG_DEBUG);
262219820Sjeff#endif
263219820Sjeff
264219820Sjeff	cl_qlist_insert_head(&p_subn->sa_infr_list, &p_infr->list_item);
265219820Sjeff
266219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Dump after insertion (size %d)\n",
267219820Sjeff		cl_qlist_count(&p_subn->sa_infr_list));
268219820Sjeff	dump_all_informs(p_subn, p_log);
269219820Sjeff	OSM_LOG_EXIT(p_log);
270219820Sjeff}
271219820Sjeff
272219820Sjeff/**********************************************************************
273219820Sjeff **********************************************************************/
274219820Sjeffvoid
275219820Sjeffosm_infr_remove_from_db(IN osm_subn_t * p_subn,
276219820Sjeff			IN osm_log_t * p_log, IN osm_infr_t * p_infr)
277219820Sjeff{
278219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
279219820Sjeff	OSM_LOG_ENTER(p_log);
280219820Sjeff
281219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Removing InformInfo Subscribing GID:%s"
282219820Sjeff		" Enum:0x%X from Database\n",
283219820Sjeff		inet_ntop(AF_INET6, p_infr->inform_record.subscriber_gid.raw,
284219820Sjeff			gid_str, sizeof gid_str),
285219820Sjeff		p_infr->inform_record.subscriber_enum);
286219820Sjeff
287219820Sjeff	osm_dump_inform_info(p_log, &(p_infr->inform_record.inform_info),
288219820Sjeff			     OSM_LOG_DEBUG);
289219820Sjeff
290219820Sjeff	cl_qlist_remove_item(&p_subn->sa_infr_list, &p_infr->list_item);
291219820Sjeff
292219820Sjeff	osm_infr_delete(p_infr);
293219820Sjeff
294219820Sjeff	OSM_LOG_EXIT(p_log);
295219820Sjeff}
296219820Sjeff
297219820Sjeff/**********************************************************************
298219820Sjeff * Send a report:
299219820Sjeff * Given a target address to send to and the notice.
300219820Sjeff * We need to send SubnAdmReport
301219820Sjeff **********************************************************************/
302219820Sjeffstatic ib_api_status_t __osm_send_report(IN osm_infr_t * p_infr_rec,	/* the informinfo */
303219820Sjeff					 IN ib_mad_notice_attr_t * p_ntc	/* notice to send */
304219820Sjeff    )
305219820Sjeff{
306219820Sjeff	osm_madw_t *p_report_madw;
307219820Sjeff	ib_mad_notice_attr_t *p_report_ntc;
308219820Sjeff	ib_mad_t *p_mad;
309219820Sjeff	ib_sa_mad_t *p_sa_mad;
310219820Sjeff	static atomic32_t trap_fwd_trans_id = 0x02DAB000;
311219820Sjeff	ib_api_status_t status = IB_SUCCESS;
312219820Sjeff	osm_log_t *p_log = p_infr_rec->sa->p_log;
313219820Sjeff
314219820Sjeff	OSM_LOG_ENTER(p_log);
315219820Sjeff
316219820Sjeff	/* HACK: who switches or uses the src and dest GIDs in the grh_info ?? */
317219820Sjeff
318219820Sjeff	/* it is better to use LIDs since the GIDs might not be there for SMI traps */
319219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "Forwarding Notice Event from LID:%u"
320219820Sjeff		" to InformInfo LID: %u TID:0x%X\n",
321219820Sjeff		cl_ntoh16(p_ntc->issuer_lid),
322219820Sjeff		cl_ntoh16(p_infr_rec->report_addr.dest_lid), trap_fwd_trans_id);
323219820Sjeff
324219820Sjeff	/* get the MAD to send */
325219820Sjeff	p_report_madw = osm_mad_pool_get(p_infr_rec->sa->p_mad_pool,
326219820Sjeff					 p_infr_rec->h_bind, MAD_BLOCK_SIZE,
327219820Sjeff					 &(p_infr_rec->report_addr));
328219820Sjeff
329219820Sjeff	p_report_madw->resp_expected = TRUE;
330219820Sjeff
331219820Sjeff	if (!p_report_madw) {
332219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 0203"
333219820Sjeff			"osm_mad_pool_get failed\n");
334219820Sjeff		status = IB_ERROR;
335219820Sjeff		goto Exit;
336219820Sjeff	}
337219820Sjeff
338219820Sjeff	/* advance trap trans id (cant simply ++ on some systems inside ntoh) */
339219820Sjeff	p_mad = osm_madw_get_mad_ptr(p_report_madw);
340219820Sjeff	ib_mad_init_new(p_mad, IB_MCLASS_SUBN_ADM, 2, IB_MAD_METHOD_REPORT,
341219820Sjeff			cl_hton64((uint64_t) cl_atomic_inc(&trap_fwd_trans_id)),
342219820Sjeff			IB_MAD_ATTR_NOTICE, 0);
343219820Sjeff
344219820Sjeff	p_sa_mad = osm_madw_get_sa_mad_ptr(p_report_madw);
345219820Sjeff
346219820Sjeff	p_report_ntc = (ib_mad_notice_attr_t *) & (p_sa_mad->data);
347219820Sjeff
348219820Sjeff	/* copy the notice */
349219820Sjeff	*p_report_ntc = *p_ntc;
350219820Sjeff
351219820Sjeff	/* The TRUE is for: response is expected */
352219820Sjeff	osm_sa_send(p_infr_rec->sa, p_report_madw, TRUE);
353219820Sjeff
354219820SjeffExit:
355219820Sjeff	OSM_LOG_EXIT(p_log);
356219820Sjeff	return (status);
357219820Sjeff}
358219820Sjeff
359219820Sjeff/**********************************************************************
360219820Sjeff * This routine compares a given Notice and a ListItem of InformInfo type.
361219820Sjeff * PREREQUISITE:
362219820Sjeff * The Notice.GID should be pre-filled with the trap generator GID
363219820Sjeff **********************************************************************/
364219820Sjeffstatic void
365219820Sjeff__match_notice_to_inf_rec(IN cl_list_item_t * const p_list_item,
366219820Sjeff			  IN void *context)
367219820Sjeff{
368219820Sjeff	osm_infr_match_ctxt_t *p_infr_match = (osm_infr_match_ctxt_t *) context;
369219820Sjeff	ib_mad_notice_attr_t *p_ntc = p_infr_match->p_ntc;
370219820Sjeff	cl_list_t *p_infr_to_remove_list = p_infr_match->p_remove_infr_list;
371219820Sjeff	osm_infr_t *p_infr_rec = (osm_infr_t *) p_list_item;
372219820Sjeff	ib_inform_info_t *p_ii = &(p_infr_rec->inform_record.inform_info);
373219820Sjeff	cl_status_t status = CL_NOT_FOUND;
374219820Sjeff	osm_log_t *p_log = p_infr_rec->sa->p_log;
375219820Sjeff	osm_subn_t *p_subn = p_infr_rec->sa->p_subn;
376219820Sjeff	ib_gid_t source_gid;
377219820Sjeff	osm_port_t *p_src_port;
378219820Sjeff	osm_port_t *p_dest_port;
379219820Sjeff
380219820Sjeff	OSM_LOG_ENTER(p_log);
381219820Sjeff
382219820Sjeff	/* matching rules
383219820Sjeff	 * InformInfo   Notice
384219820Sjeff	 * GID          IssuerGID    if non zero must match the trap
385219820Sjeff	 * LIDRange     IssuerLID    apply only if GID=0
386219820Sjeff	 * IsGeneric    IsGeneric    is compulsory and must match the trap
387219820Sjeff	 * Type         Type         if not 0xFFFF must match
388219820Sjeff	 * TrapNumber   TrapNumber   if not 0xFFFF must match
389219820Sjeff	 * DeviceId     DeviceID     if not 0xFFFF must match
390219820Sjeff	 * QPN dont care
391219820Sjeff	 * ProducerType ProducerType match or 0xFFFFFF // EZ: actually my interpretation
392219820Sjeff	 * VendorID     VendorID     match or 0xFFFFFF
393219820Sjeff	 */
394219820Sjeff
395219820Sjeff	/* GID          IssuerGID    if non zero must match the trap  */
396219820Sjeff	if (p_ii->gid.unicast.prefix != 0
397219820Sjeff	    || p_ii->gid.unicast.interface_id != 0) {
398219820Sjeff		/* match by GID */
399219820Sjeff		if (memcmp(&(p_ii->gid), &(p_ntc->issuer_gid),
400219820Sjeff			   sizeof(ib_gid_t))) {
401219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by GID\n");
402219820Sjeff			goto Exit;
403219820Sjeff		}
404219820Sjeff	} else {
405219820Sjeff		/* LIDRange     IssuerLID    apply only if GID=0 */
406219820Sjeff		/* If lid_range_begin of the informInfo is 0xFFFF - then it should be ignored. */
407219820Sjeff		if (p_ii->lid_range_begin != 0xFFFF) {
408219820Sjeff			/* a real lid range is given - check it */
409219820Sjeff			if ((cl_hton16(p_ii->lid_range_begin) >
410219820Sjeff			     cl_hton16(p_ntc->issuer_lid))
411219820Sjeff			    || (cl_hton16(p_ntc->issuer_lid) >
412219820Sjeff				cl_hton16(p_ii->lid_range_end))) {
413219820Sjeff				OSM_LOG(p_log, OSM_LOG_DEBUG,
414219820Sjeff					"Mismatch by LID Range. Needed: %u <= %u <= %u\n",
415219820Sjeff					cl_hton16(p_ii->lid_range_begin),
416219820Sjeff					cl_hton16(p_ntc->issuer_lid),
417219820Sjeff					cl_hton16(p_ii->lid_range_end));
418219820Sjeff				goto Exit;
419219820Sjeff			}
420219820Sjeff		}
421219820Sjeff	}
422219820Sjeff
423219820Sjeff	/* IsGeneric    IsGeneric    is compulsory and must match the trap  */
424219820Sjeff	if ((p_ii->is_generic && !ib_notice_is_generic(p_ntc)) ||
425219820Sjeff	    (!p_ii->is_generic && ib_notice_is_generic(p_ntc))) {
426219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Generic/Vendor\n");
427219820Sjeff		goto Exit;
428219820Sjeff	}
429219820Sjeff
430219820Sjeff	/* Type         Type         if not 0xFFFF must match */
431219820Sjeff	if ((p_ii->trap_type != 0xFFFF) &&
432219820Sjeff	    (cl_ntoh16(p_ii->trap_type) != ib_notice_get_type(p_ntc))) {
433219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Type\n");
434219820Sjeff		goto Exit;
435219820Sjeff	}
436219820Sjeff
437219820Sjeff	/* based on generic type */
438219820Sjeff	if (p_ii->is_generic) {
439219820Sjeff		/* TrapNumber   TrapNumber   if not 0xFFFF must match */
440219820Sjeff		if ((p_ii->g_or_v.generic.trap_num != 0xFFFF) &&
441219820Sjeff		    (p_ii->g_or_v.generic.trap_num !=
442219820Sjeff		     p_ntc->g_or_v.generic.trap_num)) {
443219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Trap Num\n");
444219820Sjeff			goto Exit;
445219820Sjeff		}
446219820Sjeff
447219820Sjeff		/* ProducerType ProducerType match or 0xFFFFFF  */
448219820Sjeff		if ((cl_ntoh32(ib_inform_info_get_prod_type(p_ii)) != 0xFFFFFF)
449219820Sjeff		    && (ib_inform_info_get_prod_type(p_ii) !=
450219820Sjeff			ib_notice_get_prod_type(p_ntc))) {
451219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
452219820Sjeff				"Mismatch by Node Type: II=0x%06X (%s) Trap=0x%06X (%s)\n",
453219820Sjeff				cl_ntoh32(ib_inform_info_get_prod_type(p_ii)),
454219820Sjeff				ib_get_producer_type_str
455219820Sjeff				(ib_inform_info_get_prod_type(p_ii)),
456219820Sjeff				cl_ntoh32(ib_notice_get_prod_type(p_ntc)),
457219820Sjeff				ib_get_producer_type_str(ib_notice_get_prod_type
458219820Sjeff							 (p_ntc)));
459219820Sjeff			goto Exit;
460219820Sjeff		}
461219820Sjeff	} else {
462219820Sjeff		/* DeviceId     DeviceID     if not 0xFFFF must match */
463219820Sjeff		if ((p_ii->g_or_v.vend.dev_id != 0xFFFF) &&
464219820Sjeff		    (p_ii->g_or_v.vend.dev_id != p_ntc->g_or_v.vend.dev_id)) {
465219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Dev Id\n");
466219820Sjeff			goto Exit;
467219820Sjeff		}
468219820Sjeff
469219820Sjeff		/* VendorID     VendorID     match or 0xFFFFFF  */
470219820Sjeff		if ((ib_inform_info_get_vend_id(p_ii) != CL_HTON32(0xFFFFFF)) &&
471219820Sjeff		    (ib_inform_info_get_vend_id(p_ii) !=
472219820Sjeff		     ib_notice_get_vend_id(p_ntc))) {
473219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Vendor ID\n");
474219820Sjeff			goto Exit;
475219820Sjeff		}
476219820Sjeff	}
477219820Sjeff
478219820Sjeff	/* Check if there is a pkey match. o13-17.1.1 */
479219820Sjeff	/* Check if the issuer of the trap is the SM. If it is, then the gid
480219820Sjeff	   comparison should be done on the trap source (saved as the gid in the
481219820Sjeff	   data details field).
482219820Sjeff	   If the issuer gid is not the SM - then it is the guid of the trap
483219820Sjeff	   source */
484219820Sjeff	if ((cl_ntoh64(p_ntc->issuer_gid.unicast.prefix) ==
485219820Sjeff	     p_subn->opt.subnet_prefix)
486219820Sjeff	    && (cl_ntoh64(p_ntc->issuer_gid.unicast.interface_id) ==
487219820Sjeff		p_subn->sm_port_guid))
488219820Sjeff		/* The issuer is the SM then this is trap 64-67 - compare the gid
489219820Sjeff		   with the gid saved on the data details */
490219820Sjeff		source_gid = p_ntc->data_details.ntc_64_67.gid;
491219820Sjeff	else
492219820Sjeff		source_gid = p_ntc->issuer_gid;
493219820Sjeff
494219820Sjeff	p_src_port =
495219820Sjeff	    osm_get_port_by_guid(p_subn, source_gid.unicast.interface_id);
496219820Sjeff	if (!p_src_port) {
497219820Sjeff		OSM_LOG(p_log, OSM_LOG_INFO,
498219820Sjeff			"Cannot find source port with GUID:0x%016" PRIx64 "\n",
499219820Sjeff			cl_ntoh64(source_gid.unicast.interface_id));
500219820Sjeff		goto Exit;
501219820Sjeff	}
502219820Sjeff
503219820Sjeff	p_dest_port =
504219820Sjeff	    cl_ptr_vector_get(&p_subn->port_lid_tbl,
505219820Sjeff			      cl_ntoh16(p_infr_rec->report_addr.dest_lid));
506219820Sjeff	if (!p_dest_port) {
507219820Sjeff		OSM_LOG(p_log, OSM_LOG_INFO,
508219820Sjeff			"Cannot find destination port with LID:%u\n",
509219820Sjeff			cl_ntoh16(p_infr_rec->report_addr.dest_lid));
510219820Sjeff		goto Exit;
511219820Sjeff	}
512219820Sjeff
513219820Sjeff	if (osm_port_share_pkey(p_log, p_src_port, p_dest_port) == FALSE) {
514219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG, "Mismatch by Pkey\n");
515219820Sjeff		/* According to o13-17.1.2 - If this informInfo does not have
516219820Sjeff		   lid_range_begin of 0xFFFF, then this informInfo request
517219820Sjeff		   should be removed from database */
518219820Sjeff		if (p_ii->lid_range_begin != 0xFFFF) {
519219820Sjeff			OSM_LOG(p_log, OSM_LOG_VERBOSE,
520219820Sjeff				"Pkey mismatch on lid_range_begin != 0xFFFF. "
521219820Sjeff				"Need to remove this informInfo from db\n");
522219820Sjeff			/* add the informInfo record to the remove_infr list */
523219820Sjeff			cl_list_insert_tail(p_infr_to_remove_list, p_infr_rec);
524219820Sjeff		}
525219820Sjeff		goto Exit;
526219820Sjeff	}
527219820Sjeff
528219820Sjeff	/* send the report to the address provided in the inform record */
529219820Sjeff	OSM_LOG(p_log, OSM_LOG_DEBUG, "MATCH! Sending Report...\n");
530219820Sjeff	__osm_send_report(p_infr_rec, p_ntc);
531219820Sjeff	status = CL_SUCCESS;
532219820Sjeff
533219820SjeffExit:
534219820Sjeff	OSM_LOG_EXIT(p_log);
535219820Sjeff}
536219820Sjeff
537219820Sjeff/**********************************************************************
538219820Sjeff * Once a Trap was received by osm_trap_rcv, or a Trap sourced by
539219820Sjeff * the SM was sent (Traps 64-67), this routine is called with a copy of
540219820Sjeff * the notice data.
541219820Sjeff * Given a notice attribute - compare and see if it matches the InformInfo
542219820Sjeff * element and if it does - call the Report(Notice) for the
543219820Sjeff * target QP registered by the address stored in the InformInfo element
544219820Sjeff **********************************************************************/
545219820Sjeffib_api_status_t
546219820Sjeffosm_report_notice(IN osm_log_t * const p_log,
547219820Sjeff		  IN osm_subn_t * p_subn, IN ib_mad_notice_attr_t * p_ntc)
548219820Sjeff{
549219820Sjeff	char gid_str[INET6_ADDRSTRLEN];
550219820Sjeff	osm_infr_match_ctxt_t context;
551219820Sjeff	cl_list_t infr_to_remove_list;
552219820Sjeff	osm_infr_t *p_infr_rec;
553219820Sjeff	osm_infr_t *p_next_infr_rec;
554219820Sjeff
555219820Sjeff	OSM_LOG_ENTER(p_log);
556219820Sjeff
557219820Sjeff	/*
558219820Sjeff	 * we must make sure we are ready for this...
559219820Sjeff	 * note that the trap receivers might be initialized before
560219820Sjeff	 * the osm_infr_init call is performed.
561219820Sjeff	 */
562219820Sjeff	if (p_subn->sa_infr_list.state != CL_INITIALIZED) {
563219820Sjeff		OSM_LOG(p_log, OSM_LOG_DEBUG,
564219820Sjeff			"Ignoring Notice Reports since Inform List is not initialized yet!\n");
565219820Sjeff		return (IB_ERROR);
566219820Sjeff	}
567219820Sjeff
568219820Sjeff	/* an official Event information log */
569219820Sjeff	if (ib_notice_is_generic(p_ntc))
570219820Sjeff		OSM_LOG(p_log, OSM_LOG_INFO,
571219820Sjeff			"Reporting Generic Notice type:%u num:%u (%s)"
572219820Sjeff			" from LID:%u GID:%s\n",
573219820Sjeff			ib_notice_get_type(p_ntc),
574219820Sjeff			cl_ntoh16(p_ntc->g_or_v.generic.trap_num),
575219820Sjeff			ib_get_trap_str(p_ntc->g_or_v.generic.trap_num),
576219820Sjeff			cl_ntoh16(p_ntc->issuer_lid),
577219820Sjeff			inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str,
578219820Sjeff				sizeof gid_str));
579219820Sjeff	else
580219820Sjeff		OSM_LOG(p_log, OSM_LOG_INFO,
581219820Sjeff			"Reporting Vendor Notice type:%u vend:%u dev:%u"
582219820Sjeff			" from LID:%u GID:%s\n",
583219820Sjeff			ib_notice_get_type(p_ntc),
584219820Sjeff			cl_ntoh32(ib_notice_get_vend_id(p_ntc)),
585219820Sjeff			cl_ntoh16(p_ntc->g_or_v.vend.dev_id),
586219820Sjeff			cl_ntoh16(p_ntc->issuer_lid),
587219820Sjeff			inet_ntop(AF_INET6, p_ntc->issuer_gid.raw, gid_str,
588219820Sjeff				sizeof gid_str));
589219820Sjeff
590219820Sjeff	/* Create a list that will hold all the infr records that should
591219820Sjeff	   be removed due to violation. o13-17.1.2 */
592219820Sjeff	cl_list_construct(&infr_to_remove_list);
593219820Sjeff	cl_list_init(&infr_to_remove_list, 5);
594219820Sjeff	context.p_remove_infr_list = &infr_to_remove_list;
595219820Sjeff	context.p_ntc = p_ntc;
596219820Sjeff
597219820Sjeff	/* go over all inform info available at the subnet */
598219820Sjeff	/* try match to the given notice and send if match */
599219820Sjeff	cl_qlist_apply_func(&(p_subn->sa_infr_list),
600219820Sjeff			    __match_notice_to_inf_rec, &context);
601219820Sjeff
602219820Sjeff	/* If we inserted items into the infr_to_remove_list - we need to
603219820Sjeff	   remove them */
604219820Sjeff	p_infr_rec = (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list);
605219820Sjeff	while (p_infr_rec != NULL) {
606219820Sjeff		p_next_infr_rec =
607219820Sjeff		    (osm_infr_t *) cl_list_remove_head(&infr_to_remove_list);
608219820Sjeff		osm_infr_remove_from_db(p_subn, p_log, p_infr_rec);
609219820Sjeff		p_infr_rec = p_next_infr_rec;
610219820Sjeff	}
611219820Sjeff	cl_list_destroy(&infr_to_remove_list);
612219820Sjeff
613219820Sjeff	OSM_LOG_EXIT(p_log);
614219820Sjeff
615219820Sjeff	return (IB_SUCCESS);
616219820Sjeff}
617