]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_trap_rcv.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / opensm / opensm / osm_trap_rcv.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2006 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 osm_trap_rcv_t.
39  * This object represents the Trap Receiver object.
40  * This object is part of the opensm family of objects.
41  */
42
43 #if HAVE_CONFIG_H
44 #  include <config.h>
45 #endif                          /* HAVE_CONFIG_H */
46
47 #include <string.h>
48 #include <iba/ib_types.h>
49 #include <complib/cl_qmap.h>
50 #include <complib/cl_debug.h>
51 #include <opensm/osm_madw.h>
52 #include <opensm/osm_log.h>
53 #include <opensm/osm_node.h>
54 #include <opensm/osm_helper.h>
55 #include <opensm/osm_subnet.h>
56 #include <opensm/osm_inform.h>
57 #include <opensm/osm_opensm.h>
58
59 extern void osm_req_get_node_desc(IN osm_sm_t * sm, osm_physp_t *p_physp);
60
61 /**********************************************************************
62  *
63  * TRAP HANDLING:
64  *
65  * Assuming traps can be caused by bad hardware we should provide
66  * a mechanism for filtering their propagation into the actual logic
67  * of OpenSM such that it is not overloaded by them.
68  *
69  * We will provide a trap filtering mechanism with "Aging" capability.
70  * This mechanism will track incoming traps, clasify them by their
71  * source and content and provide back their age.
72  *
73  * A timer running in the background will toggle a timer counter
74  * that should be referenced by the aging algorithm.
75  * To provide an efficient handling of aging. We also track all traps
76  * in a sorted list by their aging.
77  *
78  * The generic Aging Tracker mechanism is implemented in the
79  * cl_aging_tracker object.
80  *
81  **********************************************************************/
82
83 typedef struct osm_trap_agingracker_context {
84         osm_log_t *p_log;
85         osm_physp_t *p_physp;
86 } osm_trap_aging_tracker_context_t;
87
88 /**********************************************************************
89  **********************************************************************/
90 static osm_physp_t *get_physp_by_lid_and_num(IN osm_sm_t * sm,
91                                              IN uint16_t lid, IN uint8_t num)
92 {
93         cl_ptr_vector_t *p_vec = &(sm->p_subn->port_lid_tbl);
94         osm_port_t *p_port;
95
96         if (lid > cl_ptr_vector_get_size(p_vec))
97                 return NULL;
98
99         p_port = (osm_port_t *) cl_ptr_vector_get(p_vec, lid);
100         if (!p_port)
101                 return NULL;
102
103         if (osm_node_get_num_physp(p_port->p_node) < num)
104                 return NULL;
105
106         return osm_node_get_physp_ptr(p_port->p_node, num);
107 }
108
109 /**********************************************************************
110  **********************************************************************/
111 uint64_t
112 osm_trap_rcv_aging_tracker_callback(IN uint64_t key,
113                                     IN uint32_t num_regs, IN void *context)
114 {
115         osm_sm_t *sm = context;
116         uint16_t lid;
117         uint8_t port_num;
118         osm_physp_t *p_physp;
119
120         OSM_LOG_ENTER(sm->p_log);
121
122         if (osm_exit_flag)
123                 /* We got an exit flag - do nothing */
124                 return 0;
125
126         lid = cl_ntoh16((uint16_t) ((key & 0x0000FFFF00000000ULL) >> 32));
127         port_num = (uint8_t) ((key & 0x00FF000000000000ULL) >> 48);
128
129         p_physp = get_physp_by_lid_and_num(sm, lid, port_num);
130         if (!p_physp)
131                 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
132                         "Cannot find port num:%u with lid:%u\n",
133                         port_num, lid);
134         /* make sure the physp is still valid */
135         /* If the health port was false - set it to true */
136         else if (!osm_physp_is_healthy(p_physp)) {
137                 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
138                         "Clearing health bit of port num:%u with lid:%u\n",
139                         port_num, lid);
140
141                 /* Clear its health bit */
142                 osm_physp_set_health(p_physp, TRUE);
143         }
144
145         OSM_LOG_EXIT(sm->p_log);
146
147         /* We want to remove the event from the tracker - so
148            need to return zero. */
149         return 0;
150 }
151
152 /**********************************************************************
153  * CRC calculation for notice identification
154  **********************************************************************/
155
156 #define CRC32_POLYNOMIAL   0xEDB88320L
157
158 /* calculate the crc for a given buffer */
159 static uint32_t __osm_trap_calc_crc32(void *buffer, uint32_t count)
160 {
161         uint32_t temp1, temp2;
162         uint32_t crc = -1L;
163         unsigned char *p = (unsigned char *)buffer;
164         /* pre - calculated table for faster crc calculation */
165         static uint32_t crc_table[256];
166         static boolean_t first = TRUE;
167         int i, j;
168
169         /* if we need to initialize the lookup table */
170         if (first) {
171                 /* calc the CRC table */
172                 for (i = 0; i <= 255; i++) {
173                         crc = i;
174                         for (j = 8; j > 0; j--)
175                                 if (crc & 1)
176                                         crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
177                                 else
178                                         crc >>= 1;
179                         crc_table[i] = crc;
180                 }
181                 first = FALSE;
182         }
183
184         crc = -1L;
185         /* do the calculation */
186         while (count-- != 0) {
187                 temp1 = (crc >> 8) & 0x00FFFFFFL;
188                 temp2 = crc_table[((int)crc ^ *p++) & 0xFF];
189                 crc = temp1 ^ temp2;
190         }
191         return crc;
192 }
193
194 /********************************************************************
195  ********************************************************************/
196
197 /* The key is created in the following manner:
198    port_num  lid   crc
199    \______/ \___/ \___/
200      16b     16b   32b
201 */
202 static void
203 __osm_trap_get_key(IN uint16_t lid,
204                    IN uint8_t port_num,
205                    IN ib_mad_notice_attr_t * p_ntci, OUT uint64_t * trap_key)
206 {
207         uint32_t crc = 0;
208
209         CL_ASSERT(trap_key);
210
211         crc = __osm_trap_calc_crc32(p_ntci, sizeof(ib_mad_notice_attr_t));
212         *trap_key = ((uint64_t) port_num << 48) | ((uint64_t) lid << 32) | crc;
213 }
214
215 /**********************************************************************
216  **********************************************************************/
217 static int __print_num_received(IN uint32_t num_received)
218 {
219         uint32_t i;
220
221         /* Series is 10, 20, 50, 100, 200, 500, ... */
222         i = num_received;
223         while (i >= 10) {
224                 if (i % 10)
225                         break;
226                 i = i / 10;
227         }
228
229         if (i == 1 || i == 2 || i == 5)
230                 return 1;
231         else
232                 return 0;
233 }
234
235 static int disable_port(osm_sm_t *sm, osm_physp_t *p)
236 {
237         uint8_t payload[IB_SMP_DATA_SIZE];
238         osm_madw_context_t context;
239         ib_port_info_t *pi = (ib_port_info_t *)payload;
240         int ret;
241
242         /* select the nearest port to master opensm */
243         if (p->p_remote_physp &&
244             p->dr_path.hop_count > p->p_remote_physp->dr_path.hop_count)
245                 p = p->p_remote_physp;
246
247         /* If trap 131, might want to disable peer port if available */
248         /* but peer port has been observed not to respond to SM requests */
249
250         OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3810: "
251                 "Disabling physical port 0x%016" PRIx64 " num:%u\n",
252                 cl_ntoh64(osm_physp_get_port_guid(p)), p->port_num);
253
254         memcpy(payload, &p->port_info, sizeof(ib_port_info_t));
255
256         /* Set port to disabled/down */
257         ib_port_info_set_port_state(pi, IB_LINK_DOWN);
258         ib_port_info_set_port_phys_state(IB_PORT_PHYS_STATE_DISABLED, pi);
259
260         /* Issue set of PortInfo */
261         context.pi_context.node_guid = osm_node_get_node_guid(p->p_node);
262         context.pi_context.port_guid = osm_physp_get_port_guid(p);
263         context.pi_context.set_method = TRUE;
264         context.pi_context.light_sweep = FALSE;
265         context.pi_context.active_transition = FALSE;
266
267         ret = osm_req_set(sm, osm_physp_get_dr_path_ptr(p),
268                           payload, sizeof(payload), IB_MAD_ATTR_PORT_INFO,
269                           cl_hton32(osm_physp_get_port_num(p)),
270                           CL_DISP_MSGID_NONE, &context);
271         if (ret)
272                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3811: "
273                         "Request to set PortInfo failed\n");
274
275         return ret;
276 }
277
278 /**********************************************************************
279  **********************************************************************/
280 static void
281 __osm_trap_rcv_process_request(IN osm_sm_t * sm,
282                                IN const osm_madw_t * const p_madw)
283 {
284         uint8_t payload[sizeof(ib_mad_notice_attr_t)];
285         ib_smp_t *p_smp;
286         ib_mad_notice_attr_t *p_ntci = (ib_mad_notice_attr_t *) payload;
287         ib_api_status_t status;
288         osm_madw_t tmp_madw;    /* we need a copy to last after repress */
289         uint64_t trap_key;
290         uint32_t num_received;
291         osm_physp_t *p_physp;
292         cl_ptr_vector_t *p_tbl;
293         osm_port_t *p_port;
294         ib_net16_t source_lid = 0;
295         boolean_t is_gsi = TRUE;
296         uint8_t port_num = 0;
297         boolean_t physp_change_trap = FALSE;
298         uint64_t event_wheel_timeout = OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT;
299         boolean_t run_heavy_sweep = FALSE;
300
301         OSM_LOG_ENTER(sm->p_log);
302
303         CL_ASSERT(p_madw);
304
305         if (osm_exit_flag)
306                 /*
307                    We got an exit flag - do nothing
308                    Otherwise we start a sweep on the trap 144 caused by
309                    cleaning up SM Cap bit...
310                  */
311                 goto Exit;
312
313         /* update the is_gsi flag according to the mgmt_class field */
314         if (p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_LID ||
315             p_madw->p_mad->mgmt_class == IB_MCLASS_SUBN_DIR)
316                 is_gsi = FALSE;
317
318         /* No real need to grab the lock for this function. */
319         memset(payload, 0, sizeof(payload));
320         memset(&tmp_madw, 0, sizeof(tmp_madw));
321
322         p_smp = osm_madw_get_smp_ptr(p_madw);
323
324         if (p_smp->method != IB_MAD_METHOD_TRAP) {
325                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3801: "
326                         "Unsupported method 0x%X\n", p_smp->method);
327                 goto Exit;
328         }
329
330         /*
331          * The NOTICE Attribute is part of the SMP CLASS attributes
332          * As such the actual attribute data resides inside the SMP
333          * payload.
334          */
335
336         memcpy(payload, &(p_smp->data), IB_SMP_DATA_SIZE);
337         memcpy(&tmp_madw, p_madw, sizeof(tmp_madw));
338
339         if (is_gsi == FALSE) {
340                 /* We are in smi flow */
341                 /*
342                  * When we received a TRAP with dlid = 0 - it means it
343                  * came from our own node. So we need to fix it.
344                  */
345
346                 if (p_madw->mad_addr.addr_type.smi.source_lid == 0) {
347                         /* Check if the sm_base_lid is 0. If yes - this means
348                            that the local lid wasn't configured yet. Don't send
349                            a response to the trap. */
350                         if (sm->p_subn->sm_base_lid == 0) {
351                                 OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
352                                         "Received SLID=0 Trap with local LID=0. Ignoring MAD\n");
353                                 goto Exit;
354                         }
355                         OSM_LOG(sm->p_log, OSM_LOG_DEBUG,
356                                 "Received SLID=0 Trap. Using local LID:%u instead\n",
357                                 cl_ntoh16(sm->p_subn->sm_base_lid));
358                         tmp_madw.mad_addr.addr_type.smi.source_lid =
359                             sm->p_subn->sm_base_lid;
360                 }
361
362                 source_lid = tmp_madw.mad_addr.addr_type.smi.source_lid;
363
364                 /* Print some info about the incoming Trap */
365                 if (ib_notice_is_generic(p_ntci)) {
366                         if ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129))
367                             || (p_ntci->g_or_v.generic.trap_num ==
368                                 CL_HTON16(130))
369                             || (p_ntci->g_or_v.generic.trap_num ==
370                                 CL_HTON16(131)))
371                                 OSM_LOG(sm->p_log, OSM_LOG_ERROR,
372                                         "Received Generic Notice type:%u "
373                                         "num:%u (%s) Producer:%u (%s) "
374                                         "from LID:%u Port %d TID:0x%016"
375                                         PRIx64 "\n", ib_notice_get_type(p_ntci),
376                                         cl_ntoh16(p_ntci->g_or_v.generic.
377                                                   trap_num),
378                                         ib_get_trap_str(p_ntci->g_or_v.generic.
379                                                         trap_num),
380                                         cl_ntoh32(ib_notice_get_prod_type
381                                                   (p_ntci)),
382                                         ib_get_producer_type_str
383                                         (ib_notice_get_prod_type(p_ntci)),
384                                         cl_hton16(source_lid),
385                                         p_ntci->data_details.ntc_129_131.
386                                         port_num, cl_ntoh64(p_smp->trans_id));
387                         else
388                                 OSM_LOG(sm->p_log, OSM_LOG_ERROR,
389                                         "Received Generic Notice type:%u "
390                                         "num:%u (%s) Producer:%u (%s) "
391                                         "from LID:%u TID:0x%016" PRIx64
392                                         "\n", ib_notice_get_type(p_ntci),
393                                         cl_ntoh16(p_ntci->g_or_v.generic.
394                                                   trap_num),
395                                         ib_get_trap_str(p_ntci->g_or_v.generic.
396                                                         trap_num),
397                                         cl_ntoh32(ib_notice_get_prod_type
398                                                   (p_ntci)),
399                                         ib_get_producer_type_str
400                                         (ib_notice_get_prod_type(p_ntci)),
401                                         cl_hton16(source_lid),
402                                         cl_ntoh64(p_smp->trans_id));
403                 } else
404                         OSM_LOG(sm->p_log, OSM_LOG_ERROR,
405                                 "Received Vendor Notice type:%u vend:0x%06X "
406                                 "dev:%u from LID:%u TID:0x%016" PRIx64 "\n",
407                                 ib_notice_get_type(p_ntci),
408                                 cl_ntoh32(ib_notice_get_vend_id(p_ntci)),
409                                 cl_ntoh16(p_ntci->g_or_v.vend.dev_id),
410                                 cl_ntoh16(source_lid),
411                                 cl_ntoh64(p_smp->trans_id));
412         }
413
414         osm_dump_notice(sm->p_log, p_ntci, OSM_LOG_VERBOSE);
415
416         p_physp = osm_get_physp_by_mad_addr(sm->p_log,
417                                             sm->p_subn, &tmp_madw.mad_addr);
418         if (p_physp)
419                 p_smp->m_key = p_physp->port_info.m_key;
420         else
421                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3809: "
422                         "Failed to find source physical port for trap\n");
423
424         status = osm_resp_send(sm, &tmp_madw, 0, payload);
425         if (status != IB_SUCCESS) {
426                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3802: "
427                         "Error sending response (%s)\n",
428                         ib_get_err_str(status));
429                 goto Exit;
430         }
431
432         /*
433          * We would like to filter out recurring Traps so we track them by
434          * their source lid and content. If the same trap was already
435          * received within the aging time window more than 10 times,
436          * we simply ignore it. This is done only if we are in smi mode
437          */
438
439         if (is_gsi == FALSE) {
440                 if (ib_notice_is_generic(p_ntci) &&
441                     ((p_ntci->g_or_v.generic.trap_num == CL_HTON16(129)) ||
442                      (p_ntci->g_or_v.generic.trap_num == CL_HTON16(130)) ||
443                      (p_ntci->g_or_v.generic.trap_num == CL_HTON16(131)))) {
444                         /* If this is a trap 129, 130, or 131 - then this is a
445                          * trap signaling a change on a physical port.
446                          * Mark the physp_change_trap flag as TRUE.
447                          */
448                         physp_change_trap = TRUE;
449                         /* The source_lid should be based on the source_lid from the trap */
450                         source_lid = p_ntci->data_details.ntc_129_131.lid;
451                 }
452
453                 /* If physp_change_trap is TRUE - the key will include the port number.
454                    If not - the port_number in the key will be zero. */
455                 if (physp_change_trap == TRUE) {
456                         port_num = p_ntci->data_details.ntc_129_131.port_num;
457                         __osm_trap_get_key(source_lid, port_num, p_ntci,
458                                            &trap_key);
459                 } else
460                         __osm_trap_get_key(source_lid, 0, p_ntci, &trap_key);
461
462                 /* try to find it in the aging tracker */
463                 num_received =
464                     cl_event_wheel_num_regs(&sm->trap_aging_tracker,
465                                             trap_key);
466
467                 /* Now we know how many times it provided this trap */
468                 if (num_received > 10) {
469                         if (__print_num_received(num_received))
470                                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3804: "
471                                         "Received trap %u times consecutively\n",
472                                         num_received);
473                         /*
474                          * If the trap provides info about a bad port
475                          * we mark it as unhealthy.
476                          */
477                         if (physp_change_trap == TRUE) {
478                                 /* get the port */
479                                 p_physp = get_physp_by_lid_and_num(sm,
480                                                                    cl_ntoh16
481                                                                    (p_ntci->
482                                                                     data_details.
483                                                                     ntc_129_131.
484                                                                     lid),
485                                                                    port_num);
486
487                                 if (!p_physp)
488                                         OSM_LOG(sm->p_log, OSM_LOG_ERROR,
489                                                 "ERR 3805: "
490                                                 "Failed to find physical port by lid:%u num:%u\n",
491                                                 cl_ntoh16(p_ntci->data_details.
492                                                           ntc_129_131.lid),
493                                                 p_ntci->data_details.
494                                                 ntc_129_131.port_num);
495                                 else {
496                                         /* When babbling port policy option is enabled and
497                                            Threshold for disabling a "babbling" port is exceeded */
498                                         if (sm->p_subn->opt.
499                                             babbling_port_policy
500                                             && num_received >= 250
501                                             && disable_port(sm, p_physp) == 0)
502                                                 goto Exit;
503
504                                         OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
505                                                 "Marking unhealthy physical port by lid:%u num:%u\n",
506                                                 cl_ntoh16(p_ntci->data_details.
507                                                           ntc_129_131.lid),
508                                                 p_ntci->data_details.
509                                                 ntc_129_131.port_num);
510                                         /* check if the current state of the p_physp is healthy. If
511                                            it is - then this is a first change of state. Run a heavy sweep.
512                                            if it is not - no need to mark it again - just restart the timer. */
513                                         if (osm_physp_is_healthy(p_physp)) {
514                                                 osm_physp_set_health(p_physp,
515                                                                      FALSE);
516                                                 /* Make sure we sweep again - force a heavy sweep. */
517                                                 /* The sweep should be done only after the re-registration, or
518                                                    else we'll be losing track of the timer. */
519                                                 run_heavy_sweep = TRUE;
520                                         }
521                                         /* If we are marking the port as unhealthy - we want to
522                                            keep this for a longer period of time than the
523                                            OSM_DEFAULT_TRAP_SUPRESSION_TIMEOUT. Use the
524                                            OSM_DEFAULT_UNHEALTHY_TIMEOUT */
525                                         event_wheel_timeout =
526                                             OSM_DEFAULT_UNHEALTHY_TIMEOUT;
527                                 }
528                         }
529                 }
530
531                 /* restart the aging anyway */
532                 /* If physp_change_trap is TRUE - then use a callback to unset the
533                    healthy bit. If not - no need to use a callback. */
534                 if (physp_change_trap == TRUE)
535                         cl_event_wheel_reg(&sm->trap_aging_tracker, trap_key, cl_get_time_stamp() + event_wheel_timeout, osm_trap_rcv_aging_tracker_callback,   /* no callback */
536                                            sm   /* no context */ );
537                 else
538                         cl_event_wheel_reg(&sm->trap_aging_tracker, trap_key, cl_get_time_stamp() + event_wheel_timeout, NULL,  /* no callback */
539                                            NULL /* no context */ );
540
541                 /* If was already registered do nothing more */
542                 if (num_received > 10 && run_heavy_sweep == FALSE) {
543                         if (__print_num_received(num_received))
544                                 OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
545                                         "Continuously received this trap %u times. Ignoring\n",
546                                         num_received);
547                         goto Exit;
548                 }
549         }
550
551         /* Check for node description update. IB Spec v1.2.1 pg 823 */
552         if ((p_ntci->data_details.ntc_144.local_changes & TRAP_144_MASK_OTHER_LOCAL_CHANGES) &&
553                 (p_ntci->data_details.ntc_144.change_flgs & TRAP_144_MASK_NODE_DESCRIPTION_CHANGE)
554                 ) {
555                 OSM_LOG(sm->p_log, OSM_LOG_INFO, "Trap 144 Node description update\n");
556
557                 if (p_physp) {
558                         CL_PLOCK_ACQUIRE(sm->p_lock);
559                         osm_req_get_node_desc(sm, p_physp);
560                         CL_PLOCK_RELEASE(sm->p_lock);
561                 } else {
562                         OSM_LOG(sm->p_log, OSM_LOG_ERROR,
563                                 "ERR 3812: No physical port found for "
564                                 "trap 144: \"node description update\"\n");
565                 }
566         }
567
568         /* do a sweep if we received a trap */
569         if (sm->p_subn->opt.sweep_on_trap) {
570                 /* if this is trap number 128 or run_heavy_sweep is TRUE - update the
571                    force_single_heavy_sweep flag of the subnet.
572                    Sweep also on traps 144/145 - these traps signal a change of a certain
573                    port capability/system image guid.
574                    TODO: In the future we can change this to just getting PortInfo on
575                    this port instead of sweeping the entire subnet. */
576                 if (ib_notice_is_generic(p_ntci) &&
577                     ((cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 128) ||
578                      (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 144) ||
579                      (cl_ntoh16(p_ntci->g_or_v.generic.trap_num) == 145) ||
580                      run_heavy_sweep)) {
581                         OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
582                                 "Forcing heavy sweep. Received trap:%u\n",
583                                 cl_ntoh16(p_ntci->g_or_v.generic.trap_num));
584
585                         sm->p_subn->force_heavy_sweep = TRUE;
586                 }
587                 osm_sm_signal(sm, OSM_SIGNAL_SWEEP);
588         }
589
590         /* If we reached here due to trap 129/130/131 - do not need to do
591            the notice report. Just goto exit. We know this is the case
592            if physp_change_trap is TRUE. */
593         if (physp_change_trap == TRUE)
594                 goto Exit;
595
596         /* Add a call to osm_report_notice */
597         /* We are going to report the notice - so need to fix the IssuerGID
598            accordingly. See IBA 1.2 p.739 or IBA 1.1 p.653 for details. */
599         if (is_gsi) {
600                 if (!tmp_madw.mad_addr.addr_type.gsi.global_route) {
601                         OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3806: "
602                                 "Received gsi trap with global_route FALSE. "
603                                 "Cannot update issuer_gid!\n");
604                         goto Exit;
605                 }
606                 memcpy(&(p_ntci->issuer_gid),
607                        &(tmp_madw.mad_addr.addr_type.gsi.grh_info.src_gid),
608                        sizeof(ib_gid_t));
609         } else {
610                 /* Need to use the IssuerLID */
611                 p_tbl = &sm->p_subn->port_lid_tbl;
612
613                 CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
614
615                 if ((uint16_t) cl_ptr_vector_get_size(p_tbl) <=
616                     cl_ntoh16(source_lid)) {
617                         /*  the source lid is out of range */
618                         OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
619                                 "source lid is out of range:%u\n",
620                                 cl_ntoh16(source_lid));
621
622                         goto Exit;
623                 }
624                 p_port = cl_ptr_vector_get(p_tbl, cl_ntoh16(source_lid));
625                 if (p_port == 0) {
626                         /* We have the lid - but no corresponding port */
627                         OSM_LOG(sm->p_log, OSM_LOG_VERBOSE,
628                                 "Cannot find port corresponding to lid:%u\n",
629                                 cl_ntoh16(source_lid));
630
631                         goto Exit;
632                 }
633
634                 p_ntci->issuer_gid.unicast.prefix =
635                     sm->p_subn->opt.subnet_prefix;
636                 p_ntci->issuer_gid.unicast.interface_id = p_port->guid;
637         }
638
639         /* we need a lock here as the InformInfo DB must be stable */
640         CL_PLOCK_ACQUIRE(sm->p_lock);
641         status = osm_report_notice(sm->p_log, sm->p_subn, p_ntci);
642         CL_PLOCK_RELEASE(sm->p_lock);
643         if (status != IB_SUCCESS) {
644                 OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3803: "
645                         "Error sending trap reports (%s)\n",
646                         ib_get_err_str(status));
647                 goto Exit;
648         }
649
650 Exit:
651         OSM_LOG_EXIT(sm->p_log);
652 }
653
654 #if 0
655 /**********************************************************************
656  CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IS AN ERROR
657 **********************************************************************/
658 static void
659 __osm_trap_rcv_process_sm(IN osm_sm_t * sm,
660                           IN const osm_remote_sm_t * const p_sm)
661 {
662         /* const ib_sm_info_t*        p_smi; */
663
664         OSM_LOG_ENTER(sm->p_log);
665
666         OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3807: "
667                 "This function is not supported yet\n");
668
669         OSM_LOG_EXIT(sm->p_log);
670 }
671 #endif
672
673 /**********************************************************************
674  CURRENTLY WE ARE NOT CREATING TRAPS - SO THIS CALL IN AN ERROR
675 **********************************************************************/
676 static void
677 __osm_trap_rcv_process_response(IN osm_sm_t * sm,
678                                 IN const osm_madw_t * const p_madw)
679 {
680
681         OSM_LOG_ENTER(sm->p_log);
682
683         OSM_LOG(sm->p_log, OSM_LOG_ERROR, "ERR 3808: "
684                 "This function is not supported yet\n");
685
686         OSM_LOG_EXIT(sm->p_log);
687 }
688
689 /**********************************************************************
690  **********************************************************************/
691 void osm_trap_rcv_process(IN void *context, IN void *data)
692 {
693         osm_sm_t *sm = context;
694         osm_madw_t *p_madw = data;
695         ib_smp_t *p_smp;
696
697         OSM_LOG_ENTER(sm->p_log);
698
699         CL_ASSERT(p_madw);
700
701         p_smp = osm_madw_get_smp_ptr(p_madw);
702
703         /*
704            Determine if this is a request for our own Trap
705            or if this is a response to our request for another
706            SM's Trap.
707          */
708         if (ib_smp_is_response(p_smp))
709                 __osm_trap_rcv_process_response(sm, p_madw);
710         else
711                 __osm_trap_rcv_process_request(sm, p_madw);
712
713         OSM_LOG_EXIT(sm->p_log);
714 }