5ac945df1a0c47c12393bf3a9b940f9c2b5b696c
[mirror/winof/.git] / ulp / opensm / user / opensm / osm_sw_info_rcv.c
1 /*
2  * Copyright (c) 2004, 2005 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 the OpenIB.org BSD license
7  * below:
8  *
9  *     Redistribution and use in source and binary forms, with or
10  *     without modification, are permitted provided that the following
11  *     conditions are met:
12  *
13  *      - Redistributions of source code must retain the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer.
16  *
17  *      - Redistributions in binary form must reproduce the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  *
31  * $Id$
32  */
33
34
35 /*
36  * Abstract:
37  *    Implementation of osm_si_rcv_t.
38  * This object represents the SwitchInfo Receiver object.
39  * This object is part of the opensm family of objects.
40  *
41  * Environment:
42  *    Linux User Mode
43  *
44  * $Revision: 1.6 $
45  */
46
47 #if HAVE_CONFIG_H
48 #  include <config.h>
49 #endif /* HAVE_CONFIG_H */
50
51 #include <iba/ib_types.h>
52 #include <complib/cl_memory.h>
53 #include <complib/cl_qmap.h>
54 #include <complib/cl_passivelock.h>
55 #include <complib/cl_debug.h>
56 #include <opensm/osm_sw_info_rcv.h>
57 #include <opensm/osm_log.h>
58 #include <opensm/osm_switch.h>
59 #include <opensm/osm_subnet.h>
60 #include <opensm/osm_helper.h>
61
62 /**********************************************************************
63  **********************************************************************/
64 void
65 __osm_si_rcv_clear_sc_bit(
66   IN const osm_si_rcv_t* const p_rcv,
67   IN osm_node_t* const p_node,
68   IN ib_switch_info_t* const p_si )
69 {
70   uint8_t payload[IB_SMP_DATA_SIZE];
71   ib_api_status_t status;
72   osm_madw_context_t context;
73   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_clear_sc_bit );
74
75   context.si_context.node_guid = osm_node_get_node_guid( p_node );
76   context.si_context.set_method = TRUE;
77   context.si_context.light_sweep = FALSE;
78
79   cl_memcpy( payload, p_si, IB_SMP_DATA_SIZE );
80
81   status = osm_req_set( p_rcv->p_req,
82                         osm_node_get_any_dr_path_ptr( p_node ),
83                         payload,
84                         IB_MAD_ATTR_SWITCH_INFO,
85                         0,
86                         CL_DISP_MSGID_NONE,
87                         &context );
88
89   if( status != IB_SUCCESS )
90   {
91     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
92              "__osm_si_rcv_clear_sc_bit: ERR 3601: "
93              "Unable to clear state change bit for switch "
94              "with GUID = 0x%" PRIx64 ".\n",
95              cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
96   }
97
98   OSM_LOG_EXIT( p_rcv->p_log );
99 }
100
101 /**********************************************************************
102  The plock must be held before calling this function.
103 **********************************************************************/
104 void
105 __osm_si_rcv_get_port_info(
106   IN const osm_si_rcv_t* const p_rcv,
107   IN osm_switch_t* const p_sw,
108   IN const osm_madw_t* const p_madw )
109 {
110   osm_madw_context_t context;
111   uint8_t port_num;
112   osm_physp_t *p_physp;
113   osm_node_t *p_node;
114   uint8_t num_ports;
115   osm_dr_path_t dr_path;
116   const ib_smp_t* p_smp;
117   ib_api_status_t status = IB_SUCCESS;
118
119   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_port_info );
120
121   CL_ASSERT( p_sw );
122
123   p_node = osm_switch_get_node_ptr( p_sw );
124   p_smp = osm_madw_get_smp_ptr( p_madw );
125
126   CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
127
128   /*
129     Request PortInfo attribute for each port on the switch.
130     Don't trust the port's own DR Path, since it may no longer
131     be a legitimate path through the subnet.
132     Build a path from the mad instead, since we know that path works.
133     The port's DR Path info gets updated when the PortInfo
134     attribute is received.
135   */
136   p_physp = osm_node_get_any_physp_ptr( p_node );
137
138   CL_ASSERT( osm_physp_is_valid( p_physp ) );
139
140   context.pi_context.node_guid = osm_node_get_node_guid( p_node );
141   context.pi_context.port_guid = osm_physp_get_port_guid( p_physp );
142   context.pi_context.set_method = FALSE;
143   context.pi_context.update_master_sm_base_lid = FALSE;
144   context.pi_context.ignore_errors = FALSE;
145   context.pi_context.light_sweep = FALSE;
146
147   num_ports = osm_node_get_num_physp( p_node );
148   osm_dr_path_init( &dr_path,
149                     osm_madw_get_bind_handle( p_madw ),
150                     p_smp->hop_count, p_smp->initial_path );
151
152   for( port_num = 0; port_num < num_ports; port_num++)
153   {
154     status = osm_req_get(
155       p_rcv->p_req,
156       &dr_path,
157       IB_MAD_ATTR_PORT_INFO,
158       cl_hton32( port_num ),
159       CL_DISP_MSGID_NONE,
160       &context );
161     if( status != IB_SUCCESS )
162     {
163       /* continue the loop despite the error */
164       osm_log( p_rcv->p_log, OSM_LOG_ERROR,
165                "__osm_si_rcv_get_port_info: ERR 3602: "
166                "Failure initiating PortInfo request (%s).\n",
167                ib_get_err_str(status));
168     }
169   }
170
171   OSM_LOG_EXIT( p_rcv->p_log );
172 }
173
174 /**********************************************************************
175  The plock must be held before calling this function.
176 **********************************************************************/
177 void
178 __osm_si_rcv_get_fwd_tbl(
179   IN const osm_si_rcv_t* const p_rcv,
180   IN osm_switch_t* const p_sw )
181 {
182   osm_madw_context_t context;
183   osm_dr_path_t *p_dr_path;
184   osm_physp_t *p_physp;
185   osm_node_t *p_node;
186   uint32_t block_id_ho;
187   uint32_t max_block_id_ho;
188   ib_api_status_t status = IB_SUCCESS;
189
190   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_fwd_tbl );
191
192   CL_ASSERT( p_sw );
193
194   p_node = osm_switch_get_node_ptr( p_sw );
195
196   CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
197
198   p_physp = osm_node_get_any_physp_ptr( p_node );
199
200   CL_ASSERT( osm_physp_is_valid( p_physp ) );
201
202   context.lft_context.node_guid = osm_node_get_node_guid( p_node );
203   context.lft_context.set_method = FALSE;
204
205   max_block_id_ho = osm_switch_get_max_block_id_in_use( p_sw );
206
207   p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
208
209   for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
210   {
211     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
212     {
213       osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
214                "__osm_si_rcv_get_fwd_tbl: "
215                "Retrieving FT block %u.\n", block_id_ho );
216     }
217
218     status = osm_req_get(
219       p_rcv->p_req,
220       p_dr_path,
221       IB_MAD_ATTR_LIN_FWD_TBL,
222       cl_hton32( block_id_ho ),
223       CL_DISP_MSGID_NONE,
224       &context );
225     if( status != IB_SUCCESS )
226     {
227       /* continue the loop despite the error */
228       osm_log( p_rcv->p_log, OSM_LOG_ERROR,
229                "__osm_si_rcv_get_fwd_tbl: ERR 3603: "
230                "Failure initiating PortInfo request (%s).\n",
231                ib_get_err_str(status));
232     }
233   }
234
235   OSM_LOG_EXIT( p_rcv->p_log );
236 }
237
238 /**********************************************************************
239  The plock must be held before calling this function.
240 **********************************************************************/
241 void
242 __osm_si_rcv_get_mcast_fwd_tbl(
243   IN const osm_si_rcv_t* const p_rcv,
244   IN osm_switch_t* const p_sw )
245 {
246   osm_madw_context_t context;
247   osm_dr_path_t *p_dr_path;
248   osm_physp_t *p_physp;
249   osm_node_t *p_node;
250   osm_mcast_tbl_t* p_tbl;
251   uint32_t block_id_ho;
252   uint32_t max_block_id_ho;
253   uint32_t position;
254   uint32_t max_position;
255   uint32_t attr_mod_ho;
256   ib_api_status_t status = IB_SUCCESS;
257
258   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_get_mcast_fwd_tbl );
259
260   CL_ASSERT( p_sw );
261
262   p_node = osm_switch_get_node_ptr( p_sw );
263
264   CL_ASSERT( osm_node_get_type( p_node ) == IB_NODE_TYPE_SWITCH );
265
266   if( osm_switch_get_mcast_fwd_tbl_size( p_sw ) == 0 )
267   {
268     osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
269              "__osm_si_rcv_get_mcast_fwd_tbl: "
270              "Multicast not supported by switch 0x%016" PRIx64 ".\n",
271              cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
272     goto Exit;
273   }
274
275   p_physp = osm_node_get_any_physp_ptr( p_node );
276   p_tbl = osm_switch_get_mcast_tbl_ptr( p_sw );
277
278   CL_ASSERT( osm_physp_is_valid( p_physp ) );
279
280   context.mft_context.node_guid = osm_node_get_node_guid( p_node );
281   context.mft_context.set_method = FALSE;
282
283   max_block_id_ho = osm_mcast_tbl_get_max_block( p_tbl );
284
285   if( max_block_id_ho > IB_MCAST_MAX_BLOCK_ID )
286   {
287     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
288              "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3609: "
289              "Out-of-range mcast block size = %u on switch 0x%016" PRIx64
290              ".\n", max_block_id_ho,
291              cl_ntoh64( osm_node_get_node_guid( p_node ) ) );
292     goto Exit;
293   }
294
295   max_position = osm_mcast_tbl_get_max_position( p_tbl );
296
297   CL_ASSERT( max_position <= IB_MCAST_POSITION_MAX );
298
299   osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
300            "__osm_si_rcv_get_mcast_fwd_tbl: "
301            "Max MFT block = %u, Max position = %u.\n", max_block_id_ho,
302            max_position );
303
304   p_dr_path = osm_physp_get_dr_path_ptr( p_physp );
305
306   for( block_id_ho = 0; block_id_ho <= max_block_id_ho; block_id_ho++)
307   {
308     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
309     {
310       osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
311                "__osm_si_rcv_get_mcast_fwd_tbl: "
312                "Retrieving MFT block %u.\n", block_id_ho );
313     }
314
315     for( position = 0; position <= max_position; position++ )
316     {
317       if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
318       {
319         osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
320                  "__osm_si_rcv_get_mcast_fwd_tbl: "
321                  "Retrieving MFT position %u.\n", position );
322       }
323
324       attr_mod_ho = block_id_ho | position << IB_MCAST_POSITION_SHIFT;
325       status = osm_req_get(
326         p_rcv->p_req,
327         p_dr_path,
328         IB_MAD_ATTR_MCAST_FWD_TBL,
329         cl_hton32( attr_mod_ho ),
330         CL_DISP_MSGID_NONE,
331         &context );
332       if( status != IB_SUCCESS )
333       {
334         /* continue the loop despite the error */
335         osm_log( p_rcv->p_log, OSM_LOG_ERROR,
336                  "__osm_si_rcv_get_mcast_fwd_tbl: ERR 3607: "
337                  "Failure initiating PortInfo request (%s).\n",
338                  ib_get_err_str(status));
339       }
340     }
341   }
342
343  Exit:
344   OSM_LOG_EXIT( p_rcv->p_log );
345 }
346
347 /**********************************************************************
348    Lock must be held on entry to this function.
349 **********************************************************************/
350 void
351 __osm_si_rcv_process_new(
352   IN const osm_si_rcv_t* const p_rcv,
353   IN osm_node_t* const p_node,
354   IN const osm_madw_t* const p_madw )
355 {
356   osm_switch_t *p_sw;
357   osm_switch_t *p_check;
358   ib_switch_info_t *p_si;
359   ib_smp_t *p_smp;
360   cl_qmap_t *p_sw_guid_tbl;
361
362   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_new );
363
364   CL_ASSERT( p_rcv );
365   CL_ASSERT( p_madw );
366
367   p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
368
369   p_smp = osm_madw_get_smp_ptr( p_madw );
370   p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
371
372   osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
373
374   /*
375     Allocate a new switch object for this switch,
376     and place it in the switch table.
377   */
378   p_sw = osm_switch_new( p_node, p_madw );
379   if( p_sw == NULL )
380   {
381     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
382              "__osm_si_rcv_process_new: ERR 3608: "
383              "Unable to allocate new switch object.\n" );
384     goto Exit;
385   }
386
387   /* set subnet max mlid to the minimum MulticastFDBCap of all switches */
388   if ( p_sw->mcast_tbl.max_mlid_ho < p_rcv->p_subn->max_multicast_lid_ho )
389   {
390     p_rcv->p_subn->max_multicast_lid_ho = p_sw->mcast_tbl.max_mlid_ho;
391     osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
392              "__osm_si_rcv_process_new: "
393              "Subnet max multicast lid is 0x%X\n",
394              p_rcv->p_subn->max_multicast_lid_ho );
395   }
396
397   /* set subnet max unicast lid to the minimum LinearFDBCap of all switches */
398   if ( p_sw->fwd_tbl.p_lin_tbl->size < p_rcv->p_subn->max_unicast_lid_ho )
399   {
400     p_rcv->p_subn->max_unicast_lid_ho = p_sw->fwd_tbl.p_lin_tbl->size;
401     osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
402              "__osm_si_rcv_process_new: "
403              "Subnet max unicast lid is 0x%X\n",
404              p_rcv->p_subn->max_unicast_lid_ho );
405   }
406
407   p_check = (osm_switch_t*)cl_qmap_insert( p_sw_guid_tbl,
408                                            osm_node_get_node_guid( p_node ), &p_sw->map_item );
409
410   if( p_check != p_sw )
411   {
412     /*
413       This shouldn't happen since we hold the lock!
414     */
415     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
416              "__osm_si_rcv_process_new: ERR 3605: "
417              "Unable to add new switch object to database.\n" );
418     osm_switch_delete( &p_sw );
419     goto Exit;
420   }
421
422   /*
423     Update the switch info according to the
424     info we just received.
425   */
426   osm_switch_set_switch_info( p_sw, p_si );
427   osm_switch_discovery_count_inc( p_sw );
428
429   /*
430     Get the PortInfo attribute for every port.
431   */
432   __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
433   __osm_si_rcv_get_fwd_tbl( p_rcv, p_sw );
434
435   /*
436     Don't bother retrieving the current multicast tables
437     from the switches.  The current version of SM does
438     not support silent take-over of an existing multicast
439     configuration.
440
441     Gathering the multicast tables can also generate large amounts
442     of extra subnet-init traffic.
443
444     The code to retrieve the tables was fully debugged.
445   */
446 #if 0
447   if( !p_rcv->p_subn->opt.disable_multicast )
448     __osm_si_rcv_get_mcast_fwd_tbl( p_rcv, p_sw );
449 #endif
450
451  Exit:
452   OSM_LOG_EXIT( p_rcv->p_log );
453 }
454
455 /**********************************************************************
456    Lock must be held on entry to this function.
457    Return 1 if the caller is expected to send a change_detected event.
458    this can not be done internally as the event needs the lock...
459 **********************************************************************/
460 boolean_t
461 __osm_si_rcv_process_existing(
462   IN const osm_si_rcv_t* const p_rcv,
463   IN osm_node_t* const p_node,
464   IN osm_switch_t* const p_sw,
465   IN const osm_madw_t* const p_madw )
466 {
467   ib_switch_info_t *p_si;
468   osm_si_context_t *p_si_context;
469   ib_smp_t         *p_smp;
470   boolean_t         is_change_detected = FALSE;
471
472   OSM_LOG_ENTER( p_rcv->p_log, __osm_si_rcv_process_existing );
473
474   CL_ASSERT( p_node );
475   CL_ASSERT( p_sw );
476   CL_ASSERT( p_madw );
477
478   p_smp = osm_madw_get_smp_ptr( p_madw );
479   p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
480   p_si_context = osm_madw_get_si_context_ptr( p_madw );
481
482   if( p_si_context->set_method )
483   {
484     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
485     {
486       osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
487                "__osm_si_rcv_process_existing: "
488                "Received logical SetResp().\n" );
489     }
490
491     osm_switch_set_switch_info( p_sw, p_si );
492   }
493   else
494   {
495     if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
496     {
497       osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
498                "__osm_si_rcv_process_existing: "
499                "Received logical GetResp().\n" );
500     }
501
502     osm_switch_set_switch_info( p_sw, p_si );
503
504     /*
505       Check the port state change bit.  If true, then this switch
506       has seen a port state transition, so continue probing.
507     */
508     if( p_si_context->light_sweep == TRUE )
509     {
510       /* This is a light sweep */
511       /* If the mad was returned with an error -
512          signal a change to the state manager. */
513       if ( ib_smp_get_status( p_smp ) != 0 )
514       {
515         osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
516                  "__osm_si_rcv_process_existing: "
517                  "GetResp() received with error in light sweep. "
518                  "Commencing heavy sweep.\n" );
519           is_change_detected = TRUE;
520       }
521       else
522       {
523         /*
524           If something changed, then just signal the state
525           manager.  Don't attempt to probe further during
526           a light sweep.
527         */
528         if( ib_switch_info_get_state_change( p_si ) )
529         {
530           osm_dump_switch_info( p_rcv->p_log, p_si, OSM_LOG_DEBUG );
531           is_change_detected = TRUE;
532         }
533       }
534     }
535     else
536     {
537       /*
538         This is a heavy sweep.  Get information regardless
539         of the state change bit.
540       */
541       osm_switch_discovery_count_inc( p_sw );
542       osm_log( p_rcv->p_log, OSM_LOG_VERBOSE,
543                "__osm_si_rcv_process_existing: "
544                "discovery_count is:%u \n",
545                osm_switch_discovery_count_get( p_sw ) );
546
547       /* If this is the first discovery - then get the port_info */
548       if ( osm_switch_discovery_count_get( p_sw ) == 1 )
549         __osm_si_rcv_get_port_info( p_rcv, p_sw, p_madw );
550       else
551       {
552         osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
553                  "__osm_si_rcv_process_existing: "
554                  "Not discovering again through switch:0x%"
555                  PRIx64 ".\n",
556                  osm_node_get_node_guid( p_sw->p_node) );
557       }
558     }
559   }
560
561   OSM_LOG_EXIT( p_rcv->p_log );
562   return is_change_detected;
563 }
564
565 /**********************************************************************
566  **********************************************************************/
567 void
568 osm_si_rcv_construct(
569   IN osm_si_rcv_t* const p_rcv )
570 {
571   cl_memclr( p_rcv, sizeof(*p_rcv) );
572 }
573
574 /**********************************************************************
575  **********************************************************************/
576 void
577 osm_si_rcv_destroy(
578   IN osm_si_rcv_t* const p_rcv )
579 {
580   OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_destroy );
581
582   CL_ASSERT( p_rcv );
583   OSM_LOG_EXIT( p_rcv->p_log );
584 }
585
586
587 /**********************************************************************
588  **********************************************************************/
589 ib_api_status_t
590 osm_si_rcv_init(
591   IN osm_si_rcv_t* const p_rcv,
592   IN osm_subn_t* const p_subn,
593   IN osm_log_t* const p_log,
594   IN osm_req_t* const p_req,
595   IN osm_state_mgr_t* const p_state_mgr,
596   IN cl_plock_t* const p_lock )
597 {
598   ib_api_status_t status = IB_SUCCESS;
599   OSM_LOG_ENTER( p_log, osm_si_rcv_init );
600
601   osm_si_rcv_construct( p_rcv );
602
603   p_rcv->p_log = p_log;
604   p_rcv->p_subn = p_subn;
605   p_rcv->p_lock = p_lock;
606   p_rcv->p_req = p_req;
607   p_rcv->p_state_mgr = p_state_mgr;
608
609   OSM_LOG_EXIT( p_rcv->p_log );
610   return( status );
611 }
612
613
614 /**********************************************************************
615  **********************************************************************/
616 void
617 osm_si_rcv_process(
618   IN const osm_si_rcv_t* const p_rcv,
619   IN osm_madw_t* const p_madw )
620 {
621   cl_qmap_t *p_node_guid_tbl;
622   cl_qmap_t *p_sw_guid_tbl;
623   ib_switch_info_t *p_si;
624   ib_smp_t *p_smp;
625   osm_node_t *p_node;
626   osm_switch_t *p_sw;
627   ib_net64_t node_guid;
628   osm_si_context_t *p_context;
629
630   OSM_LOG_ENTER( p_rcv->p_log, osm_si_rcv_process );
631
632   CL_ASSERT( p_rcv );
633   CL_ASSERT( p_madw );
634
635   p_node_guid_tbl = &p_rcv->p_subn->node_guid_tbl;
636   p_sw_guid_tbl = &p_rcv->p_subn->sw_guid_tbl;
637   p_smp = osm_madw_get_smp_ptr( p_madw );
638   p_si = (ib_switch_info_t*)ib_smp_get_payload_ptr( p_smp );
639
640   /*
641     Acquire the switch object and add the switch info.
642   */
643
644   p_context = osm_madw_get_si_context_ptr( p_madw );
645
646   node_guid = p_context->node_guid;
647
648   if( osm_log_is_active( p_rcv->p_log, OSM_LOG_DEBUG ) )
649   {
650     osm_log( p_rcv->p_log, OSM_LOG_DEBUG,
651              "osm_si_rcv_process: "
652              "Switch GUID = 0x%016" PRIx64
653              ", TID = 0x%" PRIx64 ".\n",
654              cl_ntoh64( node_guid ),
655              cl_ntoh64( p_smp->trans_id ) );
656   }
657
658   CL_PLOCK_EXCL_ACQUIRE( p_rcv->p_lock );
659
660   p_node = (osm_node_t*)cl_qmap_get( p_node_guid_tbl, node_guid );
661   if( p_node == (osm_node_t*)cl_qmap_end( p_node_guid_tbl ) )
662   {
663     osm_log( p_rcv->p_log, OSM_LOG_ERROR,
664              "osm_si_rcv_process: ERR 3606: "
665              "SwitchInfo received for nonexistent node "
666              "with GUID = 0x%" PRIx64 ".\n",
667              cl_ntoh64( node_guid ) );
668   }
669   else
670   {
671
672     /*
673       Hack for bad value in Mellanox switch
674     */
675     if( cl_ntoh16( p_si->lin_top ) > IB_LID_UCAST_END_HO )
676     {
677       osm_log( p_rcv->p_log, OSM_LOG_ERROR,
678                "osm_si_rcv_process: ERR 3610: "
679                "\n\t\t\t\tBad LinearFDBTop value = 0x%X "
680                "on switch 0x%" PRIx64 "."
681                "\n\t\t\t\tForcing correction to 0x%X.\n",
682                cl_ntoh16( p_si->lin_top ),
683                cl_ntoh64( osm_node_get_node_guid( p_node ) ),
684                0 );
685
686       p_si->lin_top = 0;
687     }
688
689     /*
690       Acquire the switch object for this switch.
691     */
692     p_sw = (osm_switch_t*)cl_qmap_get( p_sw_guid_tbl,
693                                        node_guid );
694     if( p_sw == (osm_switch_t*)cl_qmap_end( p_sw_guid_tbl ) )
695     {
696       __osm_si_rcv_process_new( p_rcv, p_node, p_madw );
697       /*
698          A new switch was found during the sweep so we need
699          to ignore the current LFT settings.
700       */
701       p_rcv->p_subn->ignore_existing_lfts = TRUE;
702     }
703     else
704     {
705       /* we might get back a request for signaling change was detected */
706       if (__osm_si_rcv_process_existing( p_rcv, p_node, p_sw, p_madw ))
707       {
708         CL_PLOCK_RELEASE( p_rcv->p_lock );
709         osm_state_mgr_process( p_rcv->p_state_mgr,
710                                OSM_SIGNAL_CHANGE_DETECTED );
711         goto Exit;
712       }
713     }
714   }
715
716   CL_PLOCK_RELEASE( p_rcv->p_lock );
717  Exit:
718   OSM_LOG_EXIT( p_rcv->p_log );
719 }