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