9ab35f79f702be0736a76017066ede0a840d2b5e
[mirror/winof/.git] / ulp / opensm / user / opensm / osm_subnet.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_subn_t.
38  * This object represents an IBA subnet.
39  * This object is part of the opensm family of objects.
40  *
41  * Environment:
42  *    Linux User Mode
43  *
44  * $Revision: 1.9 $
45  */
46
47 #if HAVE_CONFIG_H
48 #  include <config.h>
49 #endif /* HAVE_CONFIG_H */
50
51 #include <opensm/osm_subnet.h>
52 #include <opensm/osm_log.h>
53 #include <opensm/osm_madw.h>
54 #include <opensm/osm_port.h>
55 #include <opensm/osm_switch.h>
56 #include <opensm/osm_remote_sm.h>
57 #include <opensm/osm_node.h>
58 #include <opensm/osm_multicast.h>
59 #include <opensm/osm_inform.h>
60 #include <stdlib.h>
61
62 /**********************************************************************
63  **********************************************************************/
64 void
65 osm_subn_construct(
66   IN osm_subn_t* const p_subn )
67 {
68   cl_memclr( p_subn, sizeof(*p_subn) );
69   cl_ptr_vector_construct( &p_subn->node_lid_tbl );
70   cl_ptr_vector_construct( &p_subn->port_lid_tbl );
71   cl_qmap_init( &p_subn->sw_guid_tbl );
72   cl_qmap_init( &p_subn->node_guid_tbl );
73   cl_qmap_init( &p_subn->port_guid_tbl );
74   cl_qmap_init( &p_subn->sm_guid_tbl );
75   cl_qlist_init( &p_subn->sa_sr_list );
76   cl_qlist_init( &p_subn->sa_infr_list );
77   cl_qmap_init( &p_subn->rtr_guid_tbl );
78   cl_qmap_init( &p_subn->prtn_pkey_tbl );
79   cl_qmap_init( &p_subn->mgrp_mlid_tbl );
80   cl_list_construct( &p_subn->new_ports_list );
81   cl_list_init( &p_subn->new_ports_list, 10 );
82   cl_list_construct( &p_subn->light_sweep_physp_list );
83   cl_list_init( &p_subn->light_sweep_physp_list, 5 );
84 }
85
86 /**********************************************************************
87  **********************************************************************/
88 void
89 osm_subn_destroy(
90   IN osm_subn_t* const p_subn )
91 {
92   osm_node_t      *p_node, *p_next_node;
93   osm_port_t      *p_port, *p_next_port;
94   osm_switch_t    *p_sw,   *p_next_sw;
95   osm_remote_sm_t *p_rsm,  *p_next_rsm;  
96   osm_mgrp_t      *p_mgrp, *p_next_mgrp;
97   osm_infr_t      *p_infr, *p_next_infr;
98
99   /* it might be a good idea to de-allocate all known objects */
100   p_next_node = (osm_node_t*)cl_qmap_head( &p_subn->node_guid_tbl );
101   while( p_next_node != (osm_node_t*)cl_qmap_end( &p_subn->node_guid_tbl ) )
102   {
103     p_node = p_next_node;
104     p_next_node = (osm_node_t*)cl_qmap_next( &p_node->map_item );
105     osm_node_delete( &p_node );
106   }
107
108   cl_ptr_vector_destroy( &p_subn->node_lid_tbl );
109
110   p_next_port = (osm_port_t*)cl_qmap_head( &p_subn->port_guid_tbl );
111   while( p_next_port != (osm_port_t*)cl_qmap_end( &p_subn->port_guid_tbl ) )
112   {
113     p_port = p_next_port;
114     p_next_port = (osm_port_t*)cl_qmap_next( &p_port->map_item );
115     osm_port_delete( &p_port );
116   }
117
118   p_next_sw = (osm_switch_t*)cl_qmap_head( &p_subn->sw_guid_tbl );
119   while( p_next_sw != (osm_switch_t*)cl_qmap_end( &p_subn->sw_guid_tbl ) )
120   {
121     p_sw = p_next_sw;
122     p_next_sw = (osm_switch_t*)cl_qmap_next( &p_sw->map_item );
123     osm_switch_delete( &p_sw );
124   }
125
126   p_next_rsm = (osm_remote_sm_t*)cl_qmap_head( &p_subn->sm_guid_tbl );
127   while( p_next_rsm != (osm_remote_sm_t*)cl_qmap_end( &p_subn->sm_guid_tbl ) )
128   {
129     p_rsm = p_next_rsm;
130     p_next_rsm = (osm_remote_sm_t*)cl_qmap_next( &p_rsm->map_item );
131     cl_free( p_rsm );
132   }
133
134   p_next_mgrp = (osm_mgrp_t*)cl_qmap_head( &p_subn->mgrp_mlid_tbl );
135   while( p_next_mgrp != (osm_mgrp_t*)cl_qmap_end( &p_subn->mgrp_mlid_tbl ) )
136   {
137     p_mgrp = p_next_mgrp;
138     p_next_mgrp = (osm_mgrp_t*)cl_qmap_next( &p_mgrp->map_item );
139     osm_mgrp_destroy( p_mgrp );
140   }
141
142   p_next_infr = (osm_infr_t*)cl_qlist_head( &p_subn->sa_infr_list );
143   while (p_next_infr != (osm_infr_t*)cl_qlist_end( &p_subn->sa_infr_list ) )
144   {
145     p_infr = p_next_infr;
146     p_next_infr = (osm_infr_t*)cl_qlist_next( &p_infr->list_item );
147     osm_infr_destroy( p_infr );
148   }
149
150   cl_list_remove_all( &p_subn->new_ports_list );
151   cl_list_destroy( &p_subn->new_ports_list );
152
153   cl_list_remove_all( &p_subn->light_sweep_physp_list );
154   cl_list_destroy( &p_subn->light_sweep_physp_list );
155
156   cl_ptr_vector_destroy( &p_subn->port_lid_tbl );
157   cl_map_remove_all(&(p_subn->opt.port_pro_ignore_guids));
158   cl_map_destroy(&(p_subn->opt.port_pro_ignore_guids));
159 }
160
161 /**********************************************************************
162  **********************************************************************/
163 ib_api_status_t
164 osm_subn_init(
165   IN osm_subn_t* const p_subn,
166   IN const osm_subn_opt_t* const p_opt )
167 {
168   cl_status_t status;
169
170   status = cl_ptr_vector_init( &p_subn->node_lid_tbl,
171                                OSM_SUBNET_VECTOR_MIN_SIZE,
172                                OSM_SUBNET_VECTOR_GROW_SIZE );
173   if( status != CL_SUCCESS )
174     return( status );
175
176   status = cl_ptr_vector_init( &p_subn->port_lid_tbl,
177                                OSM_SUBNET_VECTOR_MIN_SIZE,
178                                OSM_SUBNET_VECTOR_GROW_SIZE );
179   if( status != CL_SUCCESS )
180     return( status );
181
182   status = cl_ptr_vector_set_capacity( &p_subn->node_lid_tbl,
183                                        OSM_SUBNET_VECTOR_CAPACITY );
184   if( status != CL_SUCCESS )
185     return( status );
186
187   status = cl_ptr_vector_set_capacity( &p_subn->port_lid_tbl,
188                                        OSM_SUBNET_VECTOR_CAPACITY );
189   if( status != CL_SUCCESS )
190     return( status );
191
192   /*
193     LID zero is not valid.  NULL out this entry for the
194     convenience of other code.
195   */
196   cl_ptr_vector_set( &p_subn->node_lid_tbl, 0, NULL );
197   cl_ptr_vector_set( &p_subn->port_lid_tbl, 0, NULL );
198
199   p_subn->opt = *p_opt;
200   p_subn->max_unicast_lid_ho = IB_LID_UCAST_END_HO;
201   p_subn->max_multicast_lid_ho = IB_LID_MCAST_END_HO;
202   p_subn->min_ca_mtu = IB_MAX_MTU;
203   p_subn->min_ca_rate = IB_MAX_RATE;
204
205   /* note that insert and remove are part of the port_profile thing. */
206   cl_map_init(&(p_subn->opt.port_pro_ignore_guids), 10);
207
208   /* ignore_existing_lfts follows the reassign_lfts on first sweep */
209   p_subn->ignore_existing_lfts = p_subn->opt.reassign_lfts;
210
211   /* we assume master by default - so we only need to set it true if STANDBY */
212   p_subn->coming_out_of_standby = FALSE;
213
214   return( IB_SUCCESS );
215 }
216
217 /**********************************************************************
218  **********************************************************************/
219 ib_gid_t
220 osm_get_gid_by_mad_addr(
221   IN osm_log_t*            p_log,
222   IN const osm_subn_t     *p_subn,
223   IN const osm_mad_addr_t       *p_mad_addr )
224 {
225   const cl_ptr_vector_t*  p_tbl;
226   const osm_port_t*       p_port = NULL;
227   const osm_physp_t*      p_physp = NULL;
228   ib_gid_t                request_gid;
229
230   /* Find the port gid of the request in the subnet */
231   p_tbl = &p_subn->port_lid_tbl;
232
233   CL_ASSERT( cl_ptr_vector_get_size(p_tbl) < 0x10000 );
234
235   if ((uint16_t)cl_ptr_vector_get_size(p_tbl) > 
236       cl_ntoh16(p_mad_addr->dest_lid))
237   {
238     p_port = cl_ptr_vector_get( p_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
239     p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
240     request_gid.unicast.interface_id = p_physp->port_guid;
241     request_gid.unicast.prefix = p_subn->opt.subnet_prefix;
242   }
243   else
244   {
245     /* The dest_lid is not in the subnet table - this is an error */
246     osm_log( p_log, OSM_LOG_ERROR,
247              "osm_get_gid_by_mad_addr: ERR 7501 "
248              "Lid is out of range: 0x%X \n",
249              cl_ntoh16(p_mad_addr->dest_lid)
250              );
251   }
252
253   return request_gid;
254 }
255
256 /**********************************************************************
257  **********************************************************************/
258 osm_physp_t*
259 osm_get_physp_by_mad_addr(
260   IN osm_log_t*            p_log,
261   IN const osm_subn_t     *p_subn,
262   IN osm_mad_addr_t       *p_mad_addr )
263 {
264   const cl_ptr_vector_t*  p_port_lid_tbl;
265   osm_port_t*             p_port = NULL;
266   osm_physp_t*            p_physp = NULL;
267
268   /* Find the port gid of the request in the subnet */
269   p_port_lid_tbl = &p_subn->port_lid_tbl;
270
271   CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
272
273   if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) >
274       cl_ntoh16(p_mad_addr->dest_lid))
275   {
276     p_port = cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
277     if (p_port == NULL)
278     {
279       /* The port is not in the port_lid table - this is an error */
280       osm_log( p_log, OSM_LOG_ERROR,
281                "osm_get_physp_by_mad_addr: ERR 7502 "
282                "Cannot locate port object by lid: 0x%X \n",
283                cl_ntoh16(p_mad_addr->dest_lid)
284                );
285     
286       goto Exit;
287     }
288     p_physp = osm_port_get_phys_ptr( p_port, p_port->default_port_num);
289   }
290   else
291   {
292     /* The dest_lid is not in the subnet table - this is an error */
293     osm_log( p_log, OSM_LOG_ERROR,
294              "osm_get_physp_by_mad_addr: ERR 7503 "
295              "Lid is out of range: 0x%X \n",
296              cl_ntoh16(p_mad_addr->dest_lid)
297              );
298     
299     goto Exit;
300   }
301
302  Exit:
303   return p_physp;
304 }
305
306 /**********************************************************************
307  **********************************************************************/
308 osm_port_t*
309 osm_get_port_by_mad_addr(
310   IN osm_log_t*            p_log,
311   IN const osm_subn_t     *p_subn,
312   IN osm_mad_addr_t       *p_mad_addr )
313 {
314   const cl_ptr_vector_t*  p_port_lid_tbl;
315   osm_port_t*             p_port = NULL;
316
317   /* Find the port gid of the request in the subnet */
318   p_port_lid_tbl = &p_subn->port_lid_tbl;
319
320   CL_ASSERT( cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000 );
321
322   if ((uint16_t)cl_ptr_vector_get_size(p_port_lid_tbl) > 
323       cl_ntoh16(p_mad_addr->dest_lid))
324   {
325     p_port = 
326       cl_ptr_vector_get( p_port_lid_tbl, cl_ntoh16(p_mad_addr->dest_lid) );
327   }
328   else
329   {
330     /* The dest_lid is not in the subnet table - this is an error */
331     osm_log( p_log, OSM_LOG_ERROR,
332              "osm_get_port_by_mad_addr: ERR 7504 "
333              "Lid is out of range: 0x%X \n",
334              cl_ntoh16(p_mad_addr->dest_lid)
335              );
336     goto Exit;
337   }
338
339  Exit:
340   return p_port;
341 }
342
343 /**********************************************************************
344  **********************************************************************/
345 osm_switch_t *
346 osm_get_switch_by_guid(
347   IN const osm_subn_t *p_subn,
348   IN uint64_t          guid)
349 {
350   osm_switch_t *p_switch;
351   p_switch = (osm_switch_t*)cl_qmap_get( &(p_subn->sw_guid_tbl), guid );
352   if( p_switch == (osm_switch_t*)cl_qmap_end( &(p_subn->sw_guid_tbl)) )
353     p_switch = NULL;
354   return p_switch;
355 }
356
357 /**********************************************************************
358  **********************************************************************/
359 osm_node_t *
360 osm_get_node_by_guid(
361   IN osm_subn_t const *p_subn,
362   IN uint64_t          guid)
363 {
364   osm_node_t *p_node;
365   p_node = (osm_node_t*)cl_qmap_get( &(p_subn->node_guid_tbl), guid );
366   if( p_node == (osm_node_t*)cl_qmap_end( &(p_subn->node_guid_tbl)) )
367     p_node = NULL;
368   return p_node;
369 }
370
371 /**********************************************************************
372  **********************************************************************/
373 osm_port_t *
374 osm_get_port_by_guid(
375         IN osm_subn_t const *p_subn,
376    IN uint64_t          guid)
377 {
378   osm_port_t *p_port;
379   p_port = (osm_port_t*)cl_qmap_get( &(p_subn->port_guid_tbl), guid );
380   if( p_port == (osm_port_t*)cl_qmap_end( &(p_subn->port_guid_tbl)) )
381     p_port = NULL;
382   return p_port;
383
384 }
385
386 /**********************************************************************
387  **********************************************************************/
388 void
389 osm_subn_set_default_opt(
390   IN osm_subn_opt_t* const p_opt )
391 {
392   cl_memclr(p_opt, sizeof(osm_subn_opt_t));
393   p_opt->m_key = OSM_DEFAULT_M_KEY;
394   p_opt->sm_key = OSM_DEFAULT_SM_KEY;
395   p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
396   p_opt->m_key_lease_period = 0;
397   p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
398   p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
399   p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
400   /* by default we will consider waiting for 50x transaction timeout normal */
401   p_opt->max_msg_fifo_timeout = 50*OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
402   p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
403   p_opt->lmc = OSM_DEFAULT_LMC;
404   p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
405   p_opt->reassign_lids = FALSE;
406   p_opt->reassign_lfts = TRUE;
407   p_opt->ignore_other_sm = FALSE;
408   p_opt->single_thread = FALSE;
409   p_opt->no_multicast_option = FALSE;
410   p_opt->disable_multicast = FALSE;
411   p_opt->force_log_flush = FALSE;
412   p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
413   p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
414   p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
415   p_opt->leaf_head_of_queue_lifetime = OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
416   p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
417   p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
418   p_opt->sminfo_polling_timeout = OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
419   p_opt->polling_retry_number = 4;
420   p_opt->force_heavy_sweep = FALSE;
421   p_opt->log_flags = 0;
422   p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
423   if (!p_opt->dump_files_dir)
424     p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
425
426   p_opt->log_file = OSM_DEFAULT_LOG_FILE;
427   p_opt->port_profile_switch_nodes = FALSE;
428   p_opt->max_port_profile = 0xffffffff;
429   p_opt->pfn_ui_pre_lid_assign = NULL;
430   p_opt->ui_pre_lid_assign_ctx = NULL;
431   p_opt->pfn_ui_ucast_fdb_assign = NULL;
432   p_opt->ui_ucast_fdb_assign_ctx = NULL;
433   p_opt->pfn_ui_mcast_fdb_assign = NULL;
434   p_opt->ui_mcast_fdb_assign_ctx = NULL;
435   p_opt->sweep_on_trap = TRUE;
436   p_opt->testability_mode = OSM_TEST_MODE_NONE;
437   p_opt->updn_activate = FALSE;
438   p_opt->updn_guid_file = NULL;
439 }
440
441 /**********************************************************************
442  **********************************************************************/
443 static inline void
444 __osm_subn_opts_unpack_net64(
445   IN char *p_req_key,
446   IN char *p_key,
447   IN char *p_val_str,
448   IN uint64_t *p_val)
449 {
450   uint64_t val;
451   if (!strcmp(p_req_key, p_key))
452   {
453 #if __WORDSIZE == 64
454     val = strtoul(p_val_str, NULL, 0);
455 #else
456     val = strtoull(p_val_str, NULL, 0);
457 #endif
458     if (cl_hton64(val) != *p_val)
459     {
460       char buff[128];
461       sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n",
462               p_key, val);
463       printf(buff);
464       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
465       *p_val = cl_ntoh64(val);
466     }
467   }
468 }
469
470 /**********************************************************************
471  **********************************************************************/
472 static inline void
473 __osm_subn_opts_unpack_uint32(
474   IN char *p_req_key,
475   IN char *p_key,
476   IN char *p_val_str,
477   IN uint32_t *p_val)
478 {
479   uint32_t val;
480   if (!strcmp(p_req_key, p_key))
481   {
482     val = strtoul(p_val_str, NULL, 0);
483     if (val != *p_val)
484     {
485       char buff[128];
486       sprintf(buff, " Using Cached Option:%s = %u\n",
487               p_key, val);
488       printf(buff);
489       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
490       *p_val = val;
491     }
492   }
493 }
494
495 /**********************************************************************
496  **********************************************************************/
497 static inline void
498 __osm_subn_opts_unpack_net16(
499   IN char *p_req_key,
500   IN char *p_key,
501   IN char *p_val_str,
502   IN uint16_t *p_val)
503 {
504   if (!strcmp(p_req_key, p_key))
505   {
506     uint32_t val;
507     val = strtoul(p_val_str, NULL, 0);
508     CL_ASSERT( val < 0x10000 );
509     if (cl_hton32(val) != *p_val) 
510     {
511       char buff[128];
512       sprintf(buff, " Using Cached Option:%s = 0x%04x\n",
513               p_key, val);
514       printf(buff);
515       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
516       *p_val = cl_hton16((uint16_t)val);
517     }
518   }
519 }
520
521 /**********************************************************************
522  **********************************************************************/
523 static inline void
524 __osm_subn_opts_unpack_uint8(
525   IN char *p_req_key,
526   IN char *p_key,
527   IN char *p_val_str,
528   IN uint8_t *p_val)
529 {
530
531   if (!strcmp(p_req_key, p_key))
532   {
533     uint32_t val;
534     val = strtoul(p_val_str, NULL, 0);
535     CL_ASSERT( val < 0x100 );
536     if (val != *p_val) 
537     {
538       char buff[128];
539       sprintf(buff, " Using Cached Option:%s = %u\n",
540               p_key, val);
541       printf(buff);
542       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
543       *p_val = (uint8_t)val;
544     }
545   }
546 }
547
548 /**********************************************************************
549  **********************************************************************/
550 static inline void
551 __osm_subn_opts_unpack_boolean(
552   IN char *p_req_key,
553   IN char *p_key,
554   IN char *p_val_str,
555   IN boolean_t *p_val)
556 {
557   if (!strcmp(p_req_key, p_key) && p_val_str)
558   {
559     boolean_t val;
560     if (strcmp("TRUE", p_val_str))
561       val = FALSE;
562     else
563       val = TRUE;
564     
565     if (val != *p_val) {
566       char buff[128];
567       sprintf(buff, " Using Cached Option:%s = %s\n",
568               p_key, p_val_str);
569       printf(buff);
570       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
571       *p_val = val;
572     }
573   }
574 }
575
576 /**********************************************************************
577  **********************************************************************/
578 static inline void
579 __osm_subn_opts_unpack_charp(
580   IN char *p_req_key,
581   IN char *p_key,
582   IN char *p_val_str,  
583   IN char **p_val)
584 {
585   if (!strcmp(p_req_key, p_key) && p_val_str)
586   {
587     if (strcmp(p_val_str, *p_val))
588     {
589       char buff[128];
590       sprintf(buff, " Using Cached Option:%s = %s\n",
591               p_key, p_val_str);
592       printf(buff);
593       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
594       *p_val = (char *)cl_malloc(strlen(p_val_str));
595       strcpy( *p_val, p_val_str);
596     }
597   }
598 }
599
600 /**********************************************************************
601  **********************************************************************/
602 void
603 osm_subn_parse_conf_file(
604   IN osm_subn_opt_t* const p_opts )
605 {
606   char *p_cache_dir = getenv("OSM_CACHE_DIR");
607   char file_name[256];
608   FILE *opts_file;
609   char line[1024];
610   char *p_key, *p_val ,*p_last;
611   
612   /* try to open the options file from the cache dir */
613   if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
614
615   strcpy(file_name, p_cache_dir);
616   strcat(file_name,"/opensm.opts");
617   
618   opts_file = fopen(file_name, "r");
619   if (!opts_file) return;
620
621   while (fgets(line, 1023, opts_file) != NULL)
622   {
623     /* get the first token */
624     p_key = strtok_r(line, " \t\n", &p_last);
625     if (p_key)
626     {
627       p_val = strtok_r(NULL, " \t\n", &p_last);
628       
629       __osm_subn_opts_unpack_net64(
630         "m_key", p_key, p_val, &p_opts->m_key);
631   
632       __osm_subn_opts_unpack_net64(
633         "sm_key", p_key, p_val, &p_opts->sm_key);
634
635       __osm_subn_opts_unpack_net64(
636         "subnet_prefix",
637         p_key, p_val, &p_opts->subnet_prefix );
638
639       __osm_subn_opts_unpack_net16(
640         "m_key_lease_period",
641         p_key, p_val, &p_opts->m_key_lease_period);
642   
643       __osm_subn_opts_unpack_uint32(
644         "sweep_interval",
645         p_key, p_val, &p_opts->sweep_interval);
646       
647       __osm_subn_opts_unpack_uint32( 
648         "max_wire_smps",
649         p_key, p_val, &p_opts->max_wire_smps);
650       
651       __osm_subn_opts_unpack_uint32(
652         "transaction_timeout",
653         p_key, p_val, &p_opts->transaction_timeout);
654       
655       __osm_subn_opts_unpack_uint32(
656         "max_msg_fifo_timeout",
657         p_key, p_val, &p_opts->max_msg_fifo_timeout);
658
659       __osm_subn_opts_unpack_uint8( 
660         "sm_priority",
661         p_key, p_val, &p_opts->sm_priority);
662
663       __osm_subn_opts_unpack_uint8(
664         "lmc",
665         p_key, p_val, &p_opts->lmc);
666
667       __osm_subn_opts_unpack_uint8(
668         "max_op_vls",
669         p_key, p_val, &p_opts->max_op_vls);
670
671       __osm_subn_opts_unpack_boolean(
672         "reassign_lids",
673         p_key, p_val, &p_opts->reassign_lids);
674
675       __osm_subn_opts_unpack_boolean(
676         "reassign_lfts",
677         p_key, p_val, &p_opts->reassign_lfts);
678       
679       __osm_subn_opts_unpack_boolean( 
680         "ignore_other_sm",
681         p_key, p_val, &p_opts->ignore_other_sm);
682       
683       __osm_subn_opts_unpack_boolean( 
684         "single_thread",
685         p_key, p_val, &p_opts->single_thread);
686
687       __osm_subn_opts_unpack_boolean( 
688         "no_multicast_option",
689         p_key, p_val, &p_opts->no_multicast_option);
690       
691       __osm_subn_opts_unpack_boolean( 
692         "disable_multicast",
693         p_key, p_val, &p_opts->disable_multicast);
694       
695       __osm_subn_opts_unpack_boolean( 
696         "force_log_flush",
697         p_key, p_val, &p_opts->force_log_flush);
698
699       __osm_subn_opts_unpack_uint8( 
700         "subnet_timeout",
701         p_key, p_val, &p_opts->subnet_timeout);
702       
703       __osm_subn_opts_unpack_uint8(
704         "packet_life_time",
705         p_key, p_val, &p_opts->packet_life_time);
706       
707       __osm_subn_opts_unpack_uint8(
708         "head_of_queue_lifetime",
709         p_key, p_val, &p_opts->head_of_queue_lifetime);
710       
711       __osm_subn_opts_unpack_uint8(
712         "leaf_head_of_queue_lifetime",
713         p_key, p_val, &p_opts->leaf_head_of_queue_lifetime);
714
715       __osm_subn_opts_unpack_uint8(
716         "local_phy_errors_threshold",
717         p_key, p_val, &p_opts->local_phy_errors_threshold);
718
719       __osm_subn_opts_unpack_uint8(
720         "overrun_errors_threshold",
721         p_key, p_val, &p_opts->overrun_errors_threshold);
722       
723       __osm_subn_opts_unpack_uint32(
724         "sminfo_polling_timeout",
725         p_key, p_val, &p_opts->sminfo_polling_timeout);
726       
727       __osm_subn_opts_unpack_uint32( 
728         "polling_retry_number",
729         p_key, p_val, &p_opts->polling_retry_number);
730       
731       __osm_subn_opts_unpack_boolean(
732         "force_heavy_sweep",
733         p_key, p_val, &p_opts->force_heavy_sweep);
734
735       __osm_subn_opts_unpack_uint8( 
736         "log_flags",
737         p_key, p_val, &p_opts->log_flags);
738
739       __osm_subn_opts_unpack_boolean(
740         "port_profile_switch_nodes",
741         p_key, p_val, &p_opts->port_profile_switch_nodes);
742       
743       __osm_subn_opts_unpack_boolean(
744         "sweep_on_trap",
745         p_key, p_val, &p_opts->sweep_on_trap);
746
747       __osm_subn_opts_unpack_boolean(
748         "updn_activate",
749         p_key, p_val, &p_opts->updn_activate);
750
751       __osm_subn_opts_unpack_charp(
752         "log_file" , p_key, p_val, &p_opts->log_file);
753
754       __osm_subn_opts_unpack_charp(
755         "dump_files_dir" ,
756         p_key, p_val, &p_opts->dump_files_dir);
757
758       __osm_subn_opts_unpack_charp( 
759         "updn_guid_file" ,
760         p_key, p_val, &p_opts->updn_guid_file);
761     }
762   }
763   fclose(opts_file);
764 }
765
766 /**********************************************************************
767  **********************************************************************/
768 void
769 osm_subn_write_conf_file(
770   IN osm_subn_opt_t* const p_opts )
771 {
772   char *p_cache_dir = getenv("OSM_CACHE_DIR");
773   char file_name[256];
774   FILE *opts_file;
775   
776   /* try to open the options file from the cache dir */
777   if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
778
779   strcpy(file_name, p_cache_dir);
780   strcat(file_name,"/opensm.opts");
781   
782   opts_file = fopen(file_name, "w");
783   if (!opts_file) return;
784
785   fprintf( 
786     opts_file,
787     "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
788     "# M_Key value sent to all ports qualifing all Set(PortInfo).\n"
789     "m_key 0x%016" PRIx64 "\n\n"
790     "# The lease period used for the M_Key on this subnet in [msec]\n"
791     "m_key_lease_period %u\n\n"
792     "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n"
793     "sm_key 0x%016" PRIx64 "\n\n"
794     "# Subnet prefix used on this subnet\n"
795     "subnet_prefix 0x%016" PRIx64 "\n\n"
796     "# The LMC value used on this subnet\n"
797     "lmc %u\n\n"
798     "# The code of maximal time a packet can live in a switch\n"
799     "# The actual time is 4.096usec * 2^<packet_life_time code>\n"
800     "# The value 0x14 disables this mechanism\n"
801     "packet_life_time 0x%02x\n\n"
802     "# The code of maximal time a packet can wait at the head of\n"
803     "# transmision queue. \n"
804     "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
805     "# The value 0x14 disables this mechanism\n"          
806     "head_of_queue_lifetime 0x%02x\n\n"
807     "# The maximal time a packet can wait at the head of queue on \n"
808     "# switch port connected to a HCA\n"
809     "leaf_head_of_queue_lifetime 0x%02x\n\n"
810     "# Limit the maximal operational VLs\n"
811     "max_op_vls %u\n\n"
812     "# The subnet_timeout code that will be set for all the ports\n"
813     "# The actual timeout is 4.096usec * 2^<subnet_timeout code>\n"
814     "subnet_timeout %u\n\n"
815     "# Threshold of local phy errors for sending Trap 129\n"
816     "local_phy_errors_threshold 0x%02x\n\n"
817     "# Threshold of credits over-run errors for sending Trap 129\n"
818     "overrun_errors_threshold 0x%02x\n\n",
819     cl_ntoh64(p_opts->m_key),
820     cl_ntoh16(p_opts->m_key_lease_period),
821     cl_ntoh64(p_opts->sm_key),
822     cl_ntoh64(p_opts->subnet_prefix),
823     p_opts->lmc,
824     p_opts->packet_life_time,
825     p_opts->head_of_queue_lifetime,
826     p_opts->leaf_head_of_queue_lifetime,
827     p_opts->max_op_vls,
828     p_opts->subnet_timeout,
829     p_opts->local_phy_errors_threshold,
830     p_opts->overrun_errors_threshold
831     );
832
833   fprintf( 
834     opts_file,
835     "#\n# SWEEP OPTIONS\n#\n"
836     "# The number of seconds between subnet sweeps (0 disables it)\n"
837     "sweep_interval %u\n\n"
838     "# If TRUE cause all lids to be re-assigned\n"
839     "reassign_lids %s\n\n"
840     "# If TRUE ignore existing LFT entries on first sweep (default).\n"
841     "# Otherwise only non minimal hop cases are modified.\n"
842     "# NOTE: A standby SM clears its first sweep flag - since the\n"
843     "# master SM already sweeps...\n"
844     "reassign_lfts %s\n\n"
845     "# If true forces every sweep to be a heavy sweep\n"
846     "force_heavy_sweep %s\n\n"
847     "# If true every trap will cause a heavy sweep.\n"
848     "# NOTE: successive same traps (>10) are supressed\n"
849     "sweep_on_trap %s\n\n",
850     p_opts->sweep_interval,
851     p_opts->reassign_lids ? "TRUE" : "FALSE",
852     p_opts->reassign_lfts ? "TRUE" : "FALSE",
853     p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
854     p_opts->sweep_on_trap ? "TRUE" : "FALSE"    
855     );
856   
857   fprintf( 
858     opts_file,
859     "#\n# ROUTING OPTIONS\n#\n"
860     "# If true do not count switches as link subscriptions\n"
861     "port_profile_switch_nodes %s\n\n"
862     "# Activate the Up/Down routing algorithm\n"
863     "updn_activate %s\n\n",
864     p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE",
865     p_opts->updn_activate ? "TRUE" : "FALSE"
866     );
867   if (p_opts->updn_guid_file)
868     fprintf( opts_file,
869              "# The file holding the Up/Down root node guids\n"
870              "# One guid in each line\n"
871              "updn_guid_file %s\n\n",
872              p_opts->updn_guid_file);
873   
874   fprintf( 
875     opts_file,    
876     "#\n# HANDOVER - MULTIPLE SM's OPTIONS\n#\n"
877     "# SM priority used for deciding who is the master\n"
878     "sm_priority %u\n\n"
879     "# If TRUE other SM's on the subnet should be ignored\n"
880     "ignore_other_sm %s\n\n"
881     "# Timeout in [sec] between two polls of active master SM\n"
882     "sminfo_polling_timeout %u\n\n"
883     "# Number of failing polls of remote SM that declares it dead\n"
884     "polling_retry_number %u\n\n",
885     p_opts->sm_priority,
886     p_opts->ignore_other_sm ? "TRUE" : "FALSE",
887     p_opts->sminfo_polling_timeout,
888     p_opts->polling_retry_number
889     );
890     
891   fprintf(
892     opts_file,
893     "#\n# TIMING AND THREADING OPTIONS\n#\n"
894     "# Number of MADs sent in parallel\n"
895     "max_wire_smps %u\n\n"
896     "# The time taken to a transaction to finish in [msec]\n"
897     "transaction_timeout %u\n\n"
898     "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
899     "# If there is more then one message in the queue and the last message\n"
900     "# stayed in the queue more then this value any SA request will be \n"
901     "# immediatly returned with a BUSY status.\n"
902     "max_msg_fifo_timeout %u\n\n"
903     "# Use a single thread for handling SA queries\n"
904     "single_thread %s\n\n",
905     p_opts->max_wire_smps,
906     p_opts->transaction_timeout,
907     p_opts->max_msg_fifo_timeout,
908     p_opts->single_thread ? "TRUE" : "FALSE"
909     );
910   
911   fprintf( 
912     opts_file,
913     "#\n# DEBUG FEATURES\n#\n"
914     "# The log flags used\n"
915     "log_flags 0x%02x\n\n"
916     "# Force flush of the log file after each log message\n"
917     "force_log_flush %s\n\n"
918     "# Log file to be used\n"
919     "log_file %s\n\n" 
920     "# The directory to hold the file OpenSM dumps\n"
921     "dump_files_dir %s\n\n"
922     "# If TRUE if OpenSM should disable multicast support\n"
923     "no_multicast_option %s\n\n"
924     "# No multicast routing is performed if TRUE\n"
925     "disable_multicast %s\n\n",
926     p_opts->log_flags,
927     p_opts->force_log_flush ? "TRUE" : "FALSE",
928     p_opts->log_file,
929     p_opts->dump_files_dir,
930     p_opts->no_multicast_option ? "TRUE" : "FALSE",
931     p_opts->disable_multicast ? "TRUE" : "FALSE"
932     );
933   
934   /* optional string attributes ... */
935   
936   fclose(opts_file);
937 }
938