1219820Sjeff/*
2219820Sjeff * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
3219820Sjeff * Copyright (c) 2002-2008 Mellanox Technologies LTD. All rights reserved.
4219820Sjeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5219820Sjeff * Copyright (c) 2008 Xsigo Systems Inc.  All rights reserved.
6219820Sjeff *
7219820Sjeff * This software is available to you under a choice of one of two
8219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
9219820Sjeff * General Public License (GPL) Version 2, available from the file
10219820Sjeff * COPYING in the main directory of this source tree, or the
11219820Sjeff * OpenIB.org BSD license below:
12219820Sjeff *
13219820Sjeff *     Redistribution and use in source and binary forms, with or
14219820Sjeff *     without modification, are permitted provided that the following
15219820Sjeff *     conditions are met:
16219820Sjeff *
17219820Sjeff *      - Redistributions of source code must retain the above
18219820Sjeff *        copyright notice, this list of conditions and the following
19219820Sjeff *        disclaimer.
20219820Sjeff *
21219820Sjeff *      - Redistributions in binary form must reproduce the above
22219820Sjeff *        copyright notice, this list of conditions and the following
23219820Sjeff *        disclaimer in the documentation and/or other materials
24219820Sjeff *        provided with the distribution.
25219820Sjeff *
26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33219820Sjeff * SOFTWARE.
34219820Sjeff *
35219820Sjeff */
36219820Sjeff
37219820Sjeff/*
38219820Sjeff * Abstract:
39219820Sjeff *    Implementation of osm_subn_t.
40219820Sjeff * This object represents an IBA subnet.
41219820Sjeff * This object is part of the opensm family of objects.
42219820Sjeff */
43219820Sjeff
44219820Sjeff#if HAVE_CONFIG_H
45219820Sjeff#  include <config.h>
46219820Sjeff#endif				/* HAVE_CONFIG_H */
47219820Sjeff
48219820Sjeff#include <string.h>
49219820Sjeff#include <stdio.h>
50219820Sjeff#include <stdarg.h>
51219820Sjeff#include <limits.h>
52219820Sjeff#include <errno.h>
53219820Sjeff#include <ctype.h>
54219820Sjeff#include <complib/cl_debug.h>
55219820Sjeff#include <complib/cl_log.h>
56219820Sjeff#include <opensm/osm_subnet.h>
57219820Sjeff#include <opensm/osm_opensm.h>
58219820Sjeff#include <opensm/osm_log.h>
59219820Sjeff#include <opensm/osm_madw.h>
60219820Sjeff#include <opensm/osm_port.h>
61219820Sjeff#include <opensm/osm_switch.h>
62219820Sjeff#include <opensm/osm_remote_sm.h>
63219820Sjeff#include <opensm/osm_partition.h>
64219820Sjeff#include <opensm/osm_node.h>
65219820Sjeff#include <opensm/osm_multicast.h>
66219820Sjeff#include <opensm/osm_inform.h>
67219820Sjeff#include <opensm/osm_console.h>
68219820Sjeff#include <opensm/osm_perfmgr.h>
69219820Sjeff#include <opensm/osm_event_plugin.h>
70219820Sjeff#include <opensm/osm_qos_policy.h>
71219820Sjeff
72219820Sjeffstatic const char null_str[] = "(null)";
73219820Sjeff
74219820Sjeff/**********************************************************************
75219820Sjeff **********************************************************************/
76219820Sjeffvoid osm_subn_construct(IN osm_subn_t * const p_subn)
77219820Sjeff{
78219820Sjeff	memset(p_subn, 0, sizeof(*p_subn));
79219820Sjeff	cl_ptr_vector_construct(&p_subn->port_lid_tbl);
80219820Sjeff	cl_qmap_init(&p_subn->sw_guid_tbl);
81219820Sjeff	cl_qmap_init(&p_subn->node_guid_tbl);
82219820Sjeff	cl_qmap_init(&p_subn->port_guid_tbl);
83219820Sjeff	cl_qmap_init(&p_subn->sm_guid_tbl);
84219820Sjeff	cl_qlist_init(&p_subn->sa_sr_list);
85219820Sjeff	cl_qlist_init(&p_subn->sa_infr_list);
86219820Sjeff	cl_qlist_init(&p_subn->prefix_routes_list);
87219820Sjeff	cl_qmap_init(&p_subn->rtr_guid_tbl);
88219820Sjeff	cl_qmap_init(&p_subn->prtn_pkey_tbl);
89219820Sjeff}
90219820Sjeff
91219820Sjeff/**********************************************************************
92219820Sjeff **********************************************************************/
93219820Sjeffvoid osm_subn_destroy(IN osm_subn_t * const p_subn)
94219820Sjeff{
95219820Sjeff	int i;
96219820Sjeff	osm_node_t *p_node, *p_next_node;
97219820Sjeff	osm_port_t *p_port, *p_next_port;
98219820Sjeff	osm_switch_t *p_sw, *p_next_sw;
99219820Sjeff	osm_remote_sm_t *p_rsm, *p_next_rsm;
100219820Sjeff	osm_prtn_t *p_prtn, *p_next_prtn;
101219820Sjeff	osm_mgrp_t *p_mgrp;
102219820Sjeff	osm_infr_t *p_infr, *p_next_infr;
103219820Sjeff
104219820Sjeff	/* it might be a good idea to de-allocate all known objects */
105219820Sjeff	p_next_node = (osm_node_t *) cl_qmap_head(&p_subn->node_guid_tbl);
106219820Sjeff	while (p_next_node !=
107219820Sjeff	       (osm_node_t *) cl_qmap_end(&p_subn->node_guid_tbl)) {
108219820Sjeff		p_node = p_next_node;
109219820Sjeff		p_next_node = (osm_node_t *) cl_qmap_next(&p_node->map_item);
110219820Sjeff		osm_node_delete(&p_node);
111219820Sjeff	}
112219820Sjeff
113219820Sjeff	p_next_port = (osm_port_t *) cl_qmap_head(&p_subn->port_guid_tbl);
114219820Sjeff	while (p_next_port !=
115219820Sjeff	       (osm_port_t *) cl_qmap_end(&p_subn->port_guid_tbl)) {
116219820Sjeff		p_port = p_next_port;
117219820Sjeff		p_next_port = (osm_port_t *) cl_qmap_next(&p_port->map_item);
118219820Sjeff		osm_port_delete(&p_port);
119219820Sjeff	}
120219820Sjeff
121219820Sjeff	p_next_sw = (osm_switch_t *) cl_qmap_head(&p_subn->sw_guid_tbl);
122219820Sjeff	while (p_next_sw != (osm_switch_t *) cl_qmap_end(&p_subn->sw_guid_tbl)) {
123219820Sjeff		p_sw = p_next_sw;
124219820Sjeff		p_next_sw = (osm_switch_t *) cl_qmap_next(&p_sw->map_item);
125219820Sjeff		osm_switch_delete(&p_sw);
126219820Sjeff	}
127219820Sjeff
128219820Sjeff	p_next_rsm = (osm_remote_sm_t *) cl_qmap_head(&p_subn->sm_guid_tbl);
129219820Sjeff	while (p_next_rsm !=
130219820Sjeff	       (osm_remote_sm_t *) cl_qmap_end(&p_subn->sm_guid_tbl)) {
131219820Sjeff		p_rsm = p_next_rsm;
132219820Sjeff		p_next_rsm = (osm_remote_sm_t *) cl_qmap_next(&p_rsm->map_item);
133219820Sjeff		free(p_rsm);
134219820Sjeff	}
135219820Sjeff
136219820Sjeff	p_next_prtn = (osm_prtn_t *) cl_qmap_head(&p_subn->prtn_pkey_tbl);
137219820Sjeff	while (p_next_prtn !=
138219820Sjeff	       (osm_prtn_t *) cl_qmap_end(&p_subn->prtn_pkey_tbl)) {
139219820Sjeff		p_prtn = p_next_prtn;
140219820Sjeff		p_next_prtn = (osm_prtn_t *) cl_qmap_next(&p_prtn->map_item);
141219820Sjeff		osm_prtn_delete(&p_prtn);
142219820Sjeff	}
143219820Sjeff
144219820Sjeff	for (i = 0; i <= p_subn->max_mcast_lid_ho - IB_LID_MCAST_START_HO;
145219820Sjeff	     i++) {
146219820Sjeff		p_mgrp = p_subn->mgroups[i];
147219820Sjeff		p_subn->mgroups[i] = NULL;
148219820Sjeff		if (p_mgrp)
149219820Sjeff			osm_mgrp_delete(p_mgrp);
150219820Sjeff	}
151219820Sjeff
152219820Sjeff	p_next_infr = (osm_infr_t *) cl_qlist_head(&p_subn->sa_infr_list);
153219820Sjeff	while (p_next_infr !=
154219820Sjeff	       (osm_infr_t *) cl_qlist_end(&p_subn->sa_infr_list)) {
155219820Sjeff		p_infr = p_next_infr;
156219820Sjeff		p_next_infr = (osm_infr_t *) cl_qlist_next(&p_infr->list_item);
157219820Sjeff		osm_infr_delete(p_infr);
158219820Sjeff	}
159219820Sjeff
160219820Sjeff	cl_ptr_vector_destroy(&p_subn->port_lid_tbl);
161219820Sjeff
162219820Sjeff	osm_qos_policy_destroy(p_subn->p_qos_policy);
163219820Sjeff
164219820Sjeff	while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
165219820Sjeff		cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
166219820Sjeff		free(item);
167219820Sjeff	}
168219820Sjeff}
169219820Sjeff
170219820Sjeff/**********************************************************************
171219820Sjeff **********************************************************************/
172219820Sjeffib_api_status_t
173219820Sjeffosm_subn_init(IN osm_subn_t * const p_subn,
174219820Sjeff	      IN osm_opensm_t * const p_osm,
175219820Sjeff	      IN const osm_subn_opt_t * const p_opt)
176219820Sjeff{
177219820Sjeff	cl_status_t status;
178219820Sjeff
179219820Sjeff	p_subn->p_osm = p_osm;
180219820Sjeff
181219820Sjeff	status = cl_ptr_vector_init(&p_subn->port_lid_tbl,
182219820Sjeff				    OSM_SUBNET_VECTOR_MIN_SIZE,
183219820Sjeff				    OSM_SUBNET_VECTOR_GROW_SIZE);
184219820Sjeff	if (status != CL_SUCCESS)
185219820Sjeff		return (status);
186219820Sjeff
187219820Sjeff	status = cl_ptr_vector_set_capacity(&p_subn->port_lid_tbl,
188219820Sjeff					    OSM_SUBNET_VECTOR_CAPACITY);
189219820Sjeff	if (status != CL_SUCCESS)
190219820Sjeff		return (status);
191219820Sjeff
192219820Sjeff	/*
193219820Sjeff	   LID zero is not valid.  NULL out this entry for the
194219820Sjeff	   convenience of other code.
195219820Sjeff	 */
196219820Sjeff	cl_ptr_vector_set(&p_subn->port_lid_tbl, 0, NULL);
197219820Sjeff
198219820Sjeff	p_subn->opt = *p_opt;
199219820Sjeff	p_subn->max_ucast_lid_ho = IB_LID_UCAST_END_HO;
200219820Sjeff	p_subn->max_mcast_lid_ho = IB_LID_MCAST_END_HO;
201219820Sjeff	p_subn->min_ca_mtu = IB_MAX_MTU;
202219820Sjeff	p_subn->min_ca_rate = IB_MAX_RATE;
203219820Sjeff	p_subn->ignore_existing_lfts = TRUE;
204219820Sjeff
205219820Sjeff	/* we assume master by default - so we only need to set it true if STANDBY */
206219820Sjeff	p_subn->coming_out_of_standby = FALSE;
207219820Sjeff
208219820Sjeff	return (IB_SUCCESS);
209219820Sjeff}
210219820Sjeff
211219820Sjeff/**********************************************************************
212219820Sjeff **********************************************************************/
213219820Sjeffib_api_status_t
214219820Sjeffosm_get_gid_by_mad_addr(IN osm_log_t * p_log,
215219820Sjeff			IN const osm_subn_t * p_subn,
216219820Sjeff			IN const osm_mad_addr_t * p_mad_addr,
217219820Sjeff			OUT ib_gid_t * p_gid)
218219820Sjeff{
219219820Sjeff	const cl_ptr_vector_t *p_tbl;
220219820Sjeff	const osm_port_t *p_port = NULL;
221219820Sjeff
222219820Sjeff	if (p_gid == NULL) {
223219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7505: "
224219820Sjeff			"Provided output GID is NULL\n");
225219820Sjeff		return (IB_INVALID_PARAMETER);
226219820Sjeff	}
227219820Sjeff
228219820Sjeff	/* Find the port gid of the request in the subnet */
229219820Sjeff	p_tbl = &p_subn->port_lid_tbl;
230219820Sjeff
231219820Sjeff	CL_ASSERT(cl_ptr_vector_get_size(p_tbl) < 0x10000);
232219820Sjeff
233219820Sjeff	if ((uint16_t) cl_ptr_vector_get_size(p_tbl) >
234219820Sjeff	    cl_ntoh16(p_mad_addr->dest_lid)) {
235219820Sjeff		p_port =
236219820Sjeff		    cl_ptr_vector_get(p_tbl, cl_ntoh16(p_mad_addr->dest_lid));
237219820Sjeff		if (p_port == NULL) {
238219820Sjeff			OSM_LOG(p_log, OSM_LOG_DEBUG,
239219820Sjeff				"Did not find any port with LID: %u\n",
240219820Sjeff				cl_ntoh16(p_mad_addr->dest_lid));
241219820Sjeff			return (IB_INVALID_PARAMETER);
242219820Sjeff		}
243219820Sjeff		p_gid->unicast.interface_id = p_port->p_physp->port_guid;
244219820Sjeff		p_gid->unicast.prefix = p_subn->opt.subnet_prefix;
245219820Sjeff	} else {
246219820Sjeff		/* The dest_lid is not in the subnet table - this is an error */
247219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7501: "
248219820Sjeff			"LID is out of range: %u\n",
249219820Sjeff			cl_ntoh16(p_mad_addr->dest_lid));
250219820Sjeff		return (IB_INVALID_PARAMETER);
251219820Sjeff	}
252219820Sjeff
253219820Sjeff	return (IB_SUCCESS);
254219820Sjeff}
255219820Sjeff
256219820Sjeff/**********************************************************************
257219820Sjeff **********************************************************************/
258219820Sjeffosm_physp_t *osm_get_physp_by_mad_addr(IN osm_log_t * p_log,
259219820Sjeff				       IN const osm_subn_t * p_subn,
260219820Sjeff				       IN osm_mad_addr_t * p_mad_addr)
261219820Sjeff{
262219820Sjeff	const cl_ptr_vector_t *p_port_lid_tbl;
263219820Sjeff	osm_port_t *p_port = NULL;
264219820Sjeff	osm_physp_t *p_physp = NULL;
265219820Sjeff
266219820Sjeff	/* Find the port gid of the request in the subnet */
267219820Sjeff	p_port_lid_tbl = &p_subn->port_lid_tbl;
268219820Sjeff
269219820Sjeff	CL_ASSERT(cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000);
270219820Sjeff
271219820Sjeff	if ((uint16_t) cl_ptr_vector_get_size(p_port_lid_tbl) >
272219820Sjeff	    cl_ntoh16(p_mad_addr->dest_lid)) {
273219820Sjeff		p_port =
274219820Sjeff		    cl_ptr_vector_get(p_port_lid_tbl,
275219820Sjeff				      cl_ntoh16(p_mad_addr->dest_lid));
276219820Sjeff		if (p_port == NULL) {
277219820Sjeff			/* The port is not in the port_lid table - this is an error */
278219820Sjeff			OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7502: "
279219820Sjeff				"Cannot locate port object by lid: %u\n",
280219820Sjeff				cl_ntoh16(p_mad_addr->dest_lid));
281219820Sjeff
282219820Sjeff			goto Exit;
283219820Sjeff		}
284219820Sjeff		p_physp = p_port->p_physp;
285219820Sjeff	} else {
286219820Sjeff		/* The dest_lid is not in the subnet table - this is an error */
287219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7503: "
288219820Sjeff			"Lid is out of range: %u\n",
289219820Sjeff			cl_ntoh16(p_mad_addr->dest_lid));
290219820Sjeff	}
291219820Sjeff
292219820SjeffExit:
293219820Sjeff	return p_physp;
294219820Sjeff}
295219820Sjeff
296219820Sjeff/**********************************************************************
297219820Sjeff **********************************************************************/
298219820Sjeffosm_port_t *osm_get_port_by_mad_addr(IN osm_log_t * p_log,
299219820Sjeff				     IN const osm_subn_t * p_subn,
300219820Sjeff				     IN osm_mad_addr_t * p_mad_addr)
301219820Sjeff{
302219820Sjeff	const cl_ptr_vector_t *p_port_lid_tbl;
303219820Sjeff	osm_port_t *p_port = NULL;
304219820Sjeff
305219820Sjeff	/* Find the port gid of the request in the subnet */
306219820Sjeff	p_port_lid_tbl = &p_subn->port_lid_tbl;
307219820Sjeff
308219820Sjeff	CL_ASSERT(cl_ptr_vector_get_size(p_port_lid_tbl) < 0x10000);
309219820Sjeff
310219820Sjeff	if ((uint16_t) cl_ptr_vector_get_size(p_port_lid_tbl) >
311219820Sjeff	    cl_ntoh16(p_mad_addr->dest_lid)) {
312219820Sjeff		p_port =
313219820Sjeff		    cl_ptr_vector_get(p_port_lid_tbl,
314219820Sjeff				      cl_ntoh16(p_mad_addr->dest_lid));
315219820Sjeff	} else {
316219820Sjeff		/* The dest_lid is not in the subnet table - this is an error */
317219820Sjeff		OSM_LOG(p_log, OSM_LOG_ERROR, "ERR 7504: "
318219820Sjeff			"Lid is out of range: %u\n",
319219820Sjeff			cl_ntoh16(p_mad_addr->dest_lid));
320219820Sjeff	}
321219820Sjeff
322219820Sjeff	return p_port;
323219820Sjeff}
324219820Sjeff
325219820Sjeff/**********************************************************************
326219820Sjeff **********************************************************************/
327219820Sjeffosm_switch_t *osm_get_switch_by_guid(IN const osm_subn_t * p_subn,
328219820Sjeff				     IN uint64_t guid)
329219820Sjeff{
330219820Sjeff	osm_switch_t *p_switch;
331219820Sjeff
332219820Sjeff	p_switch = (osm_switch_t *) cl_qmap_get(&(p_subn->sw_guid_tbl), guid);
333219820Sjeff	if (p_switch == (osm_switch_t *) cl_qmap_end(&(p_subn->sw_guid_tbl)))
334219820Sjeff		p_switch = NULL;
335219820Sjeff	return p_switch;
336219820Sjeff}
337219820Sjeff
338219820Sjeff/**********************************************************************
339219820Sjeff **********************************************************************/
340219820Sjeffosm_node_t *osm_get_node_by_guid(IN osm_subn_t const *p_subn, IN uint64_t guid)
341219820Sjeff{
342219820Sjeff	osm_node_t *p_node;
343219820Sjeff
344219820Sjeff	p_node = (osm_node_t *) cl_qmap_get(&(p_subn->node_guid_tbl), guid);
345219820Sjeff	if (p_node == (osm_node_t *) cl_qmap_end(&(p_subn->node_guid_tbl)))
346219820Sjeff		p_node = NULL;
347219820Sjeff	return p_node;
348219820Sjeff}
349219820Sjeff
350219820Sjeff/**********************************************************************
351219820Sjeff **********************************************************************/
352219820Sjeffosm_port_t *osm_get_port_by_guid(IN osm_subn_t const *p_subn, IN ib_net64_t guid)
353219820Sjeff{
354219820Sjeff	osm_port_t *p_port;
355219820Sjeff
356219820Sjeff	p_port = (osm_port_t *) cl_qmap_get(&(p_subn->port_guid_tbl), guid);
357219820Sjeff	if (p_port == (osm_port_t *) cl_qmap_end(&(p_subn->port_guid_tbl)))
358219820Sjeff		p_port = NULL;
359219820Sjeff	return p_port;
360219820Sjeff}
361219820Sjeff
362219820Sjeff/**********************************************************************
363219820Sjeff **********************************************************************/
364219820Sjeffstatic void subn_set_default_qos_options(IN osm_qos_options_t * opt)
365219820Sjeff{
366219820Sjeff	opt->max_vls = OSM_DEFAULT_QOS_MAX_VLS;
367219820Sjeff	opt->high_limit = OSM_DEFAULT_QOS_HIGH_LIMIT;
368219820Sjeff	opt->vlarb_high = OSM_DEFAULT_QOS_VLARB_HIGH;
369219820Sjeff	opt->vlarb_low = OSM_DEFAULT_QOS_VLARB_LOW;
370219820Sjeff	opt->sl2vl = OSM_DEFAULT_QOS_SL2VL;
371219820Sjeff}
372219820Sjeff
373219820Sjeffstatic void subn_init_qos_options(IN osm_qos_options_t * opt)
374219820Sjeff{
375219820Sjeff	opt->max_vls = 0;
376219820Sjeff	opt->high_limit = -1;
377219820Sjeff	opt->vlarb_high = NULL;
378219820Sjeff	opt->vlarb_low = NULL;
379219820Sjeff	opt->sl2vl = NULL;
380219820Sjeff}
381219820Sjeff
382219820Sjeff/**********************************************************************
383219820Sjeff **********************************************************************/
384219820Sjeffvoid osm_subn_set_default_opt(IN osm_subn_opt_t * const p_opt)
385219820Sjeff{
386219820Sjeff	memset(p_opt, 0, sizeof(osm_subn_opt_t));
387219820Sjeff	p_opt->guid = 0;
388219820Sjeff	p_opt->m_key = OSM_DEFAULT_M_KEY;
389219820Sjeff	p_opt->sm_key = OSM_DEFAULT_SM_KEY;
390219820Sjeff	p_opt->sa_key = OSM_DEFAULT_SA_KEY;
391219820Sjeff	p_opt->subnet_prefix = IB_DEFAULT_SUBNET_PREFIX;
392219820Sjeff	p_opt->m_key_lease_period = 0;
393219820Sjeff	p_opt->sweep_interval = OSM_DEFAULT_SWEEP_INTERVAL_SECS;
394219820Sjeff	p_opt->max_wire_smps = OSM_DEFAULT_SMP_MAX_ON_WIRE;
395219820Sjeff	p_opt->console = OSM_DEFAULT_CONSOLE;
396219820Sjeff	p_opt->console_port = OSM_DEFAULT_CONSOLE_PORT;
397219820Sjeff	p_opt->transaction_timeout = OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
398219820Sjeff	/* by default we will consider waiting for 50x transaction timeout normal */
399219820Sjeff	p_opt->max_msg_fifo_timeout = 50 * OSM_DEFAULT_TRANS_TIMEOUT_MILLISEC;
400219820Sjeff	p_opt->sm_priority = OSM_DEFAULT_SM_PRIORITY;
401219820Sjeff	p_opt->lmc = OSM_DEFAULT_LMC;
402219820Sjeff	p_opt->lmc_esp0 = FALSE;
403219820Sjeff	p_opt->max_op_vls = OSM_DEFAULT_MAX_OP_VLS;
404219820Sjeff	p_opt->force_link_speed = 15;
405219820Sjeff	p_opt->reassign_lids = FALSE;
406219820Sjeff	p_opt->ignore_other_sm = FALSE;
407219820Sjeff	p_opt->single_thread = FALSE;
408219820Sjeff	p_opt->disable_multicast = FALSE;
409219820Sjeff	p_opt->force_log_flush = FALSE;
410219820Sjeff	p_opt->subnet_timeout = OSM_DEFAULT_SUBNET_TIMEOUT;
411219820Sjeff	p_opt->packet_life_time = OSM_DEFAULT_SWITCH_PACKET_LIFE;
412219820Sjeff	p_opt->vl_stall_count = OSM_DEFAULT_VL_STALL_COUNT;
413219820Sjeff	p_opt->leaf_vl_stall_count = OSM_DEFAULT_LEAF_VL_STALL_COUNT;
414219820Sjeff	p_opt->head_of_queue_lifetime = OSM_DEFAULT_HEAD_OF_QUEUE_LIFE;
415219820Sjeff	p_opt->leaf_head_of_queue_lifetime =
416219820Sjeff	    OSM_DEFAULT_LEAF_HEAD_OF_QUEUE_LIFE;
417219820Sjeff	p_opt->local_phy_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
418219820Sjeff	p_opt->overrun_errors_threshold = OSM_DEFAULT_ERROR_THRESHOLD;
419219820Sjeff	p_opt->sminfo_polling_timeout =
420219820Sjeff	    OSM_SM_DEFAULT_POLLING_TIMEOUT_MILLISECS;
421219820Sjeff	p_opt->polling_retry_number = OSM_SM_DEFAULT_POLLING_RETRY_NUMBER;
422219820Sjeff	p_opt->force_heavy_sweep = FALSE;
423219820Sjeff	p_opt->log_flags = OSM_LOG_DEFAULT_LEVEL;
424219820Sjeff	p_opt->honor_guid2lid_file = FALSE;
425219820Sjeff	p_opt->daemon = FALSE;
426219820Sjeff	p_opt->sm_inactive = FALSE;
427219820Sjeff	p_opt->babbling_port_policy = FALSE;
428219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
429219820Sjeff	p_opt->perfmgr = FALSE;
430219820Sjeff	p_opt->perfmgr_redir = TRUE;
431219820Sjeff	p_opt->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
432219820Sjeff	p_opt->perfmgr_max_outstanding_queries =
433219820Sjeff	    OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
434219820Sjeff	p_opt->event_db_dump_file = NULL; /* use default */
435219820Sjeff#endif				/* ENABLE_OSM_PERF_MGR */
436219820Sjeff
437219820Sjeff	p_opt->event_plugin_name = NULL;
438219820Sjeff	p_opt->node_name_map_name = NULL;
439219820Sjeff
440219820Sjeff	p_opt->dump_files_dir = getenv("OSM_TMP_DIR");
441219820Sjeff	if (!p_opt->dump_files_dir || !(*p_opt->dump_files_dir))
442219820Sjeff		p_opt->dump_files_dir = OSM_DEFAULT_TMP_DIR;
443219820Sjeff
444219820Sjeff	p_opt->log_file = OSM_DEFAULT_LOG_FILE;
445219820Sjeff	p_opt->log_max_size = 0;
446219820Sjeff	p_opt->partition_config_file = OSM_DEFAULT_PARTITION_CONFIG_FILE;
447219820Sjeff	p_opt->no_partition_enforcement = FALSE;
448219820Sjeff	p_opt->qos = FALSE;
449219820Sjeff	p_opt->qos_policy_file = OSM_DEFAULT_QOS_POLICY_FILE;
450219820Sjeff	p_opt->accum_log_file = TRUE;
451219820Sjeff	p_opt->port_prof_ignore_file = NULL;
452219820Sjeff	p_opt->port_profile_switch_nodes = FALSE;
453219820Sjeff	p_opt->sweep_on_trap = TRUE;
454219820Sjeff	p_opt->use_ucast_cache = FALSE;
455219820Sjeff	p_opt->routing_engine_names = NULL;
456219820Sjeff	p_opt->connect_roots = FALSE;
457219820Sjeff	p_opt->lid_matrix_dump_file = NULL;
458219820Sjeff	p_opt->lfts_file = NULL;
459219820Sjeff	p_opt->root_guid_file = NULL;
460219820Sjeff	p_opt->cn_guid_file = NULL;
461219820Sjeff	p_opt->ids_guid_file = NULL;
462219820Sjeff	p_opt->guid_routing_order_file = NULL;
463219820Sjeff	p_opt->sa_db_file = NULL;
464219820Sjeff	p_opt->exit_on_fatal = TRUE;
465219820Sjeff	p_opt->enable_quirks = FALSE;
466219820Sjeff	p_opt->no_clients_rereg = FALSE;
467219820Sjeff	p_opt->prefix_routes_file = OSM_DEFAULT_PREFIX_ROUTES_FILE;
468219820Sjeff	p_opt->consolidate_ipv6_snm_req = FALSE;
469219820Sjeff	subn_init_qos_options(&p_opt->qos_options);
470219820Sjeff	subn_init_qos_options(&p_opt->qos_ca_options);
471219820Sjeff	subn_init_qos_options(&p_opt->qos_sw0_options);
472219820Sjeff	subn_init_qos_options(&p_opt->qos_swe_options);
473219820Sjeff	subn_init_qos_options(&p_opt->qos_rtr_options);
474219820Sjeff}
475219820Sjeff
476219820Sjeff/**********************************************************************
477219820Sjeff **********************************************************************/
478219820Sjeffstatic void log_report(const char *fmt, ...)
479219820Sjeff{
480219820Sjeff	char buf[128];
481219820Sjeff	va_list args;
482219820Sjeff	va_start(args, fmt);
483219820Sjeff	vsnprintf(buf, sizeof(buf), fmt, args);
484219820Sjeff	va_end(args);
485254123Sjeff	printf("%s", buf);
486219820Sjeff	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
487219820Sjeff}
488219820Sjeff
489219820Sjeffstatic void log_config_value(char *name, const char *fmt, ...)
490219820Sjeff{
491219820Sjeff	char buf[128];
492219820Sjeff	va_list args;
493219820Sjeff	unsigned n;
494219820Sjeff	va_start(args, fmt);
495219820Sjeff	n = snprintf(buf, sizeof(buf), " Loading Cached Option:%s = ", name);
496219820Sjeff	if (n > sizeof(buf))
497219820Sjeff		n = sizeof(buf);
498219820Sjeff	n += vsnprintf(buf + n, sizeof(buf) - n, fmt, args);
499219820Sjeff	if (n > sizeof(buf))
500219820Sjeff		n = sizeof(buf);
501219820Sjeff	snprintf(buf + n, sizeof(buf) - n, "\n");
502219820Sjeff	va_end(args);
503254123Sjeff	printf("%s", buf);
504219820Sjeff	cl_log_event("OpenSM", CL_LOG_INFO, buf, NULL, 0);
505219820Sjeff}
506219820Sjeff
507219820Sjeffstatic void
508219820Sjeffopts_unpack_net64(IN char *p_req_key,
509219820Sjeff		  IN char *p_key, IN char *p_val_str, IN uint64_t * p_val)
510219820Sjeff{
511219820Sjeff	if (!strcmp(p_req_key, p_key)) {
512219820Sjeff		uint64_t val = strtoull(p_val_str, NULL, 0);
513219820Sjeff		if (cl_hton64(val) != *p_val) {
514219820Sjeff			log_config_value(p_key, "0x%016" PRIx64, val);
515219820Sjeff			*p_val = cl_ntoh64(val);
516219820Sjeff		}
517219820Sjeff	}
518219820Sjeff}
519219820Sjeff
520219820Sjeff/**********************************************************************
521219820Sjeff **********************************************************************/
522219820Sjeffstatic void
523219820Sjeffopts_unpack_uint32(IN char *p_req_key,
524219820Sjeff		   IN char *p_key, IN char *p_val_str, IN uint32_t * p_val)
525219820Sjeff{
526219820Sjeff	if (!strcmp(p_req_key, p_key)) {
527219820Sjeff		uint32_t val = strtoul(p_val_str, NULL, 0);
528219820Sjeff		if (val != *p_val) {
529219820Sjeff			log_config_value(p_key, "%u", val);
530219820Sjeff			*p_val = val;
531219820Sjeff		}
532219820Sjeff	}
533219820Sjeff}
534219820Sjeff
535219820Sjeff/**********************************************************************
536219820Sjeff **********************************************************************/
537219820Sjeffstatic void
538219820Sjeffopts_unpack_int32(IN char *p_req_key,
539219820Sjeff		  IN char *p_key, IN char *p_val_str, IN int32_t * p_val)
540219820Sjeff{
541219820Sjeff	if (!strcmp(p_req_key, p_key)) {
542219820Sjeff		int32_t val = strtol(p_val_str, NULL, 0);
543219820Sjeff		if (val != *p_val) {
544219820Sjeff			log_config_value(p_key, "%d", val);
545219820Sjeff			*p_val = val;
546219820Sjeff		}
547219820Sjeff	}
548219820Sjeff}
549219820Sjeff
550219820Sjeff/**********************************************************************
551219820Sjeff **********************************************************************/
552219820Sjeffstatic void
553219820Sjeffopts_unpack_uint16(IN char *p_req_key,
554219820Sjeff		   IN char *p_key, IN char *p_val_str, IN uint16_t * p_val)
555219820Sjeff{
556219820Sjeff	if (!strcmp(p_req_key, p_key)) {
557219820Sjeff		uint16_t val = (uint16_t) strtoul(p_val_str, NULL, 0);
558219820Sjeff		if (val != *p_val) {
559219820Sjeff			log_config_value(p_key, "%u", val);
560219820Sjeff			*p_val = val;
561219820Sjeff		}
562219820Sjeff	}
563219820Sjeff}
564219820Sjeff
565219820Sjeff/**********************************************************************
566219820Sjeff **********************************************************************/
567219820Sjeffstatic void
568219820Sjeffopts_unpack_net16(IN char *p_req_key,
569219820Sjeff		  IN char *p_key, IN char *p_val_str, IN uint16_t * p_val)
570219820Sjeff{
571219820Sjeff	if (!strcmp(p_req_key, p_key)) {
572219820Sjeff		uint32_t val;
573219820Sjeff		val = strtoul(p_val_str, NULL, 0);
574219820Sjeff		CL_ASSERT(val < 0x10000);
575219820Sjeff		if (cl_hton32(val) != *p_val) {
576219820Sjeff			log_config_value(p_key, "0x%04x", val);
577219820Sjeff			*p_val = cl_hton16((uint16_t) val);
578219820Sjeff		}
579219820Sjeff	}
580219820Sjeff}
581219820Sjeff
582219820Sjeff/**********************************************************************
583219820Sjeff **********************************************************************/
584219820Sjeffstatic void
585219820Sjeffopts_unpack_uint8(IN char *p_req_key,
586219820Sjeff		  IN char *p_key, IN char *p_val_str, IN uint8_t * p_val)
587219820Sjeff{
588219820Sjeff	if (!strcmp(p_req_key, p_key)) {
589219820Sjeff		uint32_t val;
590219820Sjeff		val = strtoul(p_val_str, NULL, 0);
591219820Sjeff		CL_ASSERT(val < 0x100);
592219820Sjeff		if (val != *p_val) {
593219820Sjeff			log_config_value(p_key, "%u", val);
594219820Sjeff			*p_val = (uint8_t) val;
595219820Sjeff		}
596219820Sjeff	}
597219820Sjeff}
598219820Sjeff
599219820Sjeff/**********************************************************************
600219820Sjeff **********************************************************************/
601219820Sjeffstatic void
602219820Sjeffopts_unpack_boolean(IN char *p_req_key,
603219820Sjeff		    IN char *p_key, IN char *p_val_str, IN boolean_t * p_val)
604219820Sjeff{
605219820Sjeff	if (!strcmp(p_req_key, p_key) && p_val_str) {
606219820Sjeff		boolean_t val;
607219820Sjeff		if (strcmp("TRUE", p_val_str))
608219820Sjeff			val = FALSE;
609219820Sjeff		else
610219820Sjeff			val = TRUE;
611219820Sjeff
612219820Sjeff		if (val != *p_val) {
613219820Sjeff			log_config_value(p_key, "%s", p_val_str);
614219820Sjeff			*p_val = val;
615219820Sjeff		}
616219820Sjeff	}
617219820Sjeff}
618219820Sjeff
619219820Sjeff/**********************************************************************
620219820Sjeff **********************************************************************/
621219820Sjeffstatic void
622219820Sjeffopts_unpack_charp(IN char *p_req_key,
623219820Sjeff		  IN char *p_key, IN char *p_val_str, IN char **p_val)
624219820Sjeff{
625219820Sjeff	if (!strcmp(p_req_key, p_key) && p_val_str) {
626219820Sjeff		const char *current_str = *p_val ? *p_val : null_str ;
627219820Sjeff		if (strcmp(p_val_str, current_str)) {
628219820Sjeff			log_config_value(p_key, "%s", p_val_str);
629219820Sjeff			/* special case the "(null)" string */
630219820Sjeff			if (strcmp(null_str, p_val_str) == 0) {
631219820Sjeff				*p_val = NULL;
632219820Sjeff			} else {
633219820Sjeff				/*
634219820Sjeff				  Ignore the possible memory leak here;
635219820Sjeff				  the pointer may be to a static default.
636219820Sjeff				*/
637219820Sjeff				*p_val = strdup(p_val_str);
638219820Sjeff			}
639219820Sjeff		}
640219820Sjeff	}
641219820Sjeff}
642219820Sjeff
643219820Sjeff/**********************************************************************
644219820Sjeff **********************************************************************/
645219820Sjeffstatic char *clean_val(char *val)
646219820Sjeff{
647219820Sjeff	char *p = val;
648219820Sjeff	/* clean leading spaces */
649219820Sjeff	while (isspace(*p))
650219820Sjeff		p++;
651219820Sjeff	val = p;
652219820Sjeff	if (!*val)
653219820Sjeff		return val;
654219820Sjeff	/* clean trailing spaces */
655219820Sjeff	p = val + strlen(val) - 1;
656219820Sjeff	while (p > val && isspace(*p))
657219820Sjeff		p--;
658219820Sjeff	p[1] = '\0';
659219820Sjeff	/* clean quotas */
660219820Sjeff	if ((*val == '\"' && *p == '\"') || (*val == '\'' && *p == '\'')) {
661219820Sjeff		val++;
662219820Sjeff		p--;
663219820Sjeff	}
664219820Sjeff	return val;
665219820Sjeff}
666219820Sjeff
667219820Sjeff/**********************************************************************
668219820Sjeff **********************************************************************/
669219820Sjeffstatic void
670219820Sjeffsubn_parse_qos_options(IN const char *prefix,
671219820Sjeff		       IN char *p_key,
672219820Sjeff		       IN char *p_val_str, IN osm_qos_options_t * opt)
673219820Sjeff{
674219820Sjeff	char name[256];
675219820Sjeff
676219820Sjeff	snprintf(name, sizeof(name), "%s_max_vls", prefix);
677219820Sjeff	opts_unpack_uint32(name, p_key, p_val_str, &opt->max_vls);
678219820Sjeff	snprintf(name, sizeof(name), "%s_high_limit", prefix);
679219820Sjeff	opts_unpack_int32(name, p_key, p_val_str, &opt->high_limit);
680219820Sjeff	snprintf(name, sizeof(name), "%s_vlarb_high", prefix);
681219820Sjeff	opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_high);
682219820Sjeff	snprintf(name, sizeof(name), "%s_vlarb_low", prefix);
683219820Sjeff	opts_unpack_charp(name, p_key, p_val_str, &opt->vlarb_low);
684219820Sjeff	snprintf(name, sizeof(name), "%s_sl2vl", prefix);
685219820Sjeff	opts_unpack_charp(name, p_key, p_val_str, &opt->sl2vl);
686219820Sjeff}
687219820Sjeff
688219820Sjeffstatic int
689219820Sjeffsubn_dump_qos_options(FILE * file,
690219820Sjeff		      const char *set_name,
691219820Sjeff		      const char *prefix, osm_qos_options_t * opt)
692219820Sjeff{
693219820Sjeff	return fprintf(file, "# %s\n"
694219820Sjeff		       "%s_max_vls %u\n"
695219820Sjeff		       "%s_high_limit %d\n"
696219820Sjeff		       "%s_vlarb_high %s\n"
697219820Sjeff		       "%s_vlarb_low %s\n"
698219820Sjeff		       "%s_sl2vl %s\n",
699219820Sjeff		       set_name,
700219820Sjeff		       prefix, opt->max_vls,
701219820Sjeff		       prefix, opt->high_limit,
702219820Sjeff		       prefix, opt->vlarb_high,
703219820Sjeff		       prefix, opt->vlarb_low, prefix, opt->sl2vl);
704219820Sjeff}
705219820Sjeff
706219820Sjeff/**********************************************************************
707219820Sjeff **********************************************************************/
708219820Sjeffstatic ib_api_status_t
709219820Sjeffappend_prefix_route(IN osm_subn_t * const p_subn, uint64_t prefix, uint64_t guid)
710219820Sjeff{
711219820Sjeff	osm_prefix_route_t *route;
712219820Sjeff
713219820Sjeff	route = malloc(sizeof *route);
714219820Sjeff	if (! route) {
715219820Sjeff		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR, "out of memory");
716219820Sjeff		return IB_ERROR;
717219820Sjeff	}
718219820Sjeff
719219820Sjeff	route->prefix = cl_hton64(prefix);
720219820Sjeff	route->guid = cl_hton64(guid);
721219820Sjeff	cl_qlist_insert_tail(&p_subn->prefix_routes_list, &route->list_item);
722219820Sjeff	return IB_SUCCESS;
723219820Sjeff}
724219820Sjeff
725219820Sjeffstatic ib_api_status_t
726219820Sjeffosm_parse_prefix_routes_file(IN osm_subn_t * const p_subn)
727219820Sjeff{
728219820Sjeff	osm_log_t *log = &p_subn->p_osm->log;
729219820Sjeff	FILE *fp;
730219820Sjeff	char buf[1024];
731219820Sjeff	int line = 0;
732219820Sjeff	int errors = 0;
733219820Sjeff
734219820Sjeff	while (!cl_is_qlist_empty(&p_subn->prefix_routes_list)) {
735219820Sjeff		cl_list_item_t *item = cl_qlist_remove_head(&p_subn->prefix_routes_list);
736219820Sjeff		free(item);
737219820Sjeff	}
738219820Sjeff
739219820Sjeff	fp = fopen(p_subn->opt.prefix_routes_file, "r");
740219820Sjeff	if (! fp) {
741219820Sjeff		if (errno == ENOENT)
742219820Sjeff			return IB_SUCCESS;
743219820Sjeff
744219820Sjeff		OSM_LOG(log, OSM_LOG_ERROR, "fopen(%s) failed: %s",
745219820Sjeff			p_subn->opt.prefix_routes_file, strerror(errno));
746219820Sjeff		return IB_ERROR;
747219820Sjeff	}
748219820Sjeff
749219820Sjeff	while (fgets(buf, sizeof buf, fp) != NULL) {
750219820Sjeff		char *p_prefix, *p_guid, *p_extra, *p_last, *p_end;
751219820Sjeff		uint64_t prefix, guid;
752219820Sjeff
753219820Sjeff		line++;
754219820Sjeff		if (errors > 10)
755219820Sjeff			break;
756219820Sjeff
757219820Sjeff		p_prefix = strtok_r(buf, " \t\n", &p_last);
758219820Sjeff		if (! p_prefix)
759219820Sjeff			continue; /* ignore blank lines */
760219820Sjeff
761219820Sjeff		if (*p_prefix == '#')
762219820Sjeff			continue; /* ignore comment lines */
763219820Sjeff
764219820Sjeff		p_guid = strtok_r(NULL, " \t\n", &p_last);
765219820Sjeff		if (! p_guid) {
766219820Sjeff			OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: missing GUID\n",
767219820Sjeff				p_subn->opt.prefix_routes_file, line);
768219820Sjeff			errors++;
769219820Sjeff			continue;
770219820Sjeff		}
771219820Sjeff
772219820Sjeff		p_extra = strtok_r(NULL, " \t\n", &p_last);
773219820Sjeff		if (p_extra && *p_extra != '#') {
774219820Sjeff			OSM_LOG(log, OSM_LOG_INFO, "%s:%d: extra tokens ignored\n",
775219820Sjeff				p_subn->opt.prefix_routes_file, line);
776219820Sjeff		}
777219820Sjeff
778219820Sjeff		if (strcmp(p_prefix, "*") == 0)
779219820Sjeff			prefix = 0;
780219820Sjeff		else {
781219820Sjeff			prefix = strtoull(p_prefix, &p_end, 16);
782219820Sjeff			if (*p_end != '\0') {
783219820Sjeff				OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal prefix: %s\n",
784219820Sjeff					p_subn->opt.prefix_routes_file, line, p_prefix);
785219820Sjeff				errors++;
786219820Sjeff				continue;
787219820Sjeff			}
788219820Sjeff		}
789219820Sjeff
790219820Sjeff		if (strcmp(p_guid, "*") == 0)
791219820Sjeff			guid = 0;
792219820Sjeff		else {
793219820Sjeff			guid = strtoull(p_guid, &p_end, 16);
794219820Sjeff			if (*p_end != '\0' && *p_end != '#') {
795219820Sjeff				OSM_LOG(log, OSM_LOG_ERROR, "%s:%d: illegal GUID: %s\n",
796219820Sjeff					p_subn->opt.prefix_routes_file, line, p_guid);
797219820Sjeff				errors++;
798219820Sjeff				continue;
799219820Sjeff			}
800219820Sjeff		}
801219820Sjeff
802219820Sjeff		if (append_prefix_route(p_subn, prefix, guid) != IB_SUCCESS) {
803219820Sjeff			errors++;
804219820Sjeff			break;
805219820Sjeff		}
806219820Sjeff	}
807219820Sjeff
808219820Sjeff	fclose(fp);
809219820Sjeff	return (errors == 0) ? IB_SUCCESS : IB_ERROR;
810219820Sjeff}
811219820Sjeff
812219820Sjeff/**********************************************************************
813219820Sjeff **********************************************************************/
814219820Sjeffstatic void subn_verify_max_vls(unsigned *max_vls, const char *prefix, unsigned dflt)
815219820Sjeff{
816219820Sjeff	if (!(*max_vls) || *max_vls > 15) {
817219820Sjeff		log_report(" Invalid Cached Option: %s_max_vls=%u: "
818219820Sjeff			   "Using Default = %u\n", prefix, *max_vls, dflt);
819219820Sjeff		*max_vls = dflt;
820219820Sjeff	}
821219820Sjeff}
822219820Sjeff
823219820Sjeffstatic void subn_verify_high_limit(int *high_limit, const char *prefix, int dflt)
824219820Sjeff{
825219820Sjeff	if (*high_limit < 0 || *high_limit > 255) {
826219820Sjeff		log_report(" Invalid Cached Option: %s_high_limit=%d: "
827219820Sjeff			   "Using Default: %d\n", prefix, *high_limit, dflt);
828219820Sjeff		*high_limit = dflt;
829219820Sjeff	}
830219820Sjeff}
831219820Sjeff
832219820Sjeffstatic void subn_verify_vlarb(char **vlarb, const char *prefix,
833219820Sjeff			      const char *suffix, char *dflt)
834219820Sjeff{
835219820Sjeff	char *str, *tok, *end, *ptr;
836219820Sjeff	int count = 0;
837219820Sjeff
838219820Sjeff	if (*vlarb == NULL) {
839219820Sjeff		log_report(" Invalid Cached Option: %s_vlarb_%s: "
840219820Sjeff		"Using Default\n", prefix, suffix);
841219820Sjeff		*vlarb = dflt;
842219820Sjeff		return;
843219820Sjeff	}
844219820Sjeff
845219820Sjeff	str = strdup(*vlarb);
846219820Sjeff
847219820Sjeff	tok = strtok_r(str, ",\n", &ptr);
848219820Sjeff	while (tok) {
849219820Sjeff		char *vl_str, *weight_str;
850219820Sjeff
851219820Sjeff		vl_str = tok;
852219820Sjeff		weight_str = strchr(tok, ':');
853219820Sjeff
854219820Sjeff		if (weight_str) {
855219820Sjeff			long vl, weight;
856219820Sjeff
857219820Sjeff			*weight_str = '\0';
858219820Sjeff			weight_str++;
859219820Sjeff
860219820Sjeff			vl = strtol(vl_str, &end, 0);
861219820Sjeff
862219820Sjeff			if (*end)
863219820Sjeff				log_report(" Warning: Cached Option "
864219820Sjeff					   "%s_vlarb_%s:vl=%s"
865219820Sjeff					   " improperly formatted\n",
866219820Sjeff					   prefix, suffix, vl_str);
867219820Sjeff			else if (vl < 0 || vl > 14)
868219820Sjeff				log_report(" Warning: Cached Option "
869219820Sjeff					   "%s_vlarb_%s:vl=%ld out of range\n",
870219820Sjeff					   prefix, suffix, vl);
871219820Sjeff
872219820Sjeff			weight = strtol(weight_str, &end, 0);
873219820Sjeff
874219820Sjeff			if (*end)
875219820Sjeff				log_report(" Warning: Cached Option "
876219820Sjeff					   "%s_vlarb_%s:weight=%s "
877219820Sjeff					   "improperly formatted\n",
878219820Sjeff					   prefix, suffix, weight_str);
879219820Sjeff			else if (weight < 0 || weight > 255)
880219820Sjeff				log_report(" Warning: Cached Option "
881219820Sjeff					   "%s_vlarb_%s:weight=%ld "
882219820Sjeff					   "out of range\n",
883219820Sjeff					   prefix, suffix, weight);
884219820Sjeff		} else
885219820Sjeff			log_report(" Warning: Cached Option "
886219820Sjeff				   "%s_vlarb_%s:vl:weight=%s "
887219820Sjeff				   "improperly formatted\n",
888219820Sjeff				   prefix, suffix, tok);
889219820Sjeff
890219820Sjeff		count++;
891219820Sjeff		tok = strtok_r(NULL, ",\n", &ptr);
892219820Sjeff	}
893219820Sjeff
894219820Sjeff	if (count > 64)
895219820Sjeff		log_report(" Warning: Cached Option %s_vlarb_%s: > 64 listed:"
896219820Sjeff			   " excess vl:weight pairs will be dropped\n",
897219820Sjeff			   prefix, suffix);
898219820Sjeff
899219820Sjeff	free(str);
900219820Sjeff}
901219820Sjeff
902219820Sjeffstatic void subn_verify_sl2vl(char **sl2vl, const char *prefix, char *dflt)
903219820Sjeff{
904219820Sjeff	char *str, *tok, *end, *ptr;
905219820Sjeff	int count = 0;
906219820Sjeff
907219820Sjeff	if (*sl2vl == NULL) {
908219820Sjeff		log_report(" Invalid Cached Option: %s_sl2vl: Using Default\n",
909219820Sjeff			   prefix);
910219820Sjeff		*sl2vl = dflt;
911219820Sjeff		return;
912219820Sjeff	}
913219820Sjeff
914219820Sjeff	str = strdup(*sl2vl);
915219820Sjeff
916219820Sjeff	tok = strtok_r(str, ",\n", &ptr);
917219820Sjeff	while (tok) {
918219820Sjeff		long vl = strtol(tok, &end, 0);
919219820Sjeff
920219820Sjeff		if (*end)
921219820Sjeff			log_report(" Warning: Cached Option %s_sl2vl:vl=%s "
922219820Sjeff				   "improperly formatted\n", prefix, tok);
923219820Sjeff		else if (vl < 0 || vl > 15)
924219820Sjeff			log_report(" Warning: Cached Option %s_sl2vl:vl=%ld "
925219820Sjeff				   "out of range\n", prefix, vl);
926219820Sjeff
927219820Sjeff		count++;
928219820Sjeff		tok = strtok_r(NULL, ",\n", &ptr);
929219820Sjeff	}
930219820Sjeff
931219820Sjeff	if (count < 16)
932219820Sjeff		log_report(" Warning: Cached Option %s_sl2vl: < 16 VLs "
933219820Sjeff			   "listed\n", prefix);
934219820Sjeff
935219820Sjeff	if (count > 16)
936219820Sjeff		log_report(" Warning: Cached Option %s_sl2vl: > 16 listed: "
937219820Sjeff			   "excess VLs will be dropped\n", prefix);
938219820Sjeff
939219820Sjeff	free(str);
940219820Sjeff}
941219820Sjeff
942219820Sjeffstatic void subn_verify_qos_set(osm_qos_options_t *set, const char *prefix,
943219820Sjeff				osm_qos_options_t *dflt)
944219820Sjeff{
945219820Sjeff	subn_verify_max_vls(&set->max_vls, prefix, dflt->max_vls);
946219820Sjeff	subn_verify_high_limit(&set->high_limit, prefix, dflt->high_limit);
947219820Sjeff	subn_verify_vlarb(&set->vlarb_low, prefix, "low", dflt->vlarb_low);
948219820Sjeff	subn_verify_vlarb(&set->vlarb_high, prefix, "high", dflt->vlarb_high);
949219820Sjeff	subn_verify_sl2vl(&set->sl2vl, prefix, dflt->sl2vl);
950219820Sjeff}
951219820Sjeff
952219820Sjeffint osm_subn_verify_config(IN osm_subn_opt_t * const p_opts)
953219820Sjeff{
954219820Sjeff	if (p_opts->lmc > 7) {
955219820Sjeff		log_report(" Invalid Cached Option Value:lmc = %u:"
956219820Sjeff			   "Using Default:%u\n", p_opts->lmc, OSM_DEFAULT_LMC);
957219820Sjeff		p_opts->lmc = OSM_DEFAULT_LMC;
958219820Sjeff	}
959219820Sjeff
960219820Sjeff	if (15 < p_opts->sm_priority) {
961219820Sjeff		log_report(" Invalid Cached Option Value:sm_priority = %u:"
962219820Sjeff			   "Using Default:%u\n",
963219820Sjeff			   p_opts->sm_priority, OSM_DEFAULT_SM_PRIORITY);
964219820Sjeff		p_opts->sm_priority = OSM_DEFAULT_SM_PRIORITY;
965219820Sjeff	}
966219820Sjeff
967219820Sjeff	if ((15 < p_opts->force_link_speed) ||
968219820Sjeff	    (p_opts->force_link_speed > 7 && p_opts->force_link_speed < 15)) {
969219820Sjeff		log_report(" Invalid Cached Option Value:force_link_speed = %u:"
970219820Sjeff			   "Using Default:%u\n", p_opts->force_link_speed,
971219820Sjeff			   IB_PORT_LINK_SPEED_ENABLED_MASK);
972219820Sjeff		p_opts->force_link_speed = IB_PORT_LINK_SPEED_ENABLED_MASK;
973219820Sjeff	}
974219820Sjeff
975219820Sjeff	if (strcmp(p_opts->console, OSM_DISABLE_CONSOLE)
976219820Sjeff	    && strcmp(p_opts->console, OSM_LOCAL_CONSOLE)
977219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
978219820Sjeff	    && strcmp(p_opts->console, OSM_LOOPBACK_CONSOLE)
979219820Sjeff	    && strcmp(p_opts->console, OSM_REMOTE_CONSOLE)
980219820Sjeff#endif
981219820Sjeff	    ) {
982219820Sjeff		log_report(" Invalid Cached Option Value:console = %s"
983219820Sjeff			   ", Using Default:%s\n",
984219820Sjeff			   p_opts->console, OSM_DEFAULT_CONSOLE);
985219820Sjeff		p_opts->console = OSM_DEFAULT_CONSOLE;
986219820Sjeff	}
987219820Sjeff
988219820Sjeff	if (p_opts->qos) {
989219820Sjeff		osm_qos_options_t dflt;
990219820Sjeff
991219820Sjeff		/* the default options in qos_options must be correct.
992219820Sjeff		 * every other one need not be, b/c those will default
993219820Sjeff		 * back to whatever is in qos_options.
994219820Sjeff		 */
995219820Sjeff
996219820Sjeff		subn_set_default_qos_options(&dflt);
997219820Sjeff
998219820Sjeff		subn_verify_qos_set(&p_opts->qos_options, "qos", &dflt);
999219820Sjeff		subn_verify_qos_set(&p_opts->qos_ca_options, "qos_ca",
1000219820Sjeff				    &p_opts->qos_options);
1001219820Sjeff		subn_verify_qos_set(&p_opts->qos_sw0_options, "qos_sw0",
1002219820Sjeff				    &p_opts->qos_options);
1003219820Sjeff		subn_verify_qos_set(&p_opts->qos_swe_options, "qos_swe",
1004219820Sjeff				    &p_opts->qos_options);
1005219820Sjeff		subn_verify_qos_set(&p_opts->qos_rtr_options, "qos_rtr",
1006219820Sjeff				    &p_opts->qos_options);
1007219820Sjeff	}
1008219820Sjeff
1009219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
1010219820Sjeff	if (p_opts->perfmgr_sweep_time_s < 1) {
1011219820Sjeff		log_report(" Invalid Cached Option Value:perfmgr_sweep_time_s "
1012219820Sjeff			   "= %u Using Default:%u\n",
1013219820Sjeff			   p_opts->perfmgr_sweep_time_s,
1014219820Sjeff			   OSM_PERFMGR_DEFAULT_SWEEP_TIME_S);
1015219820Sjeff		p_opts->perfmgr_sweep_time_s = OSM_PERFMGR_DEFAULT_SWEEP_TIME_S;
1016219820Sjeff	}
1017219820Sjeff	if (p_opts->perfmgr_max_outstanding_queries < 1) {
1018219820Sjeff		log_report(" Invalid Cached Option Value:"
1019219820Sjeff			   "perfmgr_max_outstanding_queries = %u"
1020219820Sjeff			   " Using Default:%u\n",
1021219820Sjeff			   p_opts->perfmgr_max_outstanding_queries,
1022219820Sjeff			   OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES);
1023219820Sjeff		p_opts->perfmgr_max_outstanding_queries =
1024219820Sjeff		    OSM_PERFMGR_DEFAULT_MAX_OUTSTANDING_QUERIES;
1025219820Sjeff	}
1026219820Sjeff#endif
1027219820Sjeff
1028219820Sjeff	return 0;
1029219820Sjeff}
1030219820Sjeff
1031219820Sjeff/**********************************************************************
1032219820Sjeff **********************************************************************/
1033219820Sjeffint osm_subn_parse_conf_file(char *file_name, osm_subn_opt_t * const p_opts)
1034219820Sjeff{
1035219820Sjeff	char line[1024];
1036219820Sjeff	FILE *opts_file;
1037219820Sjeff	char *p_key, *p_val;
1038219820Sjeff
1039219820Sjeff	opts_file = fopen(file_name, "r");
1040219820Sjeff	if (!opts_file) {
1041219820Sjeff		if (errno == ENOENT)
1042219820Sjeff			return 1;
1043219820Sjeff		printf("cannot open file \'%s\': %s\n",
1044219820Sjeff		       file_name, strerror(errno));
1045219820Sjeff		return -1;
1046219820Sjeff	}
1047219820Sjeff
1048219820Sjeff	printf(" Reading Cached Option File: %s\n", file_name);
1049219820Sjeff	cl_log_event("OpenSM", CL_LOG_INFO, line, NULL, 0);
1050219820Sjeff
1051219820Sjeff	p_opts->config_file = file_name;
1052219820Sjeff
1053219820Sjeff	while (fgets(line, 1023, opts_file) != NULL) {
1054219820Sjeff		/* get the first token */
1055219820Sjeff		p_key = strtok_r(line, " \t\n", &p_val);
1056219820Sjeff		if (!p_key)
1057219820Sjeff			continue;
1058219820Sjeff
1059219820Sjeff		p_val = clean_val(p_val);
1060219820Sjeff
1061219820Sjeff		opts_unpack_net64("guid", p_key, p_val, &p_opts->guid);
1062219820Sjeff
1063219820Sjeff		opts_unpack_net64("m_key", p_key, p_val, &p_opts->m_key);
1064219820Sjeff
1065219820Sjeff		opts_unpack_net64("sm_key", p_key, p_val, &p_opts->sm_key);
1066219820Sjeff
1067219820Sjeff		opts_unpack_net64("sa_key", p_key, p_val, &p_opts->sa_key);
1068219820Sjeff
1069219820Sjeff		opts_unpack_net64("subnet_prefix",
1070219820Sjeff				  p_key, p_val, &p_opts->subnet_prefix);
1071219820Sjeff
1072219820Sjeff		opts_unpack_net16("m_key_lease_period",
1073219820Sjeff				  p_key, p_val, &p_opts->m_key_lease_period);
1074219820Sjeff
1075219820Sjeff		opts_unpack_uint32("sweep_interval",
1076219820Sjeff				   p_key, p_val, &p_opts->sweep_interval);
1077219820Sjeff
1078219820Sjeff		opts_unpack_uint32("max_wire_smps",
1079219820Sjeff				   p_key, p_val, &p_opts->max_wire_smps);
1080219820Sjeff
1081219820Sjeff		opts_unpack_charp("console", p_key, p_val, &p_opts->console);
1082219820Sjeff
1083219820Sjeff		opts_unpack_uint16("console_port",
1084219820Sjeff				   p_key, p_val, &p_opts->console_port);
1085219820Sjeff
1086219820Sjeff		opts_unpack_uint32("transaction_timeout",
1087219820Sjeff				   p_key, p_val, &p_opts->transaction_timeout);
1088219820Sjeff
1089219820Sjeff		opts_unpack_uint32("max_msg_fifo_timeout",
1090219820Sjeff				   p_key, p_val, &p_opts->max_msg_fifo_timeout);
1091219820Sjeff
1092219820Sjeff		opts_unpack_uint8("sm_priority",
1093219820Sjeff				  p_key, p_val, &p_opts->sm_priority);
1094219820Sjeff
1095219820Sjeff		opts_unpack_uint8("lmc", p_key, p_val, &p_opts->lmc);
1096219820Sjeff
1097219820Sjeff		opts_unpack_boolean("lmc_esp0",
1098219820Sjeff				    p_key, p_val, &p_opts->lmc_esp0);
1099219820Sjeff
1100219820Sjeff		opts_unpack_uint8("max_op_vls",
1101219820Sjeff				  p_key, p_val, &p_opts->max_op_vls);
1102219820Sjeff
1103219820Sjeff		opts_unpack_uint8("force_link_speed",
1104219820Sjeff				  p_key, p_val, &p_opts->force_link_speed);
1105219820Sjeff
1106219820Sjeff		opts_unpack_boolean("reassign_lids",
1107219820Sjeff				    p_key, p_val, &p_opts->reassign_lids);
1108219820Sjeff
1109219820Sjeff		opts_unpack_boolean("ignore_other_sm",
1110219820Sjeff				    p_key, p_val, &p_opts->ignore_other_sm);
1111219820Sjeff
1112219820Sjeff		opts_unpack_boolean("single_thread",
1113219820Sjeff				    p_key, p_val, &p_opts->single_thread);
1114219820Sjeff
1115219820Sjeff		opts_unpack_boolean("disable_multicast",
1116219820Sjeff				    p_key, p_val, &p_opts->disable_multicast);
1117219820Sjeff
1118219820Sjeff		opts_unpack_boolean("force_log_flush",
1119219820Sjeff				    p_key, p_val, &p_opts->force_log_flush);
1120219820Sjeff
1121219820Sjeff		opts_unpack_uint8("subnet_timeout",
1122219820Sjeff				  p_key, p_val, &p_opts->subnet_timeout);
1123219820Sjeff
1124219820Sjeff		opts_unpack_uint8("packet_life_time",
1125219820Sjeff				  p_key, p_val, &p_opts->packet_life_time);
1126219820Sjeff
1127219820Sjeff		opts_unpack_uint8("vl_stall_count",
1128219820Sjeff				  p_key, p_val, &p_opts->vl_stall_count);
1129219820Sjeff
1130219820Sjeff		opts_unpack_uint8("leaf_vl_stall_count",
1131219820Sjeff				  p_key, p_val, &p_opts->leaf_vl_stall_count);
1132219820Sjeff
1133219820Sjeff		opts_unpack_uint8("head_of_queue_lifetime",
1134219820Sjeff				  p_key, p_val,
1135219820Sjeff				  &p_opts->head_of_queue_lifetime);
1136219820Sjeff
1137219820Sjeff		opts_unpack_uint8("leaf_head_of_queue_lifetime", p_key, p_val,
1138219820Sjeff				  &p_opts->leaf_head_of_queue_lifetime);
1139219820Sjeff
1140219820Sjeff		opts_unpack_uint8("local_phy_errors_threshold", p_key, p_val,
1141219820Sjeff				  &p_opts->local_phy_errors_threshold);
1142219820Sjeff
1143219820Sjeff		opts_unpack_uint8("overrun_errors_threshold",
1144219820Sjeff				  p_key, p_val,
1145219820Sjeff				  &p_opts->overrun_errors_threshold);
1146219820Sjeff
1147219820Sjeff		opts_unpack_uint32("sminfo_polling_timeout",
1148219820Sjeff				   p_key, p_val,
1149219820Sjeff				   &p_opts->sminfo_polling_timeout);
1150219820Sjeff
1151219820Sjeff		opts_unpack_uint32("polling_retry_number",
1152219820Sjeff				   p_key, p_val, &p_opts->polling_retry_number);
1153219820Sjeff
1154219820Sjeff		opts_unpack_boolean("force_heavy_sweep",
1155219820Sjeff				    p_key, p_val, &p_opts->force_heavy_sweep);
1156219820Sjeff
1157219820Sjeff		opts_unpack_uint8("log_flags",
1158219820Sjeff				  p_key, p_val, &p_opts->log_flags);
1159219820Sjeff
1160219820Sjeff		opts_unpack_charp("port_prof_ignore_file", p_key, p_val,
1161219820Sjeff				  &p_opts->port_prof_ignore_file);
1162219820Sjeff
1163219820Sjeff		opts_unpack_boolean("port_profile_switch_nodes", p_key, p_val,
1164219820Sjeff				    &p_opts->port_profile_switch_nodes);
1165219820Sjeff
1166219820Sjeff		opts_unpack_boolean("sweep_on_trap",
1167219820Sjeff				    p_key, p_val, &p_opts->sweep_on_trap);
1168219820Sjeff
1169219820Sjeff		opts_unpack_charp("routing_engine",
1170219820Sjeff				  p_key, p_val, &p_opts->routing_engine_names);
1171219820Sjeff
1172219820Sjeff		opts_unpack_boolean("connect_roots",
1173219820Sjeff				    p_key, p_val, &p_opts->connect_roots);
1174219820Sjeff
1175219820Sjeff		opts_unpack_boolean("use_ucast_cache",
1176219820Sjeff				    p_key, p_val, &p_opts->use_ucast_cache);
1177219820Sjeff
1178219820Sjeff		opts_unpack_charp("log_file", p_key, p_val, &p_opts->log_file);
1179219820Sjeff
1180219820Sjeff		opts_unpack_uint32("log_max_size",
1181219820Sjeff				   p_key, p_val,
1182219820Sjeff				   (void *) & p_opts->log_max_size);
1183219820Sjeff		p_opts->log_max_size *= 1024 * 1024; /* convert to MB */
1184219820Sjeff
1185219820Sjeff		opts_unpack_charp("partition_config_file",
1186219820Sjeff				  p_key, p_val, &p_opts->partition_config_file);
1187219820Sjeff
1188219820Sjeff		opts_unpack_boolean("no_partition_enforcement", p_key, p_val,
1189219820Sjeff				    &p_opts->no_partition_enforcement);
1190219820Sjeff
1191219820Sjeff		opts_unpack_boolean("qos", p_key, p_val, &p_opts->qos);
1192219820Sjeff
1193219820Sjeff		opts_unpack_charp("qos_policy_file",
1194219820Sjeff				  p_key, p_val, &p_opts->qos_policy_file);
1195219820Sjeff
1196219820Sjeff		opts_unpack_boolean("accum_log_file",
1197219820Sjeff				    p_key, p_val, &p_opts->accum_log_file);
1198219820Sjeff
1199219820Sjeff		opts_unpack_charp("dump_files_dir",
1200219820Sjeff				  p_key, p_val, &p_opts->dump_files_dir);
1201219820Sjeff
1202219820Sjeff		opts_unpack_charp("lid_matrix_dump_file",
1203219820Sjeff				  p_key, p_val, &p_opts->lid_matrix_dump_file);
1204219820Sjeff
1205219820Sjeff		opts_unpack_charp("lfts_file",
1206219820Sjeff				  p_key, p_val, &p_opts->lfts_file);
1207219820Sjeff
1208219820Sjeff		opts_unpack_charp("root_guid_file",
1209219820Sjeff				  p_key, p_val, &p_opts->root_guid_file);
1210219820Sjeff
1211219820Sjeff		opts_unpack_charp("cn_guid_file",
1212219820Sjeff				  p_key, p_val, &p_opts->cn_guid_file);
1213219820Sjeff
1214219820Sjeff		opts_unpack_charp("ids_guid_file",
1215219820Sjeff				  p_key, p_val, &p_opts->ids_guid_file);
1216219820Sjeff
1217219820Sjeff		opts_unpack_charp("guid_routing_order_file",
1218219820Sjeff				  p_key, p_val, &p_opts->guid_routing_order_file);
1219219820Sjeff
1220219820Sjeff		opts_unpack_charp("sa_db_file",
1221219820Sjeff				  p_key, p_val, &p_opts->sa_db_file);
1222219820Sjeff
1223219820Sjeff		opts_unpack_boolean("exit_on_fatal",
1224219820Sjeff				    p_key, p_val, &p_opts->exit_on_fatal);
1225219820Sjeff
1226219820Sjeff		opts_unpack_boolean("honor_guid2lid_file",
1227219820Sjeff				    p_key, p_val, &p_opts->honor_guid2lid_file);
1228219820Sjeff
1229219820Sjeff		opts_unpack_boolean("daemon", p_key, p_val, &p_opts->daemon);
1230219820Sjeff
1231219820Sjeff		opts_unpack_boolean("sm_inactive",
1232219820Sjeff				    p_key, p_val, &p_opts->sm_inactive);
1233219820Sjeff
1234219820Sjeff		opts_unpack_boolean("babbling_port_policy",
1235219820Sjeff				    p_key, p_val,
1236219820Sjeff				    &p_opts->babbling_port_policy);
1237219820Sjeff
1238219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
1239219820Sjeff		opts_unpack_boolean("perfmgr", p_key, p_val, &p_opts->perfmgr);
1240219820Sjeff
1241219820Sjeff		opts_unpack_boolean("perfmgr_redir",
1242219820Sjeff				    p_key, p_val, &p_opts->perfmgr_redir);
1243219820Sjeff
1244219820Sjeff		opts_unpack_uint16("perfmgr_sweep_time_s",
1245219820Sjeff				   p_key, p_val, &p_opts->perfmgr_sweep_time_s);
1246219820Sjeff
1247219820Sjeff		opts_unpack_uint32("perfmgr_max_outstanding_queries",
1248219820Sjeff				   p_key, p_val,
1249219820Sjeff				   &p_opts->perfmgr_max_outstanding_queries);
1250219820Sjeff
1251219820Sjeff		opts_unpack_charp("event_db_dump_file",
1252219820Sjeff				  p_key, p_val, &p_opts->event_db_dump_file);
1253219820Sjeff#endif				/* ENABLE_OSM_PERF_MGR */
1254219820Sjeff
1255219820Sjeff		opts_unpack_charp("event_plugin_name",
1256219820Sjeff				  p_key, p_val, &p_opts->event_plugin_name);
1257219820Sjeff
1258219820Sjeff		opts_unpack_charp("node_name_map_name",
1259219820Sjeff				  p_key, p_val, &p_opts->node_name_map_name);
1260219820Sjeff
1261219820Sjeff		subn_parse_qos_options("qos",
1262219820Sjeff				       p_key, p_val, &p_opts->qos_options);
1263219820Sjeff
1264219820Sjeff		subn_parse_qos_options("qos_ca",
1265219820Sjeff				       p_key, p_val, &p_opts->qos_ca_options);
1266219820Sjeff
1267219820Sjeff		subn_parse_qos_options("qos_sw0",
1268219820Sjeff				       p_key, p_val, &p_opts->qos_sw0_options);
1269219820Sjeff
1270219820Sjeff		subn_parse_qos_options("qos_swe",
1271219820Sjeff				       p_key, p_val, &p_opts->qos_swe_options);
1272219820Sjeff
1273219820Sjeff		subn_parse_qos_options("qos_rtr",
1274219820Sjeff				       p_key, p_val, &p_opts->qos_rtr_options);
1275219820Sjeff
1276219820Sjeff		opts_unpack_boolean("enable_quirks",
1277219820Sjeff				    p_key, p_val, &p_opts->enable_quirks);
1278219820Sjeff
1279219820Sjeff		opts_unpack_boolean("no_clients_rereg",
1280219820Sjeff				    p_key, p_val, &p_opts->no_clients_rereg);
1281219820Sjeff
1282219820Sjeff		opts_unpack_charp("prefix_routes_file",
1283219820Sjeff				  p_key, p_val, &p_opts->prefix_routes_file);
1284219820Sjeff
1285219820Sjeff		opts_unpack_boolean("consolidate_ipv6_snm_req",
1286219820Sjeff				p_key, p_val, &p_opts->consolidate_ipv6_snm_req);
1287219820Sjeff	}
1288219820Sjeff	fclose(opts_file);
1289219820Sjeff
1290219820Sjeff	osm_subn_verify_config(p_opts);
1291219820Sjeff
1292219820Sjeff	return 0;
1293219820Sjeff}
1294219820Sjeff
1295219820Sjeffint osm_subn_rescan_conf_files(IN osm_subn_t * const p_subn)
1296219820Sjeff{
1297219820Sjeff	FILE *opts_file;
1298219820Sjeff	char line[1024];
1299219820Sjeff	char *p_key, *p_val, *p_last;
1300219820Sjeff
1301219820Sjeff	if (!p_subn->opt.config_file)
1302219820Sjeff		return 0;
1303219820Sjeff
1304219820Sjeff	opts_file = fopen(p_subn->opt.config_file, "r");
1305219820Sjeff	if (!opts_file) {
1306219820Sjeff		if (errno == ENOENT)
1307219820Sjeff			return 1;
1308219820Sjeff		OSM_LOG(&p_subn->p_osm->log, OSM_LOG_ERROR,
1309219820Sjeff			"cannot open file \'%s\': %s\n",
1310219820Sjeff			p_subn->opt.config_file, strerror(errno));
1311219820Sjeff		return -1;
1312219820Sjeff	}
1313219820Sjeff
1314219820Sjeff	subn_init_qos_options(&p_subn->opt.qos_options);
1315219820Sjeff	subn_init_qos_options(&p_subn->opt.qos_ca_options);
1316219820Sjeff	subn_init_qos_options(&p_subn->opt.qos_sw0_options);
1317219820Sjeff	subn_init_qos_options(&p_subn->opt.qos_swe_options);
1318219820Sjeff	subn_init_qos_options(&p_subn->opt.qos_rtr_options);
1319219820Sjeff
1320219820Sjeff	while (fgets(line, 1023, opts_file) != NULL) {
1321219820Sjeff		/* get the first token */
1322219820Sjeff		p_key = strtok_r(line, " \t\n", &p_last);
1323219820Sjeff		if (p_key) {
1324219820Sjeff			p_val = strtok_r(NULL, " \t\n", &p_last);
1325219820Sjeff
1326219820Sjeff			subn_parse_qos_options("qos", p_key, p_val,
1327219820Sjeff					       &p_subn->opt.qos_options);
1328219820Sjeff
1329219820Sjeff			subn_parse_qos_options("qos_ca", p_key, p_val,
1330219820Sjeff					       &p_subn->opt.qos_ca_options);
1331219820Sjeff
1332219820Sjeff			subn_parse_qos_options("qos_sw0", p_key, p_val,
1333219820Sjeff					       &p_subn->opt.qos_sw0_options);
1334219820Sjeff
1335219820Sjeff			subn_parse_qos_options("qos_swe", p_key, p_val,
1336219820Sjeff					       &p_subn->opt.qos_swe_options);
1337219820Sjeff
1338219820Sjeff			subn_parse_qos_options("qos_rtr", p_key, p_val,
1339219820Sjeff					       &p_subn->opt.qos_rtr_options);
1340219820Sjeff
1341219820Sjeff		}
1342219820Sjeff	}
1343219820Sjeff	fclose(opts_file);
1344219820Sjeff
1345219820Sjeff	osm_subn_verify_config(&p_subn->opt);
1346219820Sjeff
1347219820Sjeff	osm_parse_prefix_routes_file(p_subn);
1348219820Sjeff
1349219820Sjeff	return 0;
1350219820Sjeff}
1351219820Sjeff
1352219820Sjeff/**********************************************************************
1353219820Sjeff **********************************************************************/
1354219820Sjeffint osm_subn_output_conf(FILE *out, IN osm_subn_opt_t *const p_opts)
1355219820Sjeff{
1356219820Sjeff	fprintf(out,
1357219820Sjeff		"#\n# DEVICE ATTRIBUTES OPTIONS\n#\n"
1358219820Sjeff		"# The port GUID on which the OpenSM is running\n"
1359219820Sjeff		"guid 0x%016" PRIx64 "\n\n"
1360219820Sjeff		"# M_Key value sent to all ports qualifying all Set(PortInfo)\n"
1361219820Sjeff		"m_key 0x%016" PRIx64 "\n\n"
1362219820Sjeff		"# The lease period used for the M_Key on this subnet in [sec]\n"
1363219820Sjeff		"m_key_lease_period %u\n\n"
1364219820Sjeff		"# SM_Key value of the SM used for SM authentication\n"
1365219820Sjeff		"sm_key 0x%016" PRIx64 "\n\n"
1366219820Sjeff		"# SM_Key value to qualify rcv SA queries as 'trusted'\n"
1367219820Sjeff		"sa_key 0x%016" PRIx64 "\n\n"
1368219820Sjeff		"# Note that for both values above (sm_key and sa_key)\n"
1369219820Sjeff		"# OpenSM version 3.2.1 and below used the default value '1'\n"
1370219820Sjeff		"# in a host byte order, it is fixed now but you may need to\n"
1371219820Sjeff		"# change the values to interoperate with old OpenSM running\n"
1372219820Sjeff		"# on a little endian machine.\n\n"
1373219820Sjeff		"# Subnet prefix used on this subnet\n"
1374219820Sjeff		"subnet_prefix 0x%016" PRIx64 "\n\n"
1375219820Sjeff		"# The LMC value used on this subnet\n"
1376219820Sjeff		"lmc %u\n\n"
1377219820Sjeff		"# lmc_esp0 determines whether LMC value used on subnet is used for\n"
1378219820Sjeff		"# enhanced switch port 0. If TRUE, LMC value for subnet is used for\n"
1379219820Sjeff		"# ESP0. Otherwise, LMC value for ESP0s is 0.\n"
1380219820Sjeff		"lmc_esp0 %s\n\n"
1381219820Sjeff		"# The code of maximal time a packet can live in a switch\n"
1382219820Sjeff		"# The actual time is 4.096usec * 2^<packet_life_time>\n"
1383219820Sjeff		"# The value 0x14 disables this mechanism\n"
1384219820Sjeff		"packet_life_time 0x%02x\n\n"
1385219820Sjeff		"# The number of sequential packets dropped that cause the port\n"
1386219820Sjeff		"# to enter the VLStalled state. The result of setting this value to\n"
1387219820Sjeff		"# zero is undefined.\n"
1388219820Sjeff		"vl_stall_count 0x%02x\n\n"
1389219820Sjeff		"# The number of sequential packets dropped that cause the port\n"
1390219820Sjeff		"# to enter the VLStalled state. This value is for switch ports\n"
1391219820Sjeff		"# driving a CA or router port. The result of setting this value\n"
1392219820Sjeff		"# to zero is undefined.\n"
1393219820Sjeff		"leaf_vl_stall_count 0x%02x\n\n"
1394219820Sjeff		"# The code of maximal time a packet can wait at the head of\n"
1395219820Sjeff		"# transmission queue.\n"
1396219820Sjeff		"# The actual time is 4.096usec * 2^<head_of_queue_lifetime>\n"
1397219820Sjeff		"# The value 0x14 disables this mechanism\n"
1398219820Sjeff		"head_of_queue_lifetime 0x%02x\n\n"
1399219820Sjeff		"# The maximal time a packet can wait at the head of queue on\n"
1400219820Sjeff		"# switch port connected to a CA or router port\n"
1401219820Sjeff		"leaf_head_of_queue_lifetime 0x%02x\n\n"
1402219820Sjeff		"# Limit the maximal operational VLs\n"
1403219820Sjeff		"max_op_vls %u\n\n"
1404219820Sjeff		"# Force PortInfo:LinkSpeedEnabled on switch ports\n"
1405219820Sjeff		"# If 0, don't modify PortInfo:LinkSpeedEnabled on switch port\n"
1406219820Sjeff		"# Otherwise, use value for PortInfo:LinkSpeedEnabled on switch port\n"
1407219820Sjeff		"# Values are (IB Spec 1.2.1, 14.2.5.6 Table 146 \"PortInfo\")\n"
1408219820Sjeff		"#    1: 2.5 Gbps\n"
1409219820Sjeff		"#    3: 2.5 or 5.0 Gbps\n"
1410219820Sjeff		"#    5: 2.5 or 10.0 Gbps\n"
1411219820Sjeff		"#    7: 2.5 or 5.0 or 10.0 Gbps\n"
1412219820Sjeff		"#    2,4,6,8-14 Reserved\n"
1413219820Sjeff		"#    Default 15: set to PortInfo:LinkSpeedSupported\n"
1414219820Sjeff		"force_link_speed %u\n\n"
1415219820Sjeff		"# The subnet_timeout code that will be set for all the ports\n"
1416219820Sjeff		"# The actual timeout is 4.096usec * 2^<subnet_timeout>\n"
1417219820Sjeff		"subnet_timeout %u\n\n"
1418219820Sjeff		"# Threshold of local phy errors for sending Trap 129\n"
1419219820Sjeff		"local_phy_errors_threshold 0x%02x\n\n"
1420219820Sjeff		"# Threshold of credit overrun errors for sending Trap 130\n"
1421219820Sjeff		"overrun_errors_threshold 0x%02x\n\n",
1422219820Sjeff		cl_ntoh64(p_opts->guid),
1423219820Sjeff		cl_ntoh64(p_opts->m_key),
1424219820Sjeff		cl_ntoh16(p_opts->m_key_lease_period),
1425219820Sjeff		cl_ntoh64(p_opts->sm_key),
1426219820Sjeff		cl_ntoh64(p_opts->sa_key),
1427219820Sjeff		cl_ntoh64(p_opts->subnet_prefix),
1428219820Sjeff		p_opts->lmc,
1429219820Sjeff		p_opts->lmc_esp0 ? "TRUE" : "FALSE",
1430219820Sjeff		p_opts->packet_life_time,
1431219820Sjeff		p_opts->vl_stall_count,
1432219820Sjeff		p_opts->leaf_vl_stall_count,
1433219820Sjeff		p_opts->head_of_queue_lifetime,
1434219820Sjeff		p_opts->leaf_head_of_queue_lifetime,
1435219820Sjeff		p_opts->max_op_vls,
1436219820Sjeff		p_opts->force_link_speed,
1437219820Sjeff		p_opts->subnet_timeout,
1438219820Sjeff		p_opts->local_phy_errors_threshold,
1439219820Sjeff		p_opts->overrun_errors_threshold);
1440219820Sjeff
1441219820Sjeff	fprintf(out,
1442219820Sjeff		"#\n# PARTITIONING OPTIONS\n#\n"
1443219820Sjeff		"# Partition configuration file to be used\n"
1444219820Sjeff		"partition_config_file %s\n\n"
1445219820Sjeff		"# Disable partition enforcement by switches\n"
1446219820Sjeff		"no_partition_enforcement %s\n\n",
1447219820Sjeff		p_opts->partition_config_file,
1448219820Sjeff		p_opts->no_partition_enforcement ? "TRUE" : "FALSE");
1449219820Sjeff
1450219820Sjeff	fprintf(out,
1451219820Sjeff		"#\n# SWEEP OPTIONS\n#\n"
1452219820Sjeff		"# The number of seconds between subnet sweeps (0 disables it)\n"
1453219820Sjeff		"sweep_interval %u\n\n"
1454219820Sjeff		"# If TRUE cause all lids to be reassigned\n"
1455219820Sjeff		"reassign_lids %s\n\n"
1456219820Sjeff		"# If TRUE forces every sweep to be a heavy sweep\n"
1457219820Sjeff		"force_heavy_sweep %s\n\n"
1458219820Sjeff		"# If TRUE every trap will cause a heavy sweep.\n"
1459219820Sjeff		"# NOTE: successive identical traps (>10) are suppressed\n"
1460219820Sjeff		"sweep_on_trap %s\n\n",
1461219820Sjeff		p_opts->sweep_interval,
1462219820Sjeff		p_opts->reassign_lids ? "TRUE" : "FALSE",
1463219820Sjeff		p_opts->force_heavy_sweep ? "TRUE" : "FALSE",
1464219820Sjeff		p_opts->sweep_on_trap ? "TRUE" : "FALSE");
1465219820Sjeff
1466219820Sjeff	fprintf(out,
1467219820Sjeff		"#\n# ROUTING OPTIONS\n#\n"
1468219820Sjeff		"# If TRUE count switches as link subscriptions\n"
1469219820Sjeff		"port_profile_switch_nodes %s\n\n",
1470219820Sjeff		p_opts->port_profile_switch_nodes ? "TRUE" : "FALSE");
1471219820Sjeff
1472219820Sjeff	fprintf(out,
1473219820Sjeff		"# Name of file with port guids to be ignored by port profiling\n"
1474219820Sjeff		"port_prof_ignore_file %s\n\n", p_opts->port_prof_ignore_file ?
1475219820Sjeff		p_opts->port_prof_ignore_file : null_str);
1476219820Sjeff
1477219820Sjeff	fprintf(out,
1478219820Sjeff		"# Routing engine\n"
1479219820Sjeff		"# Multiple routing engines can be specified separated by\n"
1480219820Sjeff		"# commas so that specific ordering of routing algorithms will\n"
1481219820Sjeff		"# be tried if earlier routing engines fail.\n"
1482219820Sjeff		"# Supported engines: minhop, updn, file, ftree, lash, dor\n"
1483219820Sjeff		"routing_engine %s\n\n", p_opts->routing_engine_names ?
1484219820Sjeff		p_opts->routing_engine_names : null_str);
1485219820Sjeff
1486219820Sjeff	fprintf(out,
1487219820Sjeff		"# Connect roots (use FALSE if unsure)\n"
1488219820Sjeff		"connect_roots %s\n\n",
1489219820Sjeff		p_opts->connect_roots ? "TRUE" : "FALSE");
1490219820Sjeff
1491219820Sjeff	fprintf(out,
1492219820Sjeff		"# Use unicast routing cache (use FALSE if unsure)\n"
1493219820Sjeff		"use_ucast_cache %s\n\n",
1494219820Sjeff		p_opts->use_ucast_cache ? "TRUE" : "FALSE");
1495219820Sjeff
1496219820Sjeff	fprintf(out,
1497219820Sjeff		"# Lid matrix dump file name\n"
1498219820Sjeff		"lid_matrix_dump_file %s\n\n", p_opts->lid_matrix_dump_file ?
1499219820Sjeff		p_opts->lid_matrix_dump_file : null_str);
1500219820Sjeff
1501219820Sjeff	fprintf(out,
1502219820Sjeff		"# LFTs file name\nlfts_file %s\n\n",
1503219820Sjeff		p_opts->lfts_file ? p_opts->lfts_file : null_str);
1504219820Sjeff
1505219820Sjeff	fprintf(out,
1506219820Sjeff		"# The file holding the root node guids (for fat-tree or Up/Down)\n"
1507219820Sjeff		"# One guid in each line\nroot_guid_file %s\n\n",
1508219820Sjeff		p_opts->root_guid_file ? p_opts->root_guid_file : null_str);
1509219820Sjeff
1510219820Sjeff	fprintf(out,
1511219820Sjeff		"# The file holding the fat-tree compute node guids\n"
1512219820Sjeff		"# One guid in each line\ncn_guid_file %s\n\n",
1513219820Sjeff		p_opts->cn_guid_file ? p_opts->cn_guid_file : null_str);
1514219820Sjeff
1515219820Sjeff	fprintf(out,
1516219820Sjeff		"# The file holding the node ids which will be used by"
1517219820Sjeff		" Up/Down algorithm instead\n# of GUIDs (one guid and"
1518219820Sjeff		" id in each line)\nids_guid_file %s\n\n",
1519219820Sjeff		p_opts->ids_guid_file ? p_opts->ids_guid_file : null_str);
1520219820Sjeff
1521219820Sjeff	fprintf(out,
1522219820Sjeff		"# The file holding guid routing order guids (for MinHop and Up/Down)\n"
1523219820Sjeff		"guid_routing_order_file %s\n\n",
1524219820Sjeff		p_opts->guid_routing_order_file ? p_opts->guid_routing_order_file : null_str);
1525219820Sjeff
1526219820Sjeff	fprintf(out,
1527219820Sjeff		"# SA database file name\nsa_db_file %s\n\n",
1528219820Sjeff		p_opts->sa_db_file ? p_opts->sa_db_file : null_str);
1529219820Sjeff
1530219820Sjeff	fprintf(out,
1531219820Sjeff		"#\n# HANDOVER - MULTIPLE SMs OPTIONS\n#\n"
1532219820Sjeff		"# SM priority used for deciding who is the master\n"
1533219820Sjeff		"# Range goes from 0 (lowest priority) to 15 (highest).\n"
1534219820Sjeff		"sm_priority %u\n\n"
1535219820Sjeff		"# If TRUE other SMs on the subnet should be ignored\n"
1536219820Sjeff		"ignore_other_sm %s\n\n"
1537219820Sjeff		"# Timeout in [msec] between two polls of active master SM\n"
1538219820Sjeff		"sminfo_polling_timeout %u\n\n"
1539219820Sjeff		"# Number of failing polls of remote SM that declares it dead\n"
1540219820Sjeff		"polling_retry_number %u\n\n"
1541219820Sjeff		"# If TRUE honor the guid2lid file when coming out of standby\n"
1542219820Sjeff		"# state, if such file exists and is valid\n"
1543219820Sjeff		"honor_guid2lid_file %s\n\n",
1544219820Sjeff		p_opts->sm_priority,
1545219820Sjeff		p_opts->ignore_other_sm ? "TRUE" : "FALSE",
1546219820Sjeff		p_opts->sminfo_polling_timeout,
1547219820Sjeff		p_opts->polling_retry_number,
1548219820Sjeff		p_opts->honor_guid2lid_file ? "TRUE" : "FALSE");
1549219820Sjeff
1550219820Sjeff	fprintf(out,
1551219820Sjeff		"#\n# TIMING AND THREADING OPTIONS\n#\n"
1552219820Sjeff		"# Maximum number of SMPs sent in parallel\n"
1553219820Sjeff		"max_wire_smps %u\n\n"
1554219820Sjeff		"# The maximum time in [msec] allowed for a transaction to complete\n"
1555219820Sjeff		"transaction_timeout %u\n\n"
1556219820Sjeff		"# Maximal time in [msec] a message can stay in the incoming message queue.\n"
1557219820Sjeff		"# If there is more than one message in the queue and the last message\n"
1558219820Sjeff		"# stayed in the queue more than this value, any SA request will be\n"
1559219820Sjeff		"# immediately returned with a BUSY status.\n"
1560219820Sjeff		"max_msg_fifo_timeout %u\n\n"
1561219820Sjeff		"# Use a single thread for handling SA queries\n"
1562219820Sjeff		"single_thread %s\n\n",
1563219820Sjeff		p_opts->max_wire_smps,
1564219820Sjeff		p_opts->transaction_timeout,
1565219820Sjeff		p_opts->max_msg_fifo_timeout,
1566219820Sjeff		p_opts->single_thread ? "TRUE" : "FALSE");
1567219820Sjeff
1568219820Sjeff	fprintf(out,
1569219820Sjeff		"#\n# MISC OPTIONS\n#\n"
1570219820Sjeff		"# Daemon mode\n"
1571219820Sjeff		"daemon %s\n\n"
1572219820Sjeff		"# SM Inactive\n"
1573219820Sjeff		"sm_inactive %s\n\n"
1574219820Sjeff		"# Babbling Port Policy\n"
1575219820Sjeff		"babbling_port_policy %s\n\n",
1576219820Sjeff		p_opts->daemon ? "TRUE" : "FALSE",
1577219820Sjeff		p_opts->sm_inactive ? "TRUE" : "FALSE",
1578219820Sjeff		p_opts->babbling_port_policy ? "TRUE" : "FALSE");
1579219820Sjeff
1580219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
1581219820Sjeff	fprintf(out,
1582219820Sjeff		"#\n# Performance Manager Options\n#\n"
1583219820Sjeff		"# perfmgr enable\n"
1584219820Sjeff		"perfmgr %s\n\n"
1585219820Sjeff		"# perfmgr redirection enable\n"
1586219820Sjeff		"perfmgr_redir %s\n\n"
1587219820Sjeff		"# sweep time in seconds\n"
1588219820Sjeff		"perfmgr_sweep_time_s %u\n\n"
1589219820Sjeff		"# Max outstanding queries\n"
1590219820Sjeff		"perfmgr_max_outstanding_queries %u\n\n",
1591219820Sjeff		p_opts->perfmgr ? "TRUE" : "FALSE",
1592219820Sjeff		p_opts->perfmgr_redir ? "TRUE" : "FALSE",
1593219820Sjeff		p_opts->perfmgr_sweep_time_s,
1594219820Sjeff		p_opts->perfmgr_max_outstanding_queries);
1595219820Sjeff
1596219820Sjeff	fprintf(out,
1597219820Sjeff		"#\n# Event DB Options\n#\n"
1598219820Sjeff		"# Dump file to dump the events to\n"
1599219820Sjeff		"event_db_dump_file %s\n\n", p_opts->event_db_dump_file ?
1600219820Sjeff		p_opts->event_db_dump_file : null_str);
1601219820Sjeff#endif				/* ENABLE_OSM_PERF_MGR */
1602219820Sjeff
1603219820Sjeff	fprintf(out,
1604219820Sjeff		"#\n# Event Plugin Options\n#\n"
1605219820Sjeff		"event_plugin_name %s\n\n", p_opts->event_plugin_name ?
1606219820Sjeff		p_opts->event_plugin_name : null_str);
1607219820Sjeff
1608219820Sjeff	fprintf(out,
1609219820Sjeff		"#\n# Node name map for mapping node's to more descriptive node descriptions\n"
1610219820Sjeff		"# (man ibnetdiscover for more information)\n#\n"
1611219820Sjeff		"node_name_map_name %s\n\n", p_opts->node_name_map_name ?
1612219820Sjeff		p_opts->node_name_map_name : null_str);
1613219820Sjeff
1614219820Sjeff	fprintf(out,
1615219820Sjeff		"#\n# DEBUG FEATURES\n#\n"
1616219820Sjeff		"# The log flags used\n"
1617219820Sjeff		"log_flags 0x%02x\n\n"
1618219820Sjeff		"# Force flush of the log file after each log message\n"
1619219820Sjeff		"force_log_flush %s\n\n"
1620219820Sjeff		"# Log file to be used\n"
1621219820Sjeff		"log_file %s\n\n"
1622219820Sjeff		"# Limit the size of the log file in MB. If overrun, log is restarted\n"
1623219820Sjeff		"log_max_size %lu\n\n"
1624219820Sjeff		"# If TRUE will accumulate the log over multiple OpenSM sessions\n"
1625219820Sjeff		"accum_log_file %s\n\n"
1626219820Sjeff		"# The directory to hold the file OpenSM dumps\n"
1627219820Sjeff		"dump_files_dir %s\n\n"
1628219820Sjeff		"# If TRUE enables new high risk options and hardware specific quirks\n"
1629219820Sjeff		"enable_quirks %s\n\n"
1630219820Sjeff		"# If TRUE disables client reregistration\n"
1631219820Sjeff		"no_clients_rereg %s\n\n"
1632219820Sjeff		"# If TRUE OpenSM should disable multicast support and\n"
1633219820Sjeff		"# no multicast routing is performed if TRUE\n"
1634219820Sjeff		"disable_multicast %s\n\n"
1635219820Sjeff		"# If TRUE opensm will exit on fatal initialization issues\n"
1636219820Sjeff		"exit_on_fatal %s\n\n" "# console [off|local"
1637219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
1638219820Sjeff		"|loopback|socket]\n"
1639219820Sjeff#else
1640219820Sjeff		"]\n"
1641219820Sjeff#endif
1642219820Sjeff		"console %s\n\n"
1643219820Sjeff		"# Telnet port for console (default %d)\n"
1644219820Sjeff		"console_port %d\n\n",
1645219820Sjeff		p_opts->log_flags,
1646219820Sjeff		p_opts->force_log_flush ? "TRUE" : "FALSE",
1647219820Sjeff		p_opts->log_file,
1648219820Sjeff		p_opts->log_max_size/1024/1024,
1649219820Sjeff		p_opts->accum_log_file ? "TRUE" : "FALSE",
1650219820Sjeff		p_opts->dump_files_dir,
1651219820Sjeff		p_opts->enable_quirks ? "TRUE" : "FALSE",
1652219820Sjeff		p_opts->no_clients_rereg ? "TRUE" : "FALSE",
1653219820Sjeff		p_opts->disable_multicast ? "TRUE" : "FALSE",
1654219820Sjeff		p_opts->exit_on_fatal ? "TRUE" : "FALSE",
1655219820Sjeff		p_opts->console,
1656219820Sjeff		OSM_DEFAULT_CONSOLE_PORT, p_opts->console_port);
1657219820Sjeff
1658219820Sjeff	fprintf(out,
1659219820Sjeff		"#\n# QoS OPTIONS\n#\n"
1660219820Sjeff		"# Enable QoS setup\n"
1661219820Sjeff		"qos %s\n\n"
1662219820Sjeff		"# QoS policy file to be used\n"
1663219820Sjeff		"qos_policy_file %s\n\n",
1664219820Sjeff		p_opts->qos ? "TRUE" : "FALSE", p_opts->qos_policy_file);
1665219820Sjeff
1666219820Sjeff	subn_dump_qos_options(out,
1667219820Sjeff			      "QoS default options", "qos",
1668219820Sjeff			      &p_opts->qos_options);
1669219820Sjeff	fprintf(out, "\n");
1670219820Sjeff	subn_dump_qos_options(out,
1671219820Sjeff			      "QoS CA options", "qos_ca",
1672219820Sjeff			      &p_opts->qos_ca_options);
1673219820Sjeff	fprintf(out, "\n");
1674219820Sjeff	subn_dump_qos_options(out,
1675219820Sjeff			      "QoS Switch Port 0 options", "qos_sw0",
1676219820Sjeff			      &p_opts->qos_sw0_options);
1677219820Sjeff	fprintf(out, "\n");
1678219820Sjeff	subn_dump_qos_options(out,
1679219820Sjeff			      "QoS Switch external ports options", "qos_swe",
1680219820Sjeff			      &p_opts->qos_swe_options);
1681219820Sjeff	fprintf(out, "\n");
1682219820Sjeff	subn_dump_qos_options(out,
1683219820Sjeff			      "QoS Router ports options", "qos_rtr",
1684219820Sjeff			      &p_opts->qos_rtr_options);
1685219820Sjeff	fprintf(out, "\n");
1686219820Sjeff
1687219820Sjeff	fprintf(out,
1688219820Sjeff		"# Prefix routes file name\n"
1689219820Sjeff		"prefix_routes_file %s\n\n",
1690219820Sjeff		p_opts->prefix_routes_file);
1691219820Sjeff
1692219820Sjeff	fprintf(out,
1693219820Sjeff		"#\n# IPv6 Solicited Node Multicast (SNM) Options\n#\n"
1694219820Sjeff		"consolidate_ipv6_snm_req %s\n\n",
1695219820Sjeff		p_opts->consolidate_ipv6_snm_req ? "TRUE" : "FALSE");
1696219820Sjeff
1697219820Sjeff	/* optional string attributes ... */
1698219820Sjeff
1699219820Sjeff	return 0;
1700219820Sjeff}
1701219820Sjeff
1702219820Sjeffint osm_subn_write_conf_file(char *file_name, IN osm_subn_opt_t *const p_opts)
1703219820Sjeff{
1704219820Sjeff	FILE *opts_file;
1705219820Sjeff
1706219820Sjeff	opts_file = fopen(file_name, "w");
1707219820Sjeff	if (!opts_file) {
1708219820Sjeff		printf("cannot open file \'%s\' for writing: %s\n",
1709219820Sjeff			file_name, strerror(errno));
1710219820Sjeff		return -1;
1711219820Sjeff	}
1712219820Sjeff
1713219820Sjeff	if (osm_subn_output_conf(opts_file, p_opts) < 0)
1714219820Sjeff		return -1;
1715219820Sjeff
1716219820Sjeff	fclose(opts_file);
1717219820Sjeff
1718219820Sjeff	return 0;
1719219820Sjeff}
1720