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