]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/opensm/opensm/osm_subnet.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_subnet.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
4  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5  * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
6  *
7  * This software is available to you under a choice of one of two
8  * licenses.  You may choose to be licensed under the terms of the GNU
9  * General Public License (GPL) Version 2, available from the file
10  * COPYING in the main directory of this source tree, or the
11  * OpenIB.org BSD license below:
12  *
13  *     Redistribution and use in source and binary forms, with or
14  *     without modification, are permitted provided that the following
15  *     conditions are met:
16  *
17  *      - Redistributions of source code must retain the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer.
20  *
21  *      - Redistributions in binary form must reproduce the above
22  *        copyright notice, this list of conditions and the following
23  *        disclaimer in the documentation and/or other materials
24  *        provided with the distribution.
25  *
26  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33  * SOFTWARE.
34  *
35  */
36
37 /*
38  * Abstract:
39  *    Implementation of osm_subn_t.
40  * This object represents an IBA subnet.
41  * This object is part of the opensm family of objects.
42  */
43
44 #if HAVE_CONFIG_H
45 #  include <config.h>
46 #endif                          /* HAVE_CONFIG_H */
47
48 #include <string.h>
49 #include <stdio.h>
50 #include <stdarg.h>
51 #include <limits.h>
52 #include <errno.h>
53 #include <ctype.h>
54 #include <complib/cl_debug.h>
55 #include <complib/cl_log.h>
56 #include <opensm/osm_subnet.h>
57 #include <opensm/osm_opensm.h>
58 #include <opensm/osm_log.h>
59 #include <opensm/osm_madw.h>
60 #include <opensm/osm_port.h>
61 #include <opensm/osm_switch.h>
62 #include <opensm/osm_remote_sm.h>
63 #include <opensm/osm_partition.h>
64 #include <opensm/osm_node.h>
65 #include <opensm/osm_multicast.h>
66 #include <opensm/osm_inform.h>
67 #include <opensm/osm_console.h>
68 #include <opensm/osm_perfmgr.h>
69 #include <opensm/osm_event_plugin.h>
70 #include <opensm/osm_qos_policy.h>
71
72 static const char null_str[] = "(null)";
73
74 /**********************************************************************
75  **********************************************************************/
76 void osm_subn_construct(IN osm_subn_t * const p_subn)
77 {
78         memset(p_subn, 0, sizeof(*p_subn));
79         cl_ptr_vector_construct(&p_subn->port_lid_tbl);
80         cl_qmap_init(&p_subn->sw_guid_tbl);
81         cl_qmap_init(&p_subn->node_guid_tbl);
82         cl_qmap_init(&p_subn->port_guid_tbl);
83         cl_qmap_init(&p_subn->sm_guid_tbl);
84         cl_qlist_init(&p_subn->sa_sr_list);
85         cl_qlist_init(&p_subn->sa_infr_list);
86         cl_qlist_init(&p_subn->prefix_routes_list);
87         cl_qmap_init(&p_subn->rtr_guid_tbl);
88         cl_qmap_init(&p_subn->prtn_pkey_tbl);
89 }
90
91 /**********************************************************************
92  **********************************************************************/
93 void osm_subn_destroy(IN osm_subn_t * const p_subn)
94 {
95         int i;
96         osm_node_t *p_node, *p_next_node;
97         osm_port_t *p_port, *p_next_port;
98         osm_switch_t *p_sw, *p_next_sw;
99         osm_remote_sm_t *p_rsm, *p_next_rsm;
100         osm_prtn_t *p_prtn, *p_next_prtn;
101         osm_mgrp_t *p_mgrp;
102         osm_infr_t *p_infr, *p_next_infr;
103
104         /* it might be a good idea to de-allocate all known objects */
105         p_next_node = (osm_node_t *) cl_qmap_head(&p_subn->node_guid_tbl);
106         while (p_next_node !=
107                (osm_node_t *) cl_qmap_end(&p_subn->node_guid_tbl)) {
108                 p_node = p_next_node;
109                 p_next_node = (osm_node_t *) cl_qmap_next(&p_node->map_item);
110                 osm_node_delete(&p_node);
111         }
112
113         p_next_port = (osm_port_t *) cl_qmap_head(&p_subn->port_guid_tbl);
114         while (p_next_port !=
115                (osm_port_t *) cl_qmap_end(&p_subn->port_guid_tbl)) {
116                 p_port = p_next_port;
117                 p_next_port = (osm_port_t *) cl_qmap_next(&p_port->map_item);
118                 osm_port_delete(&p_port);
119         }
120
121         p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
122         while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
123                 p_sw = p_next_sw;
124                 p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
125                 osm_switch_delete(&p_sw);
126         }
127
128         p_next_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl);
129         while (p_next_rsm !=
130                (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) {
131                 p_rsm = p_next_rsm;
132                 p_next_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item);
133                 free(p_rsm);
134         }
135
136         p_next_prtn = (osm_prtn_t *) cl_qmap_head(&p_subn->prtn_pkey_tbl);
137         while (p_next_prtn !=
138                (osm_prtn_t *) cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
139                 p_prtn = p_next_prtn;
140                 p_next_prtn = (osm_prtn_t *) cl_qmap_next(&p_prtn->map_item);
141                 osm_prtn_delete(&p_prtn);
142         }
143
144         for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
145              i++) {
146                 p_mgrp = p_subn->mgroups[i];
147                 p_subn->mgroups[i] = NULL;
148                 if (p_mgrp)
149                         osm_mgrp_delete(p_mgrp);
150         }
151
152         p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list);
153         while (p_next_infr !=
154                (osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) {
155                 p_infr = p_next_infr;
156                 p_next_infr = (osm_infr_t *) cl_qlist_next(&p_infr->list_item);
157                 osm_infr_delete(p_infr);
158         }
159
160         cl_ptr_vector_destroy(&p_subn->port_lid_tbl);
161
162         osm_qos_policy_destroy(p_subn->p_qos_policy);
163
164         while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
165                 cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
166                 free(item);
167         }
168 }
169
170 /**********************************************************************
171  **********************************************************************/
172 ib_api_status_t
173 osm_subn_init(IN osm_subn_t * const p_subn,
174               IN osm_opensm_t * const p_osm,
175               IN const osm_subn_opt_t * const p_opt)
176 {
177         cl_status_t status;
178
179         p_subn->p_osm = p_osm;
180
181         status = cl_ptr_vector_init(&p_subn->port_lid_tbl,
182                                     OSM_SUBNET_VECTOR_MIN_SIZE,
183                                     OSM_SUBNET_VECTOR_GROW_SIZE);
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->port_lid_tbl, 0, NULL);
197
198         p_subn->opt = *p_opt;
199         p_subn->max_ucast_lid_ho = IB_LID_UCAST_END_HO;
200         p_subn->max_mcast_lid_ho = IB_LID_MCAST_END_HO;
201         p_subn->min_ca_mtu = IB_MAX_MTU;
202         p_subn->min_ca_rate = IB_MAX_RATE;
203         p_subn->ignore_existing_lfts = TRUE;
204
205         /* we assume master by default - so we only need to set it true if STANDBY */
206         p_subn->coming_out_of_standby = FALSE;
207
208         return (IB_SUCCESS);
209 }
210
211 /**********************************************************************
212  **********************************************************************/
213 ib_api_status_t
214 osm_get_gid_by_mad_addr(IN osm_log_t * p_log,
215                         IN const osm_subn_t * p_subn,
216                         IN const osm_mad_addr_t * p_mad_addr,
217                         OUT ib_gid_t * p_gid)
218 {
219         const cl_ptr_vector_t *p_tbl;
220         const osm_port_t *p_port = NULL;
221
222         if (p_gid == NULL) {
223                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7505: "
224                         "Provided output GID is NULL\n");
225                 return (IB_INVALID_PARAMETER);
226         }
227
228         /* Find the port gid of the request in the subnet */
229         p_tbl = &p_subn->port_lid_tbl;
230
231         CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
232
233         if ((uint16_t) cl_ptr_vector_get_size(p_tbl) >
234             cl_ntoh16(p_mad_addr->dest_lid)) {
235                 p_port =
236                     cl_ptr_vector_get(p_tbl, cl_ntoh16(p_mad_addr->dest_lid));
237                 if (p_port == NULL) {
238                         OSM_LOG(p_log, OSM_LOG_DEBUG,
239                                 "Did not find any port with LID: %u\n",
240                                 cl_ntoh16(p_mad_addr->dest_lid));
241                         return (IB_INVALID_PARAMETER);
242                 }
243                 p_gid->unicast.interface_id = p_port->p_physp->port_guid;
244                 p_gid->unicast.prefix = p_subn->opt.subnet_prefix;
245         } else {
246                 /* The dest_lid is not in the subnet table - this is an error */
247                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7501: "
248                         "LID is out of range: %u\n",
249                         cl_ntoh16(p_mad_addr->dest_lid));
250                 return (IB_INVALID_PARAMETER);
251         }
252
253         return (IB_SUCCESS);
254 }
255
256 /**********************************************************************
257  **********************************************************************/
258 osm_physp_t *osm_get_physp_by_mad_addr(IN osm_log_t * p_log,
259                                        IN const osm_subn_t * p_subn,
260                                        IN osm_mad_addr_t * p_mad_addr)
261 {
262         const cl_ptr_vector_t *p_port_lid_tbl;
263         osm_port_t *p_port = NULL;
264         osm_physp_t *p_physp = NULL;
265
266         /* Find the port gid of the request in the subnet */
267         p_port_lid_tbl = &p_subn->port_lid_tbl;
268
269         CL_ASSERT(cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000);
270
271         if ((uint16_t) cl_ptr_vector_get_size(p_port_lid_tbl) >
272             cl_ntoh16(p_mad_addr->dest_lid)) {
273                 p_port =
274                     cl_ptr_vector_get(p_port_lid_tbl,
275                                       cl_ntoh16(p_mad_addr->dest_lid));
276                 if (p_port == NULL) {
277                         /* The port is not in the port_lid table - this is an error */
278                         OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7502: "
279                                 "Cannot locate port object by lid: %u\n",
280                                 cl_ntoh16(p_mad_addr->dest_lid));
281
282                         goto Exit;
283                 }
284                 p_physp = p_port->p_physp;
285         } else {
286                 /* The dest_lid is not in the subnet table - this is an error */
287                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7503: "
288                         "Lid is out of range: %u\n",
289                         cl_ntoh16(p_mad_addr->dest_lid));
290         }
291
292 Exit:
293         return p_physp;
294 }
295
296 /**********************************************************************
297  **********************************************************************/
298 osm_port_t *osm_get_port_by_mad_addr(IN osm_log_t * p_log,
299                                      IN const osm_subn_t * p_subn,
300                                      IN osm_mad_addr_t * p_mad_addr)
301 {
302         const cl_ptr_vector_t *p_port_lid_tbl;
303         osm_port_t *p_port = NULL;
304
305         /* Find the port gid of the request in the subnet */
306         p_port_lid_tbl = &p_subn->port_lid_tbl;
307
308         CL_ASSERT(cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000);
309
310         if ((uint16_t) cl_ptr_vector_get_size(p_port_lid_tbl) >
311             cl_ntoh16(p_mad_addr->dest_lid)) {
312                 p_port =
313                     cl_ptr_vector_get(p_port_lid_tbl,
314                                       cl_ntoh16(p_mad_addr->dest_lid));
315         } else {
316                 /* The dest_lid is not in the subnet table - this is an error */
317                 OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7504: "
318                         "Lid is out of range: %u\n",
319                         cl_ntoh16(p_mad_addr->dest_lid));
320         }
321
322         return p_port;
323 }
324
325 /**********************************************************************
326  **********************************************************************/
327 osm_switch_t *osm_get_switch_by_guid(IN const osm_subn_t * p_subn,
328                                      IN uint64_t guid)
329 {
330         osm_switch_t *p_switch;
331
332         p_switch = (osm_switch_t *) cl_qmap_get(&(p_subn->sw_guid_tbl), guid);
333         if (p_switch == (osm_switch_t *) cl_qmap_end(&(p_subn->sw_guid_tbl)))
334                 p_switch = NULL;
335         return p_switch;
336 }
337
338 /**********************************************************************
339  **********************************************************************/
340 osm_node_t *osm_get_node_by_guid(IN osm_subn_t const *p_subn, IN uint64_t guid)
341 {
342         osm_node_t *p_node;
343
344         p_node = (osm_node_t *) cl_qmap_get(&(p_subn->node_guid_tbl), guid);
345         if (p_node == (osm_node_t *) cl_qmap_end(&(p_subn->node_guid_tbl)))
346                 p_node = NULL;
347         return p_node;
348 }
349
350 /**********************************************************************
351  **********************************************************************/
352 osm_port_t *osm_get_port_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid)
353 {
354         osm_port_t *p_port;
355
356         p_port = (osm_port_t *) cl_qmap_get(&(p_subn->port_guid_tbl), guid);
357         if (p_port == (osm_port_t *) cl_qmap_end(&(p_subn->port_guid_tbl)))
358                 p_port = NULL;
359         return p_port;
360 }
361
362 /**********************************************************************
363  **********************************************************************/
364 static void subn_set_default_qos_options(IN osm_qos_options_t * opt)
365 {
366         opt->max_vls = OSM_DEFAULT_QOS_MAX_VLS;
367         opt->high_limit = OSM_DEFAULT_QOS_HIGH_LIMIT;
368         opt->vlarb_high = OSM_DEFAULT_QOS_VLARB_HIGH;
369         opt->vlarb_low = OSM_DEFAULT_QOS_VLARB_LOW;
370         opt->sl2vl = OSM_DEFAULT_QOS_SL2VL;
371 }
372
373 static void subn_init_qos_options(IN osm_qos_options_t * opt)
374 {
375         opt->max_vls = 0;
376         opt->high_limit = -1;
377         opt->vlarb_high = NULL;
378         opt->vlarb_low = NULL;
379         opt->sl2vl = NULL;
380 }
381
382 /**********************************************************************
383  **********************************************************************/
384 void osm_subn_set_default_opt(IN osm_subn_opt_t * const p_opt)
385 {
386         memset(p_opt, 0, sizeof(osm_subn_opt_t));
387         p_opt->guid = 0;
388         p_opt->m_key = OSM_DEFAULT_M_KEY;
389         p_opt->sm_key = OSM_DEFAULT_SM_KEY;
390         p_opt->sa_key = OSM_DEFAULT_SA_KEY;
391         p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
392         p_opt->m_key_lease_period = 0;
393         p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
394         p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
395         p_opt->console = OSM_DEFAULT_CONSOLE;
396         p_opt->console_port = OSM_DEFAULT_CONSOLE_PORT;
397         p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
398         /* by default we will consider waiting for 50x transaction timeout normal */
399         p_opt->max_msg_fifo_timeout = 50 * OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
400         p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
401         p_opt->lmc = OSM_DEFAULT_LMC;
402         p_opt->lmc_esp0 = FALSE;
403         p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
404         p_opt->force_link_speed = 15;
405         p_opt->reassign_lids = FALSE;
406         p_opt->ignore_other_sm = FALSE;
407         p_opt->single_thread = FALSE;
408         p_opt->disable_multicast = FALSE;
409         p_opt->force_log_flush = FALSE;
410         p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
411         p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
412         p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT;
413         p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT;
414         p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
415         p_opt->leaf_head_of_queue_lifetime =
416             OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
417         p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
418         p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
419         p_opt->sminfo_polling_timeout =
420             OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
421         p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER;
422         p_opt->force_heavy_sweep = FALSE;
423         p_opt->log_flags = OSM_LOG_DEFAULT_LEVEL;
424         p_opt->honor_guid2lid_file = FALSE;
425         p_opt->daemon = FALSE;
426         p_opt->sm_inactive = FALSE;
427         p_opt->babbling_port_policy = FALSE;
428 #ifdef ENABLE_OSM_PERF_MGR
429         p_opt->perfmgr = FALSE;
430         p_opt->perfmgr_redir = TRUE;
431         p_opt->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
432         p_opt->perfmgr_max_outstanding_queries =
433             OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
434         p_opt->event_db_dump_file = NULL; /* use default */
435 #endif                          /* ENABLE_OSM_PERF_MGR */
436
437         p_opt->event_plugin_name = NULL;
438         p_opt->node_name_map_name = NULL;
439
440         p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
441         if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir))
442                 p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
443
444         p_opt->log_file = OSM_DEFAULT_LOG_FILE;
445         p_opt->log_max_size = 0;
446         p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
447         p_opt->no_partition_enforcement = FALSE;
448         p_opt->qos = FALSE;
449         p_opt->qos_policy_file = OSM_DEFAULT_QOS_POLICY_FILE;
450         p_opt->accum_log_file = TRUE;
451         p_opt->port_prof_ignore_file = NULL;
452         p_opt->port_profile_switch_nodes = FALSE;
453         p_opt->sweep_on_trap = TRUE;
454         p_opt->use_ucast_cache = FALSE;
455         p_opt->routing_engine_names = NULL;
456         p_opt->connect_roots = FALSE;
457         p_opt->lid_matrix_dump_file = NULL;
458         p_opt->lfts_file = NULL;
459         p_opt->root_guid_file = NULL;
460         p_opt->cn_guid_file = NULL;
461         p_opt->ids_guid_file = NULL;
462         p_opt->guid_routing_order_file = NULL;
463         p_opt->sa_db_file = NULL;
464         p_opt->exit_on_fatal = TRUE;
465         p_opt->enable_quirks = FALSE;
466         p_opt->no_clients_rereg = FALSE;
467         p_opt->prefix_routes_file = OSM_DEFAULT_PREFIX_ROUTES_FILE;
468         p_opt->consolidate_ipv6_snm_req = FALSE;
469         subn_init_qos_options(&p_opt->qos_options);
470         subn_init_qos_options(&p_opt->qos_ca_options);
471         subn_init_qos_options(&p_opt->qos_sw0_options);
472         subn_init_qos_options(&p_opt->qos_swe_options);
473         subn_init_qos_options(&p_opt->qos_rtr_options);
474 }
475
476 /**********************************************************************
477  **********************************************************************/
478 static void log_report(const char *fmt, ...)
479 {
480         char buf[128];
481         va_list args;
482         va_start(args, fmt);
483         vsnprintf(buf, sizeof(buf), fmt, args);
484         va_end(args);
485         printf(buf);
486         cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
487 }
488
489 static void log_config_value(char *name, const char *fmt, ...)
490 {
491         char buf[128];
492         va_list args;
493         unsigned n;
494         va_start(args, fmt);
495         n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name);
496         if (n > sizeof(buf))
497                 n = sizeof(buf);
498         n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args);
499         if (n > sizeof(buf))
500                 n = sizeof(buf);
501         snprintf(buf + n, sizeof(buf) - n, "\n");
502         va_end(args);
503         printf(buf);
504         cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
505 }
506
507 static void
508 opts_unpack_net64(IN char *p_req_key,
509                   IN char *p_key, IN char *p_val_str, IN uint64_t * p_val)
510 {
511         if (!strcmp(p_req_key, p_key)) {
512                 uint64_t val = strtoull(p_val_str, NULL, 0);
513                 if (cl_hton64(val) != *p_val) {
514                         log_config_value(p_key, "0x%016" PRIx64, val);
515                         *p_val = cl_ntoh64(val);
516                 }
517         }
518 }
519
520 /**********************************************************************
521  **********************************************************************/
522 static void
523 opts_unpack_uint32(IN char *p_req_key,
524                    IN char *p_key, IN char *p_val_str, IN uint32_t * p_val)
525 {
526         if (!strcmp(p_req_key, p_key)) {
527                 uint32_t val = strtoul(p_val_str, NULL, 0);
528                 if (val != *p_val) {
529                         log_config_value(p_key, "%u", val);
530                         *p_val = val;
531                 }
532         }
533 }
534
535 /**********************************************************************
536  **********************************************************************/
537 static void
538 opts_unpack_int32(IN char *p_req_key,
539                   IN char *p_key, IN char *p_val_str, IN int32_t * p_val)
540 {
541         if (!strcmp(p_req_key, p_key)) {
542                 int32_t val = strtol(p_val_str, NULL, 0);
543                 if (val != *p_val) {
544                         log_config_value(p_key, "%d", val);
545                         *p_val = val;
546                 }
547         }
548 }
549
550 /**********************************************************************
551  **********************************************************************/
552 static void
553 opts_unpack_uint16(IN char *p_req_key,
554                    IN char *p_key, IN char *p_val_str, IN uint16_t * p_val)
555 {
556         if (!strcmp(p_req_key, p_key)) {
557                 uint16_t val = (uint16_t) strtoul(p_val_str, NULL, 0);
558                 if (val != *p_val) {
559                         log_config_value(p_key, "%u", val);
560                         *p_val = val;
561                 }
562         }
563 }
564
565 /**********************************************************************
566  **********************************************************************/
567 static void
568 opts_unpack_net16(IN char *p_req_key,
569                   IN char *p_key, IN char *p_val_str, IN uint16_t * p_val)
570 {
571         if (!strcmp(p_req_key, p_key)) {
572                 uint32_t val;
573                 val = strtoul(p_val_str, NULL, 0);
574                 CL_ASSERT(val < 0x10000);
575                 if (cl_hton32(val) != *p_val) {
576                         log_config_value(p_key, "0x%04x", val);
577                         *p_val = cl_hton16((uint16_t) val);
578                 }
579         }
580 }
581
582 /**********************************************************************
583  **********************************************************************/
584 static void
585 opts_unpack_uint8(IN char *p_req_key,
586                   IN char *p_key, IN char *p_val_str, IN uint8_t * p_val)
587 {
588         if (!strcmp(p_req_key, p_key)) {
589                 uint32_t val;
590                 val = strtoul(p_val_str, NULL, 0);
591                 CL_ASSERT(val < 0x100);
592                 if (val != *p_val) {
593                         log_config_value(p_key, "%u", val);
594                         *p_val = (uint8_t) val;
595                 }
596         }
597 }
598
599 /**********************************************************************
600  **********************************************************************/
601 static void
602 opts_unpack_boolean(IN char *p_req_key,
603                     IN char *p_key, IN char *p_val_str, IN boolean_t * p_val)
604 {
605         if (!strcmp(p_req_key, p_key) && p_val_str) {
606                 boolean_t val;
607                 if (strcmp("TRUE", p_val_str))
608                         val = FALSE;
609                 else
610                         val = TRUE;
611
612                 if (val != *p_val) {
613                         log_config_value(p_key, "%s", p_val_str);
614                         *p_val = val;
615                 }
616         }
617 }
618
619 /**********************************************************************
620  **********************************************************************/
621 static void
622 opts_unpack_charp(IN char *p_req_key,
623                   IN char *p_key, IN char *p_val_str, IN char **p_val)
624 {
625         if (!strcmp(p_req_key, p_key) && p_val_str) {
626                 const char *current_str = *p_val ? *p_val : null_str ;
627                 if (strcmp(p_val_str, current_str)) {
628                         log_config_value(p_key, "%s", p_val_str);
629                         /* special case the "(null)" string */
630                         if (strcmp(null_str, p_val_str) == 0) {
631                                 *p_val = NULL;
632                         } else {
633                                 /*
634                                   Ignore the possible memory leak here;
635                                   the pointer may be to a static default.
636                                 */
637                                 *p_val = strdup(p_val_str);
638                         }
639                 }
640         }
641 }
642
643 /**********************************************************************
644  **********************************************************************/
645 static char *clean_val(char *val)
646 {
647         char *p = val;
648         /* clean leading spaces */
649         while (isspace(*p))
650                 p++;
651         val = p;
652         if (!*val)
653                 return val;
654         /* clean trailing spaces */
655         p = val + strlen(val) - 1;
656         while (p > val && isspace(*p))
657                 p--;
658         p[1] = '\0';
659         /* clean quotas */
660         if ((*val == '\"' && *p == '\"') || (*val == '\'' && *p == '\'')) {
661                 val++;
662                 p--;
663         }
664         return val;
665 }
666
667 /**********************************************************************
668  **********************************************************************/
669 static void
670 subn_parse_qos_options(IN const char *prefix,
671                        IN char *p_key,
672                        IN char *p_val_str, IN osm_qos_options_t * opt)
673 {
674         char name[256];
675
676         snprintf(name, sizeof(name), "%s_max_vls", prefix);
677         opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls);
678         snprintf(name, sizeof(name), "%s_high_limit", prefix);
679         opts_unpack_int32(name, p_key, p_val_str, &opt->high_limit);
680         snprintf(name, sizeof(name), "%s_vlarb_high", prefix);
681         opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high);
682         snprintf(name, sizeof(name), "%s_vlarb_low", prefix);
683         opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low);
684         snprintf(name, sizeof(name), "%s_sl2vl", prefix);
685         opts_unpack_charp(name, p_key, p_val_str, &opt->sl2vl);
686 }
687
688 static int
689 subn_dump_qos_options(FILE * file,
690                       const char *set_name,
691                       const char *prefix, osm_qos_options_t * opt)
692 {
693         return fprintf(file, "# %s\n"
694                        "%s_max_vls %u\n"
695                        "%s_high_limit %d\n"
696                        "%s_vlarb_high %s\n"
697                        "%s_vlarb_low %s\n"
698                        "%s_sl2vl %s\n",
699                        set_name,
700                        prefix, opt->max_vls,
701                        prefix, opt->high_limit,
702                        prefix, opt->vlarb_high,
703                        prefix, opt->vlarb_low, prefix, opt->sl2vl);
704 }
705
706 /**********************************************************************
707  **********************************************************************/
708 static ib_api_status_t
709 append_prefix_route(IN osm_subn_t * const p_subn, uint64_t prefix, uint64_t guid)
710 {
711         osm_prefix_route_t *route;
712
713         route = malloc(sizeof *route);
714         if (! route) {
715                 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "out of memory");
716                 return IB_ERROR;
717         }
718
719         route->prefix = cl_hton64(prefix);
720         route->guid = cl_hton64(guid);
721         cl_qlist_insert_tail(&p_subn->prefix_routes_list, &route->list_item);
722         return IB_SUCCESS;
723 }
724
725 static ib_api_status_t
726 osm_parse_prefix_routes_file(IN osm_subn_t * const p_subn)
727 {
728         osm_log_t *log = &p_subn->p_osm->log;
729         FILE *fp;
730         char buf[1024];
731         int line = 0;
732         int errors = 0;
733
734         while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
735                 cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
736                 free(item);
737         }
738
739         fp = fopen(p_subn->opt.prefix_routes_file, "r");
740         if (! fp) {
741                 if (errno == ENOENT)
742                         return IB_SUCCESS;
743
744                 OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s",
745                         p_subn->opt.prefix_routes_file, strerror(errno));
746                 return IB_ERROR;
747         }
748
749         while (fgets(buf, sizeof buf, fp) != NULL) {
750                 char *p_prefix, *p_guid, *p_extra, *p_last, *p_end;
751                 uint64_t prefix, guid;
752
753                 line++;
754                 if (errors > 10)
755                         break;
756
757                 p_prefix = strtok_r(buf, " \t\n", &p_last);
758                 if (! p_prefix)
759                         continue; /* ignore blank lines */
760
761                 if (*p_prefix == '#')
762                         continue; /* ignore comment lines */
763
764                 p_guid = strtok_r(NULL, " \t\n", &p_last);
765                 if (! p_guid) {
766                         OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing GUID\n",
767                                 p_subn->opt.prefix_routes_file, line);
768                         errors++;
769                         continue;
770                 }
771
772                 p_extra = strtok_r(NULL, " \t\n", &p_last);
773                 if (p_extra && *p_extra != '#') {
774                         OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n",
775                                 p_subn->opt.prefix_routes_file, line);
776                 }
777
778                 if (strcmp(p_prefix, "*") == 0)
779                         prefix = 0;
780                 else {
781                         prefix = strtoull(p_prefix, &p_end, 16);
782                         if (*p_end != '\0') {
783                                 OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal prefix: %s\n",
784                                         p_subn->opt.prefix_routes_file, line, p_prefix);
785                                 errors++;
786                                 continue;
787                         }
788                 }
789
790                 if (strcmp(p_guid, "*") == 0)
791                         guid = 0;
792                 else {
793                         guid = strtoull(p_guid, &p_end, 16);
794                         if (*p_end != '\0' && *p_end != '#') {
795                                 OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal GUID: %s\n",
796                                         p_subn->opt.prefix_routes_file, line, p_guid);
797                                 errors++;
798                                 continue;
799                         }
800                 }
801
802                 if (append_prefix_route(p_subn, prefix, guid) != IB_SUCCESS) {
803                         errors++;
804                         break;
805                 }
806         }
807
808         fclose(fp);
809         return (errors == 0) ? IB_SUCCESS : IB_ERROR;
810 }
811
812 /**********************************************************************
813  **********************************************************************/
814 static void subn_verify_max_vls(unsigned *max_vls, const char *prefix, unsigned dflt)
815 {
816         if (!(*max_vls) || *max_vls > 15) {
817                 log_report(" Invalid Cached Option: %s_max_vls=%u: "
818                            "Using Default = %u\n", prefix, *max_vls, dflt);
819                 *max_vls = dflt;
820         }
821 }
822
823 static void subn_verify_high_limit(int *high_limit, const char *prefix, int dflt)
824 {
825         if (*high_limit < 0 || *high_limit > 255) {
826                 log_report(" Invalid Cached Option: %s_high_limit=%d: "
827                            "Using Default: %d\n", prefix, *high_limit, dflt);
828                 *high_limit = dflt;
829         }
830 }
831
832 static void subn_verify_vlarb(char **vlarb, const char *prefix,
833                               const char *suffix, char *dflt)
834 {
835         char *str, *tok, *end, *ptr;
836         int count = 0;
837
838         if (*vlarb == NULL) {
839                 log_report(" Invalid Cached Option: %s_vlarb_%s: "
840                 "Using Default\n", prefix, suffix);
841                 *vlarb = dflt;
842                 return;
843         }
844
845         str = strdup(*vlarb);
846
847         tok = strtok_r(str, ",\n", &ptr);
848         while (tok) {
849                 char *vl_str, *weight_str;
850
851                 vl_str = tok;
852                 weight_str = strchr(tok, ':');
853
854                 if (weight_str) {
855                         long vl, weight;
856
857                         *weight_str = '\0';
858                         weight_str++;
859
860                         vl = strtol(vl_str, &end, 0);
861
862                         if (*end)
863                                 log_report(" Warning: Cached Option "
864                                            "%s_vlarb_%s:vl=%s"
865                                            " improperly formatted\n",
866                                            prefix, suffix, vl_str);
867                         else if (vl < 0 || vl > 14)
868                                 log_report(" Warning: Cached Option "
869                                            "%s_vlarb_%s:vl=%ld out of range\n",
870                                            prefix, suffix, vl);
871
872                         weight = strtol(weight_str, &end, 0);
873
874                         if (*end)
875                                 log_report(" Warning: Cached Option "
876                                            "%s_vlarb_%s:weight=%s "
877                                            "improperly formatted\n",
878                                            prefix, suffix, weight_str);
879                         else if (weight < 0 || weight > 255)
880                                 log_report(" Warning: Cached Option "
881                                            "%s_vlarb_%s:weight=%ld "
882                                            "out of range\n",
883                                            prefix, suffix, weight);
884                 } else
885                         log_report(" Warning: Cached Option "
886                                    "%s_vlarb_%s:vl:weight=%s "
887                                    "improperly formatted\n",
888                                    prefix, suffix, tok);
889
890                 count++;
891                 tok = strtok_r(NULL, ",\n", &ptr);
892         }
893
894         if (count > 64)
895                 log_report(" Warning: Cached Option %s_vlarb_%s: > 64 listed:"
896                            " excess vl:weight pairs will be dropped\n",
897                            prefix, suffix);
898
899         free(str);
900 }
901
902 static void subn_verify_sl2vl(char **sl2vl, const char *prefix, char *dflt)
903 {
904         char *str, *tok, *end, *ptr;
905         int count = 0;
906
907         if (*sl2vl == NULL) {
908                 log_report(" Invalid Cached Option: %s_sl2vl: Using Default\n",
909                            prefix);
910                 *sl2vl = dflt;
911                 return;
912         }
913
914         str = strdup(*sl2vl);
915
916         tok = strtok_r(str, ",\n", &ptr);
917         while (tok) {
918                 long vl = strtol(tok, &end, 0);
919
920                 if (*end)
921                         log_report(" Warning: Cached Option %s_sl2vl:vl=%s "
922                                    "improperly formatted\n", prefix, tok);
923                 else if (vl < 0 || vl > 15)
924                         log_report(" Warning: Cached Option %s_sl2vl:vl=%ld "
925                                    "out of range\n", prefix, vl);
926
927                 count++;
928                 tok = strtok_r(NULL, ",\n", &ptr);
929         }
930
931         if (count < 16)
932                 log_report(" Warning: Cached Option %s_sl2vl: < 16 VLs "
933                            "listed\n", prefix);
934
935         if (count > 16)
936                 log_report(" Warning: Cached Option %s_sl2vl: > 16 listed: "
937                            "excess VLs will be dropped\n", prefix);
938
939         free(str);
940 }
941
942 static void subn_verify_qos_set(osm_qos_options_t *set, const char *prefix,
943                                 osm_qos_options_t *dflt)
944 {
945         subn_verify_max_vls(&set->max_vls, prefix, dflt->max_vls);
946         subn_verify_high_limit(&set->high_limit, prefix, dflt->high_limit);
947         subn_verify_vlarb(&set->vlarb_low, prefix, "low", dflt->vlarb_low);
948         subn_verify_vlarb(&set->vlarb_high, prefix, "high", dflt->vlarb_high);
949         subn_verify_sl2vl(&set->sl2vl, prefix, dflt->sl2vl);
950 }
951
952 int osm_subn_verify_config(IN osm_subn_opt_t * const p_opts)
953 {
954         if (p_opts->lmc > 7) {
955                 log_report(" Invalid Cached Option Value:lmc = %u:"
956                            "Using Default:%u\n", p_opts->lmc, OSM_DEFAULT_LMC);
957                 p_opts->lmc = OSM_DEFAULT_LMC;
958         }
959
960         if (15 < p_opts->sm_priority) {
961                 log_report(" Invalid Cached Option Value:sm_priority = %u:"
962                            "Using Default:%u\n",
963                            p_opts->sm_priority, OSM_DEFAULT_SM_PRIORITY);
964                 p_opts->sm_priority = OSM_DEFAULT_SM_PRIORITY;
965         }
966
967         if ((15 < p_opts->force_link_speed) ||
968             (p_opts->force_link_speed > 7 && p_opts->force_link_speed < 15)) {
969                 log_report(" Invalid Cached Option Value:force_link_speed = %u:"
970                            "Using Default:%u\n", p_opts->force_link_speed,
971                            IB_PORT_LINK_SPEED_ENABLED_MASK);
972                 p_opts->force_link_speed = IB_PORT_LINK_SPEED_ENABLED_MASK;
973         }
974
975         if (strcmp(p_opts->console, OSM_DISABLE_CONSOLE)
976             && strcmp(p_opts->console, OSM_LOCAL_CONSOLE)
977 #ifdef ENABLE_OSM_CONSOLE_SOCKET
978             && strcmp(p_opts->console, OSM_LOOPBACK_CONSOLE)
979             && strcmp(p_opts->console, OSM_REMOTE_CONSOLE)
980 #endif
981             ) {
982                 log_report(" Invalid Cached Option Value:console = %s"
983                            ", Using Default:%s\n",
984                            p_opts->console, OSM_DEFAULT_CONSOLE);
985                 p_opts->console = OSM_DEFAULT_CONSOLE;
986         }
987
988         if (p_opts->qos) {
989                 osm_qos_options_t dflt;
990
991                 /* the default options in qos_options must be correct.
992                  * every other one need not be, b/c those will default
993                  * back to whatever is in qos_options.
994                  */
995
996                 subn_set_default_qos_options(&dflt);
997
998                 subn_verify_qos_set(&p_opts->qos_options, "qos", &dflt);
999                 subn_verify_qos_set(&p_opts->qos_ca_options, "qos_ca",
1000                                     &p_opts->qos_options);
1001                 subn_verify_qos_set(&p_opts->qos_sw0_options, "qos_sw0",
1002                                     &p_opts->qos_options);
1003                 subn_verify_qos_set(&p_opts->qos_swe_options, "qos_swe",
1004                                     &p_opts->qos_options);
1005                 subn_verify_qos_set(&p_opts->qos_rtr_options, "qos_rtr",
1006                                     &p_opts->qos_options);
1007         }
1008
1009 #ifdef ENABLE_OSM_PERF_MGR
1010         if (p_opts->perfmgr_sweep_time_s < 1) {
1011                 log_report(" Invalid Cached Option Value:perfmgr_sweep_time_s "
1012                            "= %u Using Default:%u\n",
1013                            p_opts->perfmgr_sweep_time_s,
1014                            OSM_PERFMGR_DEFAULT_SWEEP_TIME_S);
1015                 p_opts->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
1016         }
1017         if (p_opts->perfmgr_max_outstanding_queries < 1) {
1018                 log_report(" Invalid Cached Option Value:"
1019                            "perfmgr_max_outstanding_queries = %u"
1020                            " Using Default:%u\n",
1021                            p_opts->perfmgr_max_outstanding_queries,
1022                            OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES);
1023                 p_opts->perfmgr_max_outstanding_queries =
1024                     OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
1025         }
1026 #endif
1027
1028         return 0;
1029 }
1030
1031 /**********************************************************************
1032  **********************************************************************/
1033 int osm_subn_parse_conf_file(char *file_name, osm_subn_opt_t * const p_opts)
1034 {
1035         char line[1024];
1036         FILE *opts_file;
1037         char *p_key, *p_val;
1038
1039         opts_file = fopen(file_name, "r");
1040         if (!opts_file) {
1041                 if (errno == ENOENT)
1042                         return 1;
1043                 printf("cannot open file \'%s\': %s\n",
1044                        file_name, strerror(errno));
1045                 return -1;
1046         }
1047
1048         printf(" Reading Cached Option File: %s\n", file_name);
1049         cl_log_event("OpenSM", CL_LOG_INFO, line, NULL, 0);
1050
1051         p_opts->config_file = file_name;
1052
1053         while (fgets(line, 1023, opts_file) != NULL) {
1054                 /* get the first token */
1055                 p_key = strtok_r(line, " \t\n", &p_val);
1056                 if (!p_key)
1057                         continue;
1058
1059                 p_val = clean_val(p_val);
1060
1061                 opts_unpack_net64("guid", p_key, p_val, &p_opts->guid);
1062
1063                 opts_unpack_net64("m_key", p_key, p_val, &p_opts->m_key);
1064
1065                 opts_unpack_net64("sm_key", p_key, p_val, &p_opts->sm_key);
1066
1067                 opts_unpack_net64("sa_key", p_key, p_val, &p_opts->sa_key);
1068
1069                 opts_unpack_net64("subnet_prefix",
1070                                   p_key, p_val, &p_opts->subnet_prefix);
1071
1072                 opts_unpack_net16("m_key_lease_period",
1073                                   p_key, p_val, &p_opts->m_key_lease_period);
1074
1075                 opts_unpack_uint32("sweep_interval",
1076                                    p_key, p_val, &p_opts->sweep_interval);
1077
1078                 opts_unpack_uint32("max_wire_smps",
1079                                    p_key, p_val, &p_opts->max_wire_smps);
1080
1081                 opts_unpack_charp("console", p_key, p_val, &p_opts->console);
1082
1083                 opts_unpack_uint16("console_port",
1084                                    p_key, p_val, &p_opts->console_port);
1085
1086                 opts_unpack_uint32("transaction_timeout",
1087                                    p_key, p_val, &p_opts->transaction_timeout);
1088
1089                 opts_unpack_uint32("max_msg_fifo_timeout",
1090                                    p_key, p_val, &p_opts->max_msg_fifo_timeout);
1091
1092                 opts_unpack_uint8("sm_priority",
1093                                   p_key, p_val, &p_opts->sm_priority);
1094
1095                 opts_unpack_uint8("lmc", p_key, p_val, &p_opts->lmc);
1096
1097                 opts_unpack_boolean("lmc_esp0",
1098                                     p_key, p_val, &p_opts->lmc_esp0);
1099
1100                 opts_unpack_uint8("max_op_vls",
1101                                   p_key, p_val, &p_opts->max_op_vls);
1102
1103                 opts_unpack_uint8("force_link_speed",
1104                                   p_key, p_val, &p_opts->force_link_speed);
1105
1106                 opts_unpack_boolean("reassign_lids",
1107                                     p_key, p_val, &p_opts->reassign_lids);
1108
1109                 opts_unpack_boolean("ignore_other_sm",
1110                                     p_key, p_val, &p_opts->ignore_other_sm);
1111
1112                 opts_unpack_boolean("single_thread",
1113                                     p_key, p_val, &p_opts->single_thread);
1114
1115                 opts_unpack_boolean("disable_multicast",
1116                                     p_key, p_val, &p_opts->disable_multicast);
1117
1118                 opts_unpack_boolean("force_log_flush",
1119                                     p_key, p_val, &p_opts->force_log_flush);
1120
1121                 opts_unpack_uint8("subnet_timeout",
1122                                   p_key, p_val, &p_opts->subnet_timeout);
1123
1124                 opts_unpack_uint8("packet_life_time",
1125                                   p_key, p_val, &p_opts->packet_life_time);
1126
1127                 opts_unpack_uint8("vl_stall_count",
1128                                   p_key, p_val, &p_opts->vl_stall_count);
1129
1130                 opts_unpack_uint8("leaf_vl_stall_count",
1131                                   p_key, p_val, &p_opts->leaf_vl_stall_count);
1132
1133                 opts_unpack_uint8("head_of_queue_lifetime",
1134                                   p_key, p_val,
1135                                   &p_opts->head_of_queue_lifetime);
1136
1137                 opts_unpack_uint8("leaf_head_of_queue_lifetime", p_key, p_val,
1138                                   &p_opts->leaf_head_of_queue_lifetime);
1139
1140                 opts_unpack_uint8("local_phy_errors_threshold", p_key, p_val,
1141                                   &p_opts->local_phy_errors_threshold);
1142
1143                 opts_unpack_uint8("overrun_errors_threshold",
1144                                   p_key, p_val,
1145                                   &p_opts->overrun_errors_threshold);
1146
1147                 opts_unpack_uint32("sminfo_polling_timeout",
1148                                    p_key, p_val,
1149                                    &p_opts->sminfo_polling_timeout);
1150
1151                 opts_unpack_uint32("polling_retry_number",
1152                                    p_key, p_val, &p_opts->polling_retry_number);
1153
1154                 opts_unpack_boolean("force_heavy_sweep",
1155                                     p_key, p_val, &p_opts->force_heavy_sweep);
1156
1157                 opts_unpack_uint8("log_flags",
1158                                   p_key, p_val, &p_opts->log_flags);
1159
1160                 opts_unpack_charp("port_prof_ignore_file", p_key, p_val,
1161                                   &p_opts->port_prof_ignore_file);
1162
1163                 opts_unpack_boolean("port_profile_switch_nodes", p_key, p_val,
1164                                     &p_opts->port_profile_switch_nodes);
1165
1166                 opts_unpack_boolean("sweep_on_trap",
1167                                     p_key, p_val, &p_opts->sweep_on_trap);
1168
1169                 opts_unpack_charp("routing_engine",
1170                                   p_key, p_val, &p_opts->routing_engine_names);
1171
1172                 opts_unpack_boolean("connect_roots",
1173                                     p_key, p_val, &p_opts->connect_roots);
1174
1175                 opts_unpack_boolean("use_ucast_cache",
1176                                     p_key, p_val, &p_opts->use_ucast_cache);
1177
1178                 opts_unpack_charp("log_file", p_key, p_val, &p_opts->log_file);
1179
1180                 opts_unpack_uint32("log_max_size",
1181                                    p_key, p_val,
1182                                    (void *) & p_opts->log_max_size);
1183                 p_opts->log_max_size *= 1024 * 1024; /* convert to MB */
1184
1185                 opts_unpack_charp("partition_config_file",
1186                                   p_key, p_val, &p_opts->partition_config_file);
1187
1188                 opts_unpack_boolean("no_partition_enforcement", p_key, p_val,
1189                                     &p_opts->no_partition_enforcement);
1190
1191                 opts_unpack_boolean("qos", p_key, p_val, &p_opts->qos);
1192
1193                 opts_unpack_charp("qos_policy_file",
1194                                   p_key, p_val, &p_opts->qos_policy_file);
1195
1196                 opts_unpack_boolean("accum_log_file",
1197                                     p_key, p_val, &p_opts->accum_log_file);
1198
1199                 opts_unpack_charp("dump_files_dir",
1200                                   p_key, p_val, &p_opts->dump_files_dir);
1201
1202                 opts_unpack_charp("lid_matrix_dump_file",
1203                                   p_key, p_val, &p_opts->lid_matrix_dump_file);
1204
1205                 opts_unpack_charp("lfts_file",
1206                                   p_key, p_val, &p_opts->lfts_file);
1207
1208                 opts_unpack_charp("root_guid_file",
1209                                   p_key, p_val, &p_opts->root_guid_file);
1210
1211                 opts_unpack_charp("cn_guid_file",
1212                                   p_key, p_val, &p_opts->cn_guid_file);
1213
1214                 opts_unpack_charp("ids_guid_file",
1215                                   p_key, p_val, &p_opts->ids_guid_file);
1216
1217                 opts_unpack_charp("guid_routing_order_file",
1218                                   p_key, p_val, &p_opts->guid_routing_order_file);
1219
1220                 opts_unpack_charp("sa_db_file",
1221                                   p_key, p_val, &p_opts->sa_db_file);
1222
1223                 opts_unpack_boolean("exit_on_fatal",
1224                                     p_key, p_val, &p_opts->exit_on_fatal);
1225
1226                 opts_unpack_boolean("honor_guid2lid_file",
1227                                     p_key, p_val, &p_opts->honor_guid2lid_file);
1228
1229                 opts_unpack_boolean("daemon", p_key, p_val, &p_opts->daemon);
1230
1231                 opts_unpack_boolean("sm_inactive",
1232                                     p_key, p_val, &p_opts->sm_inactive);
1233
1234                 opts_unpack_boolean("babbling_port_policy",
1235                                     p_key, p_val,
1236                                     &p_opts->babbling_port_policy);
1237
1238 #ifdef ENABLE_OSM_PERF_MGR
1239                 opts_unpack_boolean("perfmgr", p_key, p_val, &p_opts->perfmgr);
1240
1241                 opts_unpack_boolean("perfmgr_redir",
1242                                     p_key, p_val, &p_opts->perfmgr_redir);
1243
1244                 opts_unpack_uint16("perfmgr_sweep_time_s",
1245                                    p_key, p_val, &p_opts->perfmgr_sweep_time_s);
1246
1247                 opts_unpack_uint32("perfmgr_max_outstanding_queries",
1248                                    p_key, p_val,
1249                                    &p_opts->perfmgr_max_outstanding_queries);
1250
1251                 opts_unpack_charp("event_db_dump_file",
1252                                   p_key, p_val, &p_opts->event_db_dump_file);
1253 #endif                          /* ENABLE_OSM_PERF_MGR */
1254
1255                 opts_unpack_charp("event_plugin_name",
1256                                   p_key, p_val, &p_opts->event_plugin_name);
1257
1258                 opts_unpack_charp("node_name_map_name",
1259                                   p_key, p_val, &p_opts->node_name_map_name);
1260
1261                 subn_parse_qos_options("qos",
1262                                        p_key, p_val, &p_opts->qos_options);
1263
1264                 subn_parse_qos_options("qos_ca",
1265                                        p_key, p_val, &p_opts->qos_ca_options);
1266
1267                 subn_parse_qos_options("qos_sw0",
1268                                        p_key, p_val, &p_opts->qos_sw0_options);
1269
1270                 subn_parse_qos_options("qos_swe",
1271                                        p_key, p_val, &p_opts->qos_swe_options);
1272
1273                 subn_parse_qos_options("qos_rtr",
1274                                        p_key, p_val, &p_opts->qos_rtr_options);
1275
1276                 opts_unpack_boolean("enable_quirks",
1277                                     p_key, p_val, &p_opts->enable_quirks);
1278
1279                 opts_unpack_boolean("no_clients_rereg",
1280                                     p_key, p_val, &p_opts->no_clients_rereg);
1281
1282                 opts_unpack_charp("prefix_routes_file",
1283                                   p_key, p_val, &p_opts->prefix_routes_file);
1284
1285                 opts_unpack_boolean("consolidate_ipv6_snm_req",
1286                                 p_key, p_val, &p_opts->consolidate_ipv6_snm_req);
1287         }
1288         fclose(opts_file);
1289
1290         osm_subn_verify_config(p_opts);
1291
1292         return 0;
1293 }
1294
1295 int osm_subn_rescan_conf_files(IN osm_subn_t * const p_subn)
1296 {
1297         FILE *opts_file;
1298         char line[1024];
1299         char *p_key, *p_val, *p_last;
1300
1301         if (!p_subn->opt.config_file)
1302                 return 0;
1303
1304         opts_file = fopen(p_subn->opt.config_file, "r");
1305         if (!opts_file) {
1306                 if (errno == ENOENT)
1307                         return 1;
1308                 OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
1309                         "cannot open file \'%s\': %s\n",
1310                         p_subn->opt.config_file, strerror(errno));
1311                 return -1;
1312         }
1313
1314         subn_init_qos_options(&p_subn->opt.qos_options);
1315         subn_init_qos_options(&p_subn->opt.qos_ca_options);
1316         subn_init_qos_options(&p_subn->opt.qos_sw0_options);
1317         subn_init_qos_options(&p_subn->opt.qos_swe_options);
1318         subn_init_qos_options(&p_subn->opt.qos_rtr_options);
1319
1320         while (fgets(line, 1023, opts_file) != NULL) {
1321                 /* get the first token */
1322                 p_key = strtok_r(line, " \t\n", &p_last);
1323                 if (p_key) {
1324                         p_val = strtok_r(NULL, " \t\n", &p_last);
1325
1326                         subn_parse_qos_options("qos", p_key, p_val,
1327                                                &p_subn->opt.qos_options);
1328
1329                         subn_parse_qos_options("qos_ca", p_key, p_val,
1330                                                &p_subn->opt.qos_ca_options);
1331
1332                         subn_parse_qos_options("qos_sw0", p_key, p_val,
1333                                                &p_subn->opt.qos_sw0_options);
1334
1335                         subn_parse_qos_options("qos_swe", p_key, p_val,
1336                                                &p_subn->opt.qos_swe_options);
1337
1338                         subn_parse_qos_options("qos_rtr", p_key, p_val,
1339                                                &p_subn->opt.qos_rtr_options);
1340
1341                 }
1342         }
1343         fclose(opts_file);
1344
1345         osm_subn_verify_config(&p_subn->opt);
1346
1347         osm_parse_prefix_routes_file(p_subn);
1348
1349         return 0;
1350 }
1351
1352 /**********************************************************************
1353  **********************************************************************/
1354 int osm_subn_output_conf(FILE *out, IN osm_subn_opt_t *const p_opts)
1355 {
1356         fprintf(out,
1357                 "#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
1358                 "# The port GUID on which the OpenSM is running\n"
1359                 "guid 0x%016" PRIx64 "\n\n"
1360                 "# M_Key value sent to all ports qualifying all Set(PortInfo)\n"
1361                 "m_key 0x%016" PRIx64 "\n\n"
1362                 "# The lease period used for the M_Key on this subnet in [sec]\n"
1363                 "m_key_lease_period %u\n\n"
1364                 "# SM_Key value of the SM used for SM authentication\n"
1365                 "sm_key 0x%016" PRIx64 "\n\n"
1366                 "# SM_Key value to qualify rcv SA queries as 'trusted'\n"
1367                 "sa_key 0x%016" PRIx64 "\n\n"
1368                 "# Note that for both values above (sm_key and sa_key)\n"
1369                 "# OpenSM version 3.2.1 and below used the default value '1'\n"
1370                 "# in a host byte order, it is fixed now but you may need to\n"
1371                 "# change the values to interoperate with old OpenSM running\n"
1372                 "# on a little endian machine.\n\n"
1373                 "# Subnet prefix used on this subnet\n"
1374                 "subnet_prefix 0x%016" PRIx64 "\n\n"
1375                 "# The LMC value used on this subnet\n"
1376                 "lmc %u\n\n"
1377                 "# lmc_esp0 determines whether LMC value used on subnet is used for\n"
1378                 "# enhanced switch port 0. If TRUE, LMC value for subnet is used for\n"
1379                 "# ESP0. Otherwise, LMC value for ESP0s is 0.\n"
1380                 "lmc_esp0 %s\n\n"
1381                 "# The code of maximal time a packet can live in a switch\n"
1382                 "# The actual time is 4.096usec * 2^<packet_life_time>\n"
1383                 "# The value 0x14 disables this mechanism\n"
1384                 "packet_life_time 0x%02x\n\n"
1385                 "# The number of sequential packets dropped that cause the port\n"
1386                 "# to enter the VLStalled state. The result of setting this value to\n"
1387                 "# zero is undefined.\n"
1388                 "vl_stall_count 0x%02x\n\n"
1389                 "# The number of sequential packets dropped that cause the port\n"
1390                 "# to enter the VLStalled state. This value is for switch ports\n"
1391                 "# driving a CA or router port. The result of setting this value\n"
1392                 "# to zero is undefined.\n"
1393                 "leaf_vl_stall_count 0x%02x\n\n"
1394                 "# The code of maximal time a packet can wait at the head of\n"
1395                 "# transmission queue.\n"
1396                 "# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
1397                 "# The value 0x14 disables this mechanism\n"
1398                 "head_of_queue_lifetime 0x%02x\n\n"
1399                 "# The maximal time a packet can wait at the head of queue on\n"
1400                 "# switch port connected to a CA or router port\n"
1401                 "leaf_head_of_queue_lifetime 0x%02x\n\n"
1402                 "# Limit the maximal operational VLs\n"
1403                 "max_op_vls %u\n\n"
1404                 "# Force PortInfo:LinkSpeedEnabled on switch ports\n"
1405                 "# If 0, don't modify PortInfo:LinkSpeedEnabled on switch port\n"
1406                 "# Otherwise, use value for PortInfo:LinkSpeedEnabled on switch port\n"
1407                 "# Values are (IB Spec 1.2.1, 14.2.5.6 Table 146 \"PortInfo\")\n"
1408                 "#    1: 2.5 Gbps\n"
1409                 "#    3: 2.5 or 5.0 Gbps\n"
1410                 "#    5: 2.5 or 10.0 Gbps\n"
1411                 "#    7: 2.5 or 5.0 or 10.0 Gbps\n"
1412                 "#    2,4,6,8-14 Reserved\n"
1413                 "#    Default 15: set to PortInfo:LinkSpeedSupported\n"
1414                 "force_link_speed %u\n\n"
1415                 "# The subnet_timeout code that will be set for all the ports\n"
1416                 "# The actual timeout is 4.096usec * 2^<subnet_timeout>\n"
1417                 "subnet_timeout %u\n\n"
1418                 "# Threshold of local phy errors for sending Trap 129\n"
1419                 "local_phy_errors_threshold 0x%02x\n\n"
1420                 "# Threshold of credit overrun errors for sending Trap 130\n"
1421                 "overrun_errors_threshold 0x%02x\n\n",
1422                 cl_ntoh64(p_opts->guid),
1423                 cl_ntoh64(p_opts->m_key),
1424                 cl_ntoh16(p_opts->m_key_lease_period),
1425                 cl_ntoh64(p_opts->sm_key),
1426                 cl_ntoh64(p_opts->sa_key),
1427                 cl_ntoh64(p_opts->subnet_prefix),
1428                 p_opts->lmc,
1429                 p_opts->lmc_esp0 ? "TRUE" : "FALSE",
1430                 p_opts->packet_life_time,
1431                 p_opts->vl_stall_count,
1432                 p_opts->leaf_vl_stall_count,
1433                 p_opts->head_of_queue_lifetime,
1434                 p_opts->leaf_head_of_queue_lifetime,
1435                 p_opts->max_op_vls,
1436                 p_opts->force_link_speed,
1437                 p_opts->subnet_timeout,
1438                 p_opts->local_phy_errors_threshold,
1439                 p_opts->overrun_errors_threshold);
1440
1441         fprintf(out,
1442                 "#\n# PARTITIONING OPTIONS\n#\n"
1443                 "# Partition configuration file to be used\n"
1444                 "partition_config_file %s\n\n"
1445                 "# Disable partition enforcement by switches\n"
1446                 "no_partition_enforcement %s\n\n",
1447                 p_opts->partition_config_file,
1448                 p_opts->no_partition_enforcement ? "TRUE" : "FALSE");
1449
1450         fprintf(out,
1451                 "#\n# SWEEP OPTIONS\n#\n"
1452                 "# The number of seconds between subnet sweeps (0 disables it)\n"
1453                 "sweep_interval %u\n\n"
1454                 "# If TRUE cause all lids to be reassigned\n"
1455                 "reassign_lids %s\n\n"
1456                 "# If TRUE forces every sweep to be a heavy sweep\n"
1457                 "force_heavy_sweep %s\n\n"
1458                 "# If TRUE every trap will cause a heavy sweep.\n"
1459                 "# NOTE: successive identical traps (>10) are suppressed\n"
1460                 "sweep_on_trap %s\n\n",
1461                 p_opts->sweep_interval,
1462                 p_opts->reassign_lids ? "TRUE" : "FALSE",
1463                 p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
1464                 p_opts->sweep_on_trap ? "TRUE" : "FALSE");
1465
1466         fprintf(out,
1467                 "#\n# ROUTING OPTIONS\n#\n"
1468                 "# If TRUE count switches as link subscriptions\n"
1469                 "port_profile_switch_nodes %s\n\n",
1470                 p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
1471
1472         fprintf(out,
1473                 "# Name of file with port guids to be ignored by port profiling\n"
1474                 "port_prof_ignore_file %s\n\n", p_opts->port_prof_ignore_file ?
1475                 p_opts->port_prof_ignore_file : null_str);
1476
1477         fprintf(out,
1478                 "# Routing engine\n"
1479                 "# Multiple routing engines can be specified separated by\n"
1480                 "# commas so that specific ordering of routing algorithms will\n"
1481                 "# be tried if earlier routing engines fail.\n"
1482                 "# Supported engines: minhop, updn, file, ftree, lash, dor\n"
1483                 "routing_engine %s\n\n", p_opts->routing_engine_names ?
1484                 p_opts->routing_engine_names : null_str);
1485
1486         fprintf(out,
1487                 "# Connect roots (use FALSE if unsure)\n"
1488                 "connect_roots %s\n\n",
1489                 p_opts->connect_roots ? "TRUE" : "FALSE");
1490
1491         fprintf(out,
1492                 "# Use unicast routing cache (use FALSE if unsure)\n"
1493                 "use_ucast_cache %s\n\n",
1494                 p_opts->use_ucast_cache ? "TRUE" : "FALSE");
1495
1496         fprintf(out,
1497                 "# Lid matrix dump file name\n"
1498                 "lid_matrix_dump_file %s\n\n", p_opts->lid_matrix_dump_file ?
1499                 p_opts->lid_matrix_dump_file : null_str);
1500
1501         fprintf(out,
1502                 "# LFTs file name\nlfts_file %s\n\n",
1503                 p_opts->lfts_file ? p_opts->lfts_file : null_str);
1504
1505         fprintf(out,
1506                 "# The file holding the root node guids (for fat-tree or Up/Down)\n"
1507                 "# One guid in each line\nroot_guid_file %s\n\n",
1508                 p_opts->root_guid_file ? p_opts->root_guid_file : null_str);
1509
1510         fprintf(out,
1511                 "# The file holding the fat-tree compute node guids\n"
1512                 "# One guid in each line\ncn_guid_file %s\n\n",
1513                 p_opts->cn_guid_file ? p_opts->cn_guid_file : null_str);
1514
1515         fprintf(out,
1516                 "# The file holding the node ids which will be used by"
1517                 " Up/Down algorithm instead\n# of GUIDs (one guid and"
1518                 " id in each line)\nids_guid_file %s\n\n",
1519                 p_opts->ids_guid_file ? p_opts->ids_guid_file : null_str);
1520
1521         fprintf(out,
1522                 "# The file holding guid routing order guids (for MinHop and Up/Down)\n"
1523                 "guid_routing_order_file %s\n\n",
1524                 p_opts->guid_routing_order_file ? p_opts->guid_routing_order_file : null_str);
1525
1526         fprintf(out,
1527                 "# SA database file name\nsa_db_file %s\n\n",
1528                 p_opts->sa_db_file ? p_opts->sa_db_file : null_str);
1529
1530         fprintf(out,
1531                 "#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
1532                 "# SM priority used for deciding who is the master\n"
1533                 "# Range goes from 0 (lowest priority) to 15 (highest).\n"
1534                 "sm_priority %u\n\n"
1535                 "# If TRUE other SMs on the subnet should be ignored\n"
1536                 "ignore_other_sm %s\n\n"
1537                 "# Timeout in [msec] between two polls of active master SM\n"
1538                 "sminfo_polling_timeout %u\n\n"
1539                 "# Number of failing polls of remote SM that declares it dead\n"
1540                 "polling_retry_number %u\n\n"
1541                 "# If TRUE honor the guid2lid file when coming out of standby\n"
1542                 "# state, if such file exists and is valid\n"
1543                 "honor_guid2lid_file %s\n\n",
1544                 p_opts->sm_priority,
1545                 p_opts->ignore_other_sm ? "TRUE" : "FALSE",
1546                 p_opts->sminfo_polling_timeout,
1547                 p_opts->polling_retry_number,
1548                 p_opts->honor_guid2lid_file ? "TRUE" : "FALSE");
1549
1550         fprintf(out,
1551                 "#\n# TIMING AND THREADING OPTIONS\n#\n"
1552                 "# Maximum number of SMPs sent in parallel\n"
1553                 "max_wire_smps %u\n\n"
1554                 "# The maximum time in [msec] allowed for a transaction to complete\n"
1555                 "transaction_timeout %u\n\n"
1556                 "# Maximal time in [msec] a message can stay in the incoming message queue.\n"
1557                 "# If there is more than one message in the queue and the last message\n"
1558                 "# stayed in the queue more than this value, any SA request will be\n"
1559                 "# immediately returned with a BUSY status.\n"
1560                 "max_msg_fifo_timeout %u\n\n"
1561                 "# Use a single thread for handling SA queries\n"
1562                 "single_thread %s\n\n",
1563                 p_opts->max_wire_smps,
1564                 p_opts->transaction_timeout,
1565                 p_opts->max_msg_fifo_timeout,
1566                 p_opts->single_thread ? "TRUE" : "FALSE");
1567
1568         fprintf(out,
1569                 "#\n# MISC OPTIONS\n#\n"
1570                 "# Daemon mode\n"
1571                 "daemon %s\n\n"
1572                 "# SM Inactive\n"
1573                 "sm_inactive %s\n\n"
1574                 "# Babbling Port Policy\n"
1575                 "babbling_port_policy %s\n\n",
1576                 p_opts->daemon ? "TRUE" : "FALSE",
1577                 p_opts->sm_inactive ? "TRUE" : "FALSE",
1578                 p_opts->babbling_port_policy ? "TRUE" : "FALSE");
1579
1580 #ifdef ENABLE_OSM_PERF_MGR
1581         fprintf(out,
1582                 "#\n# Performance Manager Options\n#\n"
1583                 "# perfmgr enable\n"
1584                 "perfmgr %s\n\n"
1585                 "# perfmgr redirection enable\n"
1586                 "perfmgr_redir %s\n\n"
1587                 "# sweep time in seconds\n"
1588                 "perfmgr_sweep_time_s %u\n\n"
1589                 "# Max outstanding queries\n"
1590                 "perfmgr_max_outstanding_queries %u\n\n",
1591                 p_opts->perfmgr ? "TRUE" : "FALSE",
1592                 p_opts->perfmgr_redir ? "TRUE" : "FALSE",
1593                 p_opts->perfmgr_sweep_time_s,
1594                 p_opts->perfmgr_max_outstanding_queries);
1595
1596         fprintf(out,
1597                 "#\n# Event DB Options\n#\n"
1598                 "# Dump file to dump the events to\n"
1599                 "event_db_dump_file %s\n\n", p_opts->event_db_dump_file ?
1600                 p_opts->event_db_dump_file : null_str);
1601 #endif                          /* ENABLE_OSM_PERF_MGR */
1602
1603         fprintf(out,
1604                 "#\n# Event Plugin Options\n#\n"
1605                 "event_plugin_name %s\n\n", p_opts->event_plugin_name ?
1606                 p_opts->event_plugin_name : null_str);
1607
1608         fprintf(out,
1609                 "#\n# Node name map for mapping node's to more descriptive node descriptions\n"
1610                 "# (man ibnetdiscover for more information)\n#\n"
1611                 "node_name_map_name %s\n\n", p_opts->node_name_map_name ?
1612                 p_opts->node_name_map_name : null_str);
1613
1614         fprintf(out,
1615                 "#\n# DEBUG FEATURES\n#\n"
1616                 "# The log flags used\n"
1617                 "log_flags 0x%02x\n\n"
1618                 "# Force flush of the log file after each log message\n"
1619                 "force_log_flush %s\n\n"
1620                 "# Log file to be used\n"
1621                 "log_file %s\n\n"
1622                 "# Limit the size of the log file in MB. If overrun, log is restarted\n"
1623                 "log_max_size %lu\n\n"
1624                 "# If TRUE will accumulate the log over multiple OpenSM sessions\n"
1625                 "accum_log_file %s\n\n"
1626                 "# The directory to hold the file OpenSM dumps\n"
1627                 "dump_files_dir %s\n\n"
1628                 "# If TRUE enables new high risk options and hardware specific quirks\n"
1629                 "enable_quirks %s\n\n"
1630                 "# If TRUE disables client reregistration\n"
1631                 "no_clients_rereg %s\n\n"
1632                 "# If TRUE OpenSM should disable multicast support and\n"
1633                 "# no multicast routing is performed if TRUE\n"
1634                 "disable_multicast %s\n\n"
1635                 "# If TRUE opensm will exit on fatal initialization issues\n"
1636                 "exit_on_fatal %s\n\n" "# console [off|local"
1637 #ifdef ENABLE_OSM_CONSOLE_SOCKET
1638                 "|loopback|socket]\n"
1639 #else
1640                 "]\n"
1641 #endif
1642                 "console %s\n\n"
1643                 "# Telnet port for console (default %d)\n"
1644                 "console_port %d\n\n",
1645                 p_opts->log_flags,
1646                 p_opts->force_log_flush ? "TRUE" : "FALSE",
1647                 p_opts->log_file,
1648                 p_opts->log_max_size/1024/1024,
1649                 p_opts->accum_log_file ? "TRUE" : "FALSE",
1650                 p_opts->dump_files_dir,
1651                 p_opts->enable_quirks ? "TRUE" : "FALSE",
1652                 p_opts->no_clients_rereg ? "TRUE" : "FALSE",
1653                 p_opts->disable_multicast ? "TRUE" : "FALSE",
1654                 p_opts->exit_on_fatal ? "TRUE" : "FALSE",
1655                 p_opts->console,
1656                 OSM_DEFAULT_CONSOLE_PORT, p_opts->console_port);
1657
1658         fprintf(out,
1659                 "#\n# QoS OPTIONS\n#\n"
1660                 "# Enable QoS setup\n"
1661                 "qos %s\n\n"
1662                 "# QoS policy file to be used\n"
1663                 "qos_policy_file %s\n\n",
1664                 p_opts->qos ? "TRUE" : "FALSE", p_opts->qos_policy_file);
1665
1666         subn_dump_qos_options(out,
1667                               "QoS default options", "qos",
1668                               &p_opts->qos_options);
1669         fprintf(out, "\n");
1670         subn_dump_qos_options(out,
1671                               "QoS CA options", "qos_ca",
1672                               &p_opts->qos_ca_options);
1673         fprintf(out, "\n");
1674         subn_dump_qos_options(out,
1675                               "QoS Switch Port 0 options", "qos_sw0",
1676                               &p_opts->qos_sw0_options);
1677         fprintf(out, "\n");
1678         subn_dump_qos_options(out,
1679                               "QoS Switch external ports options", "qos_swe",
1680                               &p_opts->qos_swe_options);
1681         fprintf(out, "\n");
1682         subn_dump_qos_options(out,
1683                               "QoS Router ports options", "qos_rtr",
1684                               &p_opts->qos_rtr_options);
1685         fprintf(out, "\n");
1686
1687         fprintf(out,
1688                 "# Prefix routes file name\n"
1689                 "prefix_routes_file %s\n\n",
1690                 p_opts->prefix_routes_file);
1691
1692         fprintf(out,
1693                 "#\n# IPv6 Solicited Node Multicast (SNM) Options\n#\n"
1694                 "consolidate_ipv6_snm_req %s\n\n",
1695                 p_opts->consolidate_ipv6_snm_req ? "TRUE" : "FALSE");
1696
1697         /* optional string attributes ... */
1698
1699         return 0;
1700 }
1701
1702 int osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t *const p_opts)
1703 {
1704         FILE *opts_file;
1705
1706         opts_file = fopen(file_name, "w");
1707         if (!opts_file) {
1708                 printf("cannot open file \'%s\' for writing: %s\n",
1709                         file_name, strerror(errno));
1710                 return -1;
1711         }
1712
1713         if (osm_subn_output_conf(opts_file, p_opts) < 0)
1714                 return -1;
1715
1716         fclose(opts_file);
1717
1718         return 0;
1719 }