Add -e flag to main in order to enable starting a new log file,
[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->accum_log_file = TRUE;
428   p_opt->port_profile_switch_nodes = FALSE;
429   p_opt->max_port_profile = 0xffffffff;
430   p_opt->pfn_ui_pre_lid_assign = NULL;
431   p_opt->ui_pre_lid_assign_ctx = NULL;
432   p_opt->pfn_ui_ucast_fdb_assign = NULL;
433   p_opt->ui_ucast_fdb_assign_ctx = NULL;
434   p_opt->pfn_ui_mcast_fdb_assign = NULL;
435   p_opt->ui_mcast_fdb_assign_ctx = NULL;
436   p_opt->sweep_on_trap = TRUE;
437   p_opt->testability_mode = OSM_TEST_MODE_NONE;
438   p_opt->updn_activate = FALSE;
439   p_opt->updn_guid_file = NULL;
440 }
441
442 /**********************************************************************
443  **********************************************************************/
444 static inline void
445 __osm_subn_opts_unpack_net64(
446   IN char *p_req_key,
447   IN char *p_key,
448   IN char *p_val_str,
449   IN uint64_t *p_val)
450 {
451   uint64_t val;
452   if (!strcmp(p_req_key, p_key))
453   {
454 #if __WORDSIZE == 64
455     val = strtoul(p_val_str, NULL, 0);
456 #else
457     val = strtoull(p_val_str, NULL, 0);
458 #endif
459     if (cl_hton64(val) != *p_val)
460     {
461       char buff[128];
462       sprintf(buff, " Using Cached Option:%s = 0x%016" PRIx64 "\n",
463               p_key, val);
464       printf(buff);
465       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
466       *p_val = cl_ntoh64(val);
467     }
468   }
469 }
470
471 /**********************************************************************
472  **********************************************************************/
473 static inline void
474 __osm_subn_opts_unpack_uint32(
475   IN char *p_req_key,
476   IN char *p_key,
477   IN char *p_val_str,
478   IN uint32_t *p_val)
479 {
480   uint32_t val;
481   if (!strcmp(p_req_key, p_key))
482   {
483     val = strtoul(p_val_str, NULL, 0);
484     if (val != *p_val)
485     {
486       char buff[128];
487       sprintf(buff, " Using Cached Option:%s = %u\n",
488               p_key, val);
489       printf(buff);
490       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
491       *p_val = val;
492     }
493   }
494 }
495
496 /**********************************************************************
497  **********************************************************************/
498 static inline void
499 __osm_subn_opts_unpack_net16(
500   IN char *p_req_key,
501   IN char *p_key,
502   IN char *p_val_str,
503   IN uint16_t *p_val)
504 {
505   if (!strcmp(p_req_key, p_key))
506   {
507     uint32_t val;
508     val = strtoul(p_val_str, NULL, 0);
509     CL_ASSERT( val < 0x10000 );
510     if (cl_hton32(val) != *p_val) 
511     {
512       char buff[128];
513       sprintf(buff, " Using Cached Option:%s = 0x%04x\n",
514               p_key, val);
515       printf(buff);
516       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
517       *p_val = cl_hton16((uint16_t)val);
518     }
519   }
520 }
521
522 /**********************************************************************
523  **********************************************************************/
524 static inline void
525 __osm_subn_opts_unpack_uint8(
526   IN char *p_req_key,
527   IN char *p_key,
528   IN char *p_val_str,
529   IN uint8_t *p_val)
530 {
531
532   if (!strcmp(p_req_key, p_key))
533   {
534     uint32_t val;
535     val = strtoul(p_val_str, NULL, 0);
536     CL_ASSERT( val < 0x100 );
537     if (val != *p_val) 
538     {
539       char buff[128];
540       sprintf(buff, " Using Cached Option:%s = %u\n",
541               p_key, val);
542       printf(buff);
543       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
544       *p_val = (uint8_t)val;
545     }
546   }
547 }
548
549 /**********************************************************************
550  **********************************************************************/
551 static inline void
552 __osm_subn_opts_unpack_boolean(
553   IN char *p_req_key,
554   IN char *p_key,
555   IN char *p_val_str,
556   IN boolean_t *p_val)
557 {
558   if (!strcmp(p_req_key, p_key) && p_val_str)
559   {
560     boolean_t val;
561     if (strcmp("TRUE", p_val_str))
562       val = FALSE;
563     else
564       val = TRUE;
565     
566     if (val != *p_val) {
567       char buff[128];
568       sprintf(buff, " Using Cached Option:%s = %s\n",
569               p_key, p_val_str);
570       printf(buff);
571       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
572       *p_val = val;
573     }
574   }
575 }
576
577 /**********************************************************************
578  **********************************************************************/
579 static inline void
580 __osm_subn_opts_unpack_charp(
581   IN char *p_req_key,
582   IN char *p_key,
583   IN char *p_val_str,  
584   IN char **p_val)
585 {
586   if (!strcmp(p_req_key, p_key) && p_val_str)
587   {
588     if (strcmp(p_val_str, *p_val))
589     {
590       char buff[128];
591       sprintf(buff, " Using Cached Option:%s = %s\n",
592               p_key, p_val_str);
593       printf(buff);
594       cl_log_event("OpenSM", LOG_INFO, buff, NULL, 0);
595       *p_val = (char *)cl_malloc(strlen(p_val_str));
596       strcpy( *p_val, p_val_str);
597     }
598   }
599 }
600
601 /**********************************************************************
602  **********************************************************************/
603 void
604 osm_subn_parse_conf_file(
605   IN osm_subn_opt_t* const p_opts )
606 {
607   char *p_cache_dir = getenv("OSM_CACHE_DIR");
608   char file_name[256];
609   FILE *opts_file;
610   char line[1024];
611   char *p_key, *p_val ,*p_last;
612   
613   /* try to open the options file from the cache dir */
614   if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
615
616   strcpy(file_name, p_cache_dir);
617   strcat(file_name,"/opensm.opts");
618   
619   opts_file = fopen(file_name, "r");
620   if (!opts_file) return;
621
622   while (fgets(line, 1023, opts_file) != NULL)
623   {
624     /* get the first token */
625     p_key = strtok_r(line, " \t\n", &p_last);
626     if (p_key)
627     {
628       p_val = strtok_r(NULL, " \t\n", &p_last);
629       
630       __osm_subn_opts_unpack_net64(
631         "m_key", p_key, p_val, &p_opts->m_key);
632   
633       __osm_subn_opts_unpack_net64(
634         "sm_key", p_key, p_val, &p_opts->sm_key);
635
636       __osm_subn_opts_unpack_net64(
637         "subnet_prefix",
638         p_key, p_val, &p_opts->subnet_prefix );
639
640       __osm_subn_opts_unpack_net16(
641         "m_key_lease_period",
642         p_key, p_val, &p_opts->m_key_lease_period);
643   
644       __osm_subn_opts_unpack_uint32(
645         "sweep_interval",
646         p_key, p_val, &p_opts->sweep_interval);
647       
648       __osm_subn_opts_unpack_uint32( 
649         "max_wire_smps",
650         p_key, p_val, &p_opts->max_wire_smps);
651       
652       __osm_subn_opts_unpack_uint32(
653         "transaction_timeout",
654         p_key, p_val, &p_opts->transaction_timeout);
655       
656       __osm_subn_opts_unpack_uint32(
657         "max_msg_fifo_timeout",
658         p_key, p_val, &p_opts->max_msg_fifo_timeout);
659
660       __osm_subn_opts_unpack_uint8( 
661         "sm_priority",
662         p_key, p_val, &p_opts->sm_priority);
663
664       __osm_subn_opts_unpack_uint8(
665         "lmc",
666         p_key, p_val, &p_opts->lmc);
667
668       __osm_subn_opts_unpack_uint8(
669         "max_op_vls",
670         p_key, p_val, &p_opts->max_op_vls);
671
672       __osm_subn_opts_unpack_boolean(
673         "reassign_lids",
674         p_key, p_val, &p_opts->reassign_lids);
675
676       __osm_subn_opts_unpack_boolean(
677         "reassign_lfts",
678         p_key, p_val, &p_opts->reassign_lfts);
679       
680       __osm_subn_opts_unpack_boolean( 
681         "ignore_other_sm",
682         p_key, p_val, &p_opts->ignore_other_sm);
683       
684       __osm_subn_opts_unpack_boolean( 
685         "single_thread",
686         p_key, p_val, &p_opts->single_thread);
687
688       __osm_subn_opts_unpack_boolean( 
689         "no_multicast_option",
690         p_key, p_val, &p_opts->no_multicast_option);
691       
692       __osm_subn_opts_unpack_boolean( 
693         "disable_multicast",
694         p_key, p_val, &p_opts->disable_multicast);
695       
696       __osm_subn_opts_unpack_boolean( 
697         "force_log_flush",
698         p_key, p_val, &p_opts->force_log_flush);
699
700       __osm_subn_opts_unpack_uint8( 
701         "subnet_timeout",
702         p_key, p_val, &p_opts->subnet_timeout);
703       
704       __osm_subn_opts_unpack_uint8(
705         "packet_life_time",
706         p_key, p_val, &p_opts->packet_life_time);
707       
708       __osm_subn_opts_unpack_uint8(
709         "head_of_queue_lifetime",
710         p_key, p_val, &p_opts->head_of_queue_lifetime);
711       
712       __osm_subn_opts_unpack_uint8(
713         "leaf_head_of_queue_lifetime",
714         p_key, p_val, &p_opts->leaf_head_of_queue_lifetime);
715
716       __osm_subn_opts_unpack_uint8(
717         "local_phy_errors_threshold",
718         p_key, p_val, &p_opts->local_phy_errors_threshold);
719
720       __osm_subn_opts_unpack_uint8(
721         "overrun_errors_threshold",
722         p_key, p_val, &p_opts->overrun_errors_threshold);
723       
724       __osm_subn_opts_unpack_uint32(
725         "sminfo_polling_timeout",
726         p_key, p_val, &p_opts->sminfo_polling_timeout);
727       
728       __osm_subn_opts_unpack_uint32( 
729         "polling_retry_number",
730         p_key, p_val, &p_opts->polling_retry_number);
731       
732       __osm_subn_opts_unpack_boolean(
733         "force_heavy_sweep",
734         p_key, p_val, &p_opts->force_heavy_sweep);
735
736       __osm_subn_opts_unpack_uint8( 
737         "log_flags",
738         p_key, p_val, &p_opts->log_flags);
739
740       __osm_subn_opts_unpack_boolean(
741         "port_profile_switch_nodes",
742         p_key, p_val, &p_opts->port_profile_switch_nodes);
743       
744       __osm_subn_opts_unpack_boolean(
745         "sweep_on_trap",
746         p_key, p_val, &p_opts->sweep_on_trap);
747
748       __osm_subn_opts_unpack_boolean(
749         "updn_activate",
750         p_key, p_val, &p_opts->updn_activate);
751
752       __osm_subn_opts_unpack_charp(
753         "log_file" , p_key, p_val, &p_opts->log_file);
754
755       __osm_subn_opts_unpack_boolean(
756         "accum_log_file",
757         p_key, p_val, &p_opts->accum_log_file);
758
759       __osm_subn_opts_unpack_charp(
760         "dump_files_dir" ,
761         p_key, p_val, &p_opts->dump_files_dir);
762
763       __osm_subn_opts_unpack_charp( 
764         "updn_guid_file" ,
765         p_key, p_val, &p_opts->updn_guid_file);
766     }
767   }
768   fclose(opts_file);
769 }
770
771 /**********************************************************************
772  **********************************************************************/
773 void
774 osm_subn_write_conf_file(
775   IN osm_subn_opt_t* const p_opts )
776 {
777   char *p_cache_dir = getenv("OSM_CACHE_DIR");
778   char file_name[256];
779   FILE *opts_file;
780   
781   /* try to open the options file from the cache dir */
782   if (! p_cache_dir) p_cache_dir = OSM_DEFAULT_CACHE_DIR;
783
784   strcpy(file_name, p_cache_dir);
785   strcat(file_name,"/opensm.opts");
786   
787   opts_file = fopen(file_name, "w");
788   if (!opts_file) return;
789
790   fprintf( 
791     opts_file,
792     "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
793     "# M_Key value sent to all ports qualifing all Set(PortInfo).\n"
794     "m_key 0x%016" PRIx64 "\n\n"
795     "# The lease period used for the M_Key on this subnet in [msec]\n"
796     "m_key_lease_period %u\n\n"
797     "# SM_Key value of the SM to qualify rcv SA queries as 'trusted'\n"
798     "sm_key 0x%016" PRIx64 "\n\n"
799     "# Subnet prefix used on this subnet\n"
800     "subnet_prefix 0x%016" PRIx64 "\n\n"
801     "# The LMC value used on this subnet\n"
802     "lmc %u\n\n"
803     "# The code of maximal time a packet can live in a switch\n"
804     "# The actual time is 4.096usec * 2^<packet_life_time code>\n"
805     "# The value 0x14 disables this mechanism\n"
806     "packet_life_time 0x%02x\n\n"
807     "# The code of maximal time a packet can wait at the head of\n"
808     "# transmision queue. \n"
809     "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
810     "# The value 0x14 disables this mechanism\n"          
811     "head_of_queue_lifetime 0x%02x\n\n"
812     "# The maximal time a packet can wait at the head of queue on \n"
813     "# switch port connected to a HCA\n"
814     "leaf_head_of_queue_lifetime 0x%02x\n\n"
815     "# Limit the maximal operational VLs\n"
816     "max_op_vls %u\n\n"
817     "# The subnet_timeout code that will be set for all the ports\n"
818     "# The actual timeout is 4.096usec * 2^<subnet_timeout code>\n"
819     "subnet_timeout %u\n\n"
820     "# Threshold of local phy errors for sending Trap 129\n"
821     "local_phy_errors_threshold 0x%02x\n\n"
822     "# Threshold of credits over-run errors for sending Trap 129\n"
823     "overrun_errors_threshold 0x%02x\n\n",
824     cl_ntoh64(p_opts->m_key),
825     cl_ntoh16(p_opts->m_key_lease_period),
826     cl_ntoh64(p_opts->sm_key),
827     cl_ntoh64(p_opts->subnet_prefix),
828     p_opts->lmc,
829     p_opts->packet_life_time,
830     p_opts->head_of_queue_lifetime,
831     p_opts->leaf_head_of_queue_lifetime,
832     p_opts->max_op_vls,
833     p_opts->subnet_timeout,
834     p_opts->local_phy_errors_threshold,
835     p_opts->overrun_errors_threshold
836     );
837
838   fprintf( 
839     opts_file,
840     "#\n# SWEEP OPTIONS\n#\n"
841     "# The number of seconds between subnet sweeps (0 disables it)\n"
842     "sweep_interval %u\n\n"
843     "# If TRUE cause all lids to be re-assigned\n"
844     "reassign_lids %s\n\n"
845     "# If TRUE ignore existing LFT entries on first sweep (default).\n"
846     "# Otherwise only non minimal hop cases are modified.\n"
847     "# NOTE: A standby SM clears its first sweep flag - since the\n"
848     "# master SM already sweeps...\n"
849     "reassign_lfts %s\n\n"
850     "# If true forces every sweep to be a heavy sweep\n"
851     "force_heavy_sweep %s\n\n"
852     "# If true every trap will cause a heavy sweep.\n"
853     "# NOTE: successive same traps (>10) are supressed\n"
854     "sweep_on_trap %s\n\n",
855     p_opts->sweep_interval,
856     p_opts->reassign_lids ? "TRUE" : "FALSE",
857     p_opts->reassign_lfts ? "TRUE" : "FALSE",
858     p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
859     p_opts->sweep_on_trap ? "TRUE" : "FALSE"    
860     );
861   
862   fprintf( 
863     opts_file,
864     "#\n# ROUTING OPTIONS\n#\n"
865     "# If true do not count switches as link subscriptions\n"
866     "port_profile_switch_nodes %s\n\n"
867     "# Activate the Up/Down routing algorithm\n"
868     "updn_activate %s\n\n",
869     p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE",
870     p_opts->updn_activate ? "TRUE" : "FALSE"
871     );
872   if (p_opts->updn_guid_file)
873     fprintf( opts_file,
874              "# The file holding the Up/Down root node guids\n"
875              "# One guid in each line\n"
876              "updn_guid_file %s\n\n",
877              p_opts->updn_guid_file);
878   
879   fprintf( 
880     opts_file,    
881     "#\n# HANDOVER - MULTIPLE SM's OPTIONS\n#\n"
882     "# SM priority used for deciding who is the master\n"
883     "sm_priority %u\n\n"
884     "# If TRUE other SM's on the subnet should be ignored\n"
885     "ignore_other_sm %s\n\n"
886     "# Timeout in [sec] between two polls of active master SM\n"
887     "sminfo_polling_timeout %u\n\n"
888     "# Number of failing polls of remote SM that declares it dead\n"
889     "polling_retry_number %u\n\n",
890     p_opts->sm_priority,
891     p_opts->ignore_other_sm ? "TRUE" : "FALSE",
892     p_opts->sminfo_polling_timeout,
893     p_opts->polling_retry_number
894     );
895     
896   fprintf(
897     opts_file,
898     "#\n# TIMING AND THREADING OPTIONS\n#\n"
899     "# Number of MADs sent in parallel\n"
900     "max_wire_smps %u\n\n"
901     "# The time taken to a transaction to finish in [msec]\n"
902     "transaction_timeout %u\n\n"
903     "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
904     "# If there is more then one message in the queue and the last message\n"
905     "# stayed in the queue more then this value any SA request will be \n"
906     "# immediatly returned with a BUSY status.\n"
907     "max_msg_fifo_timeout %u\n\n"
908     "# Use a single thread for handling SA queries\n"
909     "single_thread %s\n\n",
910     p_opts->max_wire_smps,
911     p_opts->transaction_timeout,
912     p_opts->max_msg_fifo_timeout,
913     p_opts->single_thread ? "TRUE" : "FALSE"
914     );
915   
916   fprintf( 
917     opts_file,
918     "#\n# DEBUG FEATURES\n#\n"
919     "# The log flags used\n"
920     "log_flags 0x%02x\n\n"
921     "# Force flush of the log file after each log message\n"
922     "force_log_flush %s\n\n"
923     "# Log file to be used\n"
924     "log_file %s\n\n" 
925     "accum_log_file %s\n\n"
926     "# The directory to hold the file OpenSM dumps\n"
927     "dump_files_dir %s\n\n"
928     "# If TRUE if OpenSM should disable multicast support\n"
929     "no_multicast_option %s\n\n"
930     "# No multicast routing is performed if TRUE\n"
931     "disable_multicast %s\n\n",
932     p_opts->log_flags,
933     p_opts->force_log_flush ? "TRUE" : "FALSE",
934     p_opts->log_file,
935     p_opts->accum_log_file,
936     p_opts->dump_files_dir,
937     p_opts->no_multicast_option ? "TRUE" : "FALSE",
938     p_opts->disable_multicast ? "TRUE" : "FALSE"
939     );
940   
941   /* optional string attributes ... */
942   
943   fclose(opts_file);
944 }
945