15115240jeff/*
2c187222hselasky * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3c187222hselasky * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
45115240jeff * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5c187222hselasky * Copyright (c) 2009 HNR Consulting. All rights reserved.
6c187222hselasky * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
7c187222hselasky * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
85115240jeff *
95115240jeff * This software is available to you under a choice of one of two
105115240jeff * licenses.  You may choose to be licensed under the terms of the GNU
115115240jeff * General Public License (GPL) Version 2, available from the file
125115240jeff * COPYING in the main directory of this source tree, or the
135115240jeff * OpenIB.org BSD license below:
145115240jeff *
155115240jeff *     Redistribution and use in source and binary forms, with or
165115240jeff *     without modification, are permitted provided that the following
175115240jeff *     conditions are met:
185115240jeff *
195115240jeff *      - Redistributions of source code must retain the above
205115240jeff *        copyright notice, this list of conditions and the following
215115240jeff *        disclaimer.
225115240jeff *
235115240jeff *      - Redistributions in binary form must reproduce the above
245115240jeff *        copyright notice, this list of conditions and the following
255115240jeff *        disclaimer in the documentation and/or other materials
265115240jeff *        provided with the distribution.
275115240jeff *
285115240jeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
295115240jeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
305115240jeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
315115240jeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
325115240jeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
335115240jeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
345115240jeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
355115240jeff * SOFTWARE.
365115240jeff *
375115240jeff */
385115240jeff
395115240jeff/*
405115240jeff * Abstract:
415115240jeff *    Command line interface for opensm.
425115240jeff */
435115240jeff
445115240jeff#if HAVE_CONFIG_H
455115240jeff#  include <config.h>
465115240jeff#endif				/* HAVE_CONFIG_H */
475115240jeff
485115240jeff#include <stdio.h>
495115240jeff#include <stdlib.h>
505115240jeff#include <getopt.h>
515115240jeff#include <unistd.h>
525115240jeff#include <signal.h>
535115240jeff#include <sys/types.h>
545115240jeff#include <sys/stat.h>
555115240jeff#include <fcntl.h>
565115240jeff#include <complib/cl_types.h>
575115240jeff#include <complib/cl_debug.h>
58c187222hselasky#include <opensm/osm_file_ids.h>
59c187222hselasky#define FILE_ID OSM_FILE_MAIN_C
605115240jeff#include <vendor/osm_vendor_api.h>
615115240jeff#include <opensm/osm_version.h>
625115240jeff#include <opensm/osm_opensm.h>
635115240jeff#include <opensm/osm_console.h>
645115240jeff#include <opensm/osm_console_io.h>
655115240jeff#include <opensm/osm_perfmgr.h>
665115240jeff
675115240jeffvolatile unsigned int osm_exit_flag = 0;
685115240jeff
695115240jeffstatic volatile unsigned int osm_hup_flag = 0;
705115240jeffstatic volatile unsigned int osm_usr1_flag = 0;
71c187222hselaskystatic char *pidfile;
725115240jeff
73c187222hselasky#define MAX_LOCAL_IBPORTS 64
745115240jeff#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
755115240jeff
765115240jeffstatic void mark_exit_flag(int signum)
775115240jeff{
785115240jeff	if (!osm_exit_flag)
795115240jeff		printf("OpenSM: Got signal %d - exiting...\n", signum);
805115240jeff	osm_exit_flag = 1;
815115240jeff}
825115240jeff
835115240jeffstatic void mark_hup_flag(int signum)
845115240jeff{
855115240jeff	osm_hup_flag = 1;
865115240jeff}
875115240jeff
885115240jeffstatic void mark_usr1_flag(int signum)
895115240jeff{
905115240jeff	osm_usr1_flag = 1;
915115240jeff}
925115240jeff
935115240jeffstatic sigset_t saved_sigset;
945115240jeff
955115240jeffstatic void block_signals()
965115240jeff{
975115240jeff	sigset_t set;
985115240jeff
995115240jeff	sigemptyset(&set);
1005115240jeff	sigaddset(&set, SIGINT);
1015115240jeff	sigaddset(&set, SIGTERM);
1025115240jeff	sigaddset(&set, SIGHUP);
1035115240jeff#ifndef HAVE_OLD_LINUX_THREADS
1045115240jeff	sigaddset(&set, SIGUSR1);
1055115240jeff#endif
1065115240jeff	pthread_sigmask(SIG_SETMASK, &set, &saved_sigset);
1075115240jeff}
1085115240jeff
1095115240jeffstatic void setup_signals()
1105115240jeff{
1115115240jeff	struct sigaction act;
1125115240jeff
1135115240jeff	sigemptyset(&act.sa_mask);
1145115240jeff	act.sa_handler = mark_exit_flag;
1155115240jeff	act.sa_flags = 0;
1165115240jeff	sigaction(SIGINT, &act, NULL);
1175115240jeff	sigaction(SIGTERM, &act, NULL);
1185115240jeff	act.sa_handler = mark_hup_flag;
1195115240jeff	sigaction(SIGHUP, &act, NULL);
1205115240jeff	sigaction(SIGCONT, &act, NULL);
1215115240jeff#ifndef HAVE_OLD_LINUX_THREADS
1225115240jeff	act.sa_handler = mark_usr1_flag;
1235115240jeff	sigaction(SIGUSR1, &act, NULL);
1245115240jeff#endif
1255115240jeff	pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL);
1265115240jeff}
1275115240jeff
1285115240jeffstatic void show_usage(void)
1295115240jeff{
1305115240jeff	printf("\n------- OpenSM - Usage and options ----------------------\n");
1315115240jeff	printf("Usage:   opensm [options]\n");
1325115240jeff	printf("Options:\n");
1335115240jeff	printf("--version\n          Prints OpenSM version and exits.\n\n");
1345115240jeff	printf("--config, -F <file-name>\n"
1355115240jeff	       "          The name of the OpenSM config file. When not specified\n"
136c187222hselasky	       "          " OSM_DEFAULT_CONFIG_FILE
137c187222hselasky	       " will be used (if exists).\n\n");
1385115240jeff	printf("--create-config, -c <file-name>\n"
1395115240jeff	       "          OpenSM will dump its configuration to the specified file and exit.\n"
1405115240jeff	       "          This is a way to generate OpenSM configuration file template.\n\n");
1415115240jeff	printf("--guid, -g <GUID in hex>\n"
1425115240jeff	       "          This option specifies the local port GUID value\n"
1435115240jeff	       "          with which OpenSM should bind.  OpenSM may be\n"
1445115240jeff	       "          bound to 1 port at a time.\n"
1455115240jeff	       "          If GUID given is 0, OpenSM displays a list\n"
1465115240jeff	       "          of possible port GUIDs and waits for user input.\n"
1475115240jeff	       "          Without -g, OpenSM tries to use the default port.\n\n");
1485115240jeff	printf("--lmc, -l <LMC>\n"
1495115240jeff	       "          This option specifies the subnet's LMC value.\n"
1505115240jeff	       "          The number of LIDs assigned to each port is 2^LMC.\n"
1515115240jeff	       "          The LMC value must be in the range 0-7.\n"
1525115240jeff	       "          LMC values > 0 allow multiple paths between ports.\n"
1535115240jeff	       "          LMC values > 0 should only be used if the subnet\n"
1545115240jeff	       "          topology actually provides multiple paths between\n"
1555115240jeff	       "          ports, i.e. multiple interconnects between switches.\n"
1565115240jeff	       "          Without -l, OpenSM defaults to LMC = 0, which allows\n"
1575115240jeff	       "          one path between any two ports.\n\n");
1585115240jeff	printf("--priority, -p <PRIORITY>\n"
1595115240jeff	       "          This option specifies the SM's PRIORITY.\n"
1605115240jeff	       "          This will effect the handover cases, where master\n"
1615115240jeff	       "          is chosen by priority and GUID.  Range goes\n"
1625115240jeff	       "          from 0 (lowest priority) to 15 (highest).\n\n");
1635115240jeff	printf("--smkey, -k <SM_Key>\n"
1645115240jeff	       "          This option specifies the SM's SM_Key (64 bits).\n"
1655115240jeff	       "          This will effect SM authentication.\n"
1665115240jeff	       "          Note that OpenSM version 3.2.1 and below used the\n"
1675115240jeff	       "          default value '1' in a host byte order, it is fixed\n"
1685115240jeff	       "          now but you may need this option to interoperate\n"
1695115240jeff	       "          with old OpenSM running on a little endian machine.\n\n");
1705115240jeff	printf("--reassign_lids, -r\n"
1715115240jeff	       "          This option causes OpenSM to reassign LIDs to all\n"
1725115240jeff	       "          end nodes. Specifying -r on a running subnet\n"
1735115240jeff	       "          may disrupt subnet traffic.\n"
1745115240jeff	       "          Without -r, OpenSM attempts to preserve existing\n"
1755115240jeff	       "          LID assignments resolving multiple use of same LID.\n\n");
1765115240jeff	printf("--routing_engine, -R <engine name>\n"
1775115240jeff	       "          This option chooses routing engine(s) to use instead of default\n"
1785115240jeff	       "          Min Hop algorithm.  Multiple routing engines can be specified\n"
1795115240jeff	       "          separated by commas so that specific ordering of routing\n"
1805115240jeff	       "          algorithms will be tried if earlier routing engines fail.\n"
181c187222hselasky	       "          If all configured routing engines fail, OpenSM will always\n"
182c187222hselasky	       "          attempt to route with Min Hop unless 'no_fallback' is\n"
183c187222hselasky	       "          included in the list of routing engines.\n"
184c187222hselasky	       "          Supported engines: updn, dnup, file, ftree, lash, dor, torus-2QoS, dfsssp, sssp\n\n");
185c187222hselasky	printf("--do_mesh_analysis\n"
186c187222hselasky	       "          This option enables additional analysis for the lash\n"
187c187222hselasky	       "          routing engine to precondition switch port assignments\n"
188c187222hselasky	       "          in regular cartesian meshes which may reduce the number\n"
189c187222hselasky	       "          of SLs required to give a deadlock free routing\n\n");
190c187222hselasky	printf("--lash_start_vl <vl number>\n"
191c187222hselasky	       "          Sets the starting VL to use for the lash routing algorithm.\n"
192c187222hselasky	       "          Defaults to 0.\n");
193c187222hselasky	printf("--sm_sl <sl number>\n"
194c187222hselasky	       "          Sets the SL to use to communicate with the SM/SA. Defaults to 0.\n\n");
1955115240jeff	printf("--connect_roots, -z\n"
196c187222hselasky	       "          This option enforces routing engines (up/down and \n"
197c187222hselasky	       "          fat-tree) to make connectivity between root switches\n"
1985115240jeff	       "          and in this way be IBA compliant. In many cases,\n"
1995115240jeff	       "          this can violate \"pure\" deadlock free algorithm, so\n"
2005115240jeff	       "          use it carefully.\n\n");
2015115240jeff	printf("--ucast_cache, -A\n"
2025115240jeff	       "          This option enables unicast routing cache to prevent\n"
2035115240jeff	       "          routing recalculation (which is a heavy task in a\n"
2045115240jeff	       "          large cluster) when there was no topology change\n"
2055115240jeff	       "          detected during the heavy sweep, or when the topology\n"
2065115240jeff	       "          change does not require new routing calculation,\n"
2075115240jeff	       "          e.g. in case of host reboot.\n"
2085115240jeff	       "          This option becomes very handy when the cluster size\n"
2095115240jeff	       "          is thousands of nodes.\n\n");
2105115240jeff	printf("--lid_matrix_file, -M <file name>\n"
2115115240jeff	       "          This option specifies the name of the lid matrix dump file\n"
2125115240jeff	       "          from where switch lid matrices (min hops tables will be\n"
2135115240jeff	       "          loaded.\n\n");
2145115240jeff	printf("--lfts_file, -U <file name>\n"
2155115240jeff	       "          This option specifies the name of the LFTs file\n"
216c187222hselasky	       "          from where switch forwarding tables will be loaded when using \"file\"\n"
217c187222hselasky	       "          routing engine.\n\n");
2185115240jeff	printf("--sadb_file, -S <file name>\n"
2195115240jeff	       "          This option specifies the name of the SA DB dump file\n"
2205115240jeff	       "          from where SA database will be loaded.\n\n");
2215115240jeff	printf("--root_guid_file, -a <path to file>\n"
2225115240jeff	       "          Set the root nodes for the Up/Down or Fat-Tree routing\n"
2235115240jeff	       "          algorithm to the guids provided in the given file (one\n"
2245115240jeff	       "          to a line)\n" "\n");
2255115240jeff	printf("--cn_guid_file, -u <path to file>\n"
226c187222hselasky	       "          Set the compute nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n"
227c187222hselasky	       "          to the port GUIDs provided in the given file (one to a line)\n\n");
228c187222hselasky	printf("--io_guid_file, -G <path to file>\n"
229c187222hselasky	       "          Set the I/O nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n"
230c187222hselasky	       "          to the port GUIDs provided in the given file (one to a line)\n\n");
231c187222hselasky	printf("--port-shifting\n"
232c187222hselasky	       "          Attempt to shift port routes around to remove alignment problems\n"
233c187222hselasky	       "          in routing tables\n\n");
234c187222hselasky	printf("--scatter-ports <random seed>\n"
235c187222hselasky	       "          Randomize best port chosen for a route\n"
236c187222hselasky	       "          Assign ports in a random order instead of round-robin\n"
237c187222hselasky	       "          If zero disable (default), otherwise use the value as a random seed\n\n");
238c187222hselasky	printf("--max_reverse_hops, -H <hop_count>\n"
239c187222hselasky	       "          Set the max number of hops the wrong way around\n"
240c187222hselasky	       "          an I/O node is allowed to do (connectivity for I/O nodes on top swithces)\n\n");
2415115240jeff	printf("--ids_guid_file, -m <path to file>\n"
2425115240jeff	       "          Name of the map file with set of the IDs which will be used\n"
2435115240jeff	       "          by Up/Down routing algorithm instead of node GUIDs\n"
2445115240jeff	       "          (format: <guid> <id> per line)\n\n");
2455115240jeff	printf("--guid_routing_order_file, -X <path to file>\n"
2465115240jeff	       "          Set the order port guids will be routed for the MinHop\n"
2475115240jeff	       "          and Up/Down routing algorithms to the guids provided in the\n"
2485115240jeff	       "          given file (one to a line)\n\n");
249c187222hselasky	printf("--torus_config <path to file>\n"
250c187222hselasky	       "          This option defines the file name for the extra configuration\n"
251c187222hselasky	       "          info needed for the torus-2QoS routing engine.   The default\n"
252c187222hselasky	       "          name is \'"OSM_DEFAULT_TORUS_CONF_FILE"\'\n\n");
2535115240jeff	printf("--once, -o\n"
2545115240jeff	       "          This option causes OpenSM to configure the subnet\n"
2555115240jeff	       "          once, then exit.  Ports remain in the ACTIVE state.\n\n");
2565115240jeff	printf("--sweep, -s <interval>\n"
2575115240jeff	       "          This option specifies the number of seconds between\n"
2585115240jeff	       "          subnet sweeps.  Specifying -s 0 disables sweeping.\n"
2595115240jeff	       "          Without -s, OpenSM defaults to a sweep interval of\n"
2605115240jeff	       "          10 seconds.\n\n");
2615115240jeff	printf("--timeout, -t <milliseconds>\n"
2625115240jeff	       "          This option specifies the time in milliseconds\n"
2635115240jeff	       "          used for transaction timeouts.\n"
264c187222hselasky	       "          Timeout values should be > 0.\n"
2655115240jeff	       "          Without -t, OpenSM defaults to a timeout value of\n"
2665115240jeff	       "          200 milliseconds.\n\n");
267c187222hselasky	printf("--retries <number>\n"
268c187222hselasky	       "          This option specifies the number of retries used\n"
269c187222hselasky	       "          for transactions.\n"
270c187222hselasky	       "          Without --retries, OpenSM defaults to %u retries\n"
271c187222hselasky	       "          for transactions.\n\n", OSM_DEFAULT_RETRY_COUNT);
2725115240jeff	printf("--maxsmps, -n <number>\n"
2735115240jeff	       "          This option specifies the number of VL15 SMP MADs\n"
2745115240jeff	       "          allowed on the wire at any one time.\n"
2755115240jeff	       "          Specifying --maxsmps 0 allows unlimited outstanding\n"
2765115240jeff	       "          SMPs.\n"
2775115240jeff	       "          Without --maxsmps, OpenSM defaults to a maximum of\n"
2785115240jeff	       "          4 outstanding SMPs.\n\n");
2795115240jeff	printf("--console, -q [off|local"
280c187222hselasky#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
281c187222hselasky	       "|loopback"
282c187222hselasky#endif
2835115240jeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
284c187222hselasky	       "|socket"
2855115240jeff#endif
2865115240jeff	       "]\n          This option activates the OpenSM console (default off).\n\n");
287c187222hselasky#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
2885115240jeff	printf("--console-port, -C <port>\n"
2895115240jeff	       "          Specify an alternate telnet port for the console (default %d).\n\n",
2905115240jeff	       OSM_DEFAULT_CONSOLE_PORT);
2915115240jeff#endif
292c187222hselasky	printf("--ignore_guids, -i <equalize-ignore-guids-file>\n"
2935115240jeff	       "          This option provides the means to define a set of ports\n"
2945115240jeff	       "          (by guid) that will be ignored by the link load\n"
2955115240jeff	       "          equalization algorithm.\n\n");
296c187222hselasky	printf("--hop_weights_file, -w <path to file>\n"
297c187222hselasky	       "          This option provides the means to define a weighting\n"
298c187222hselasky	       "          factor per port for customizing the least weight\n"
299c187222hselasky	       "          hops for the routing.\n\n");
300c187222hselasky	printf("--port_search_ordering_file, -O <path to file>\n"
301c187222hselasky	       "          This option provides the means to define a mapping\n"
302c187222hselasky	       "          between ports and dimension (Order) for controlling\n"
303c187222hselasky	       "          Dimension Order Routing (DOR).\n"
304c187222hselasky	       "          Moreover this option provides the means to define non\n"
305c187222hselasky	       "          default routing port order.\n\n");
306c187222hselasky	printf("--dimn_ports_file, -O <path to file> (DEPRECATED)\n"
307c187222hselasky	       "          Use --port_search_ordering_file instead.\n"
308c187222hselasky	       "          This option provides the means to define a mapping\n"
309c187222hselasky	       "          between ports and dimension (Order) for controlling\n"
310c187222hselasky	       "          Dimension Order Routing (DOR).\n\n");
3115115240jeff	printf("--honor_guid2lid, -x\n"
3125115240jeff	       "          This option forces OpenSM to honor the guid2lid file,\n"
3135115240jeff	       "          when it comes out of Standby state, if such file exists\n"
3145115240jeff	       "          under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n");
3155115240jeff	printf("--log_file, -f <log-file-name>\n"
3165115240jeff	       "          This option defines the log to be the given file.\n"
3175115240jeff	       "          By default, the log goes to /var/log/opensm.log.\n"
3185115240jeff	       "          For the log to go to standard output use -f stdout.\n\n");
3195115240jeff	printf("--log_limit, -L <size in MB>\n"
3205115240jeff	       "          This option defines maximal log file size in MB. When\n"
3215115240jeff	       "          specified the log file will be truncated upon reaching\n"
3225115240jeff	       "          this limit.\n\n");
3235115240jeff	printf("--erase_log_file, -e\n"
3245115240jeff	       "          This option will cause deletion of the log file\n"
3255115240jeff	       "          (if it previously exists). By default, the log file\n"
3265115240jeff	       "          is accumulative.\n\n");
3275115240jeff	printf("--Pconfig, -P <partition-config-file>\n"
3285115240jeff	       "          This option defines the optional partition configuration file.\n"
3295115240jeff	       "          The default name is \'"
3305115240jeff	       OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n");
331c187222hselasky	printf("--no_part_enforce, -N (DEPRECATED)\n"
332c187222hselasky	       "          Use --part_enforce instead.\n"
3335115240jeff	       "          This option disables partition enforcement on switch external ports.\n\n");
334c187222hselasky	printf("--part_enforce, -Z [both, in, out, off]\n"
335c187222hselasky	       "          This option indicates the partition enforcement type (for switches)\n"
336c187222hselasky	       "          Enforcement type can be outbound only (out), inbound only (in), both or\n"
337c187222hselasky	       "          disabled (off). Default is both.\n\n");
338c187222hselasky	printf("--allow_both_pkeys, -W\n"
339c187222hselasky	       "          This option indicates whether both full and limited membership\n"
340c187222hselasky	       "          on the same partition can be configured in the PKeyTable.\n"
341c187222hselasky	       "          Default is not to allow both pkeys.\n\n");
3425115240jeff	printf("--qos, -Q\n" "          This option enables QoS setup.\n\n");
3435115240jeff	printf("--qos_policy_file, -Y <QoS-policy-file>\n"
3445115240jeff	       "          This option defines the optional QoS policy file.\n"
3455115240jeff	       "          The default name is \'" OSM_DEFAULT_QOS_POLICY_FILE
3465115240jeff	       "\'.\n\n");
347c187222hselasky	printf("--congestion_control\n"
348c187222hselasky	       "          (EXPERIMENTAL) This option enables congestion control configuration.\n\n");
349c187222hselasky	printf("--cc_key <key>\n"
350c187222hselasky	       "          (EXPERIMENTAL) This option configures the CCkey to use when configuring\n"
351c187222hselasky	       "          congestion control.\n\n");
3525115240jeff	printf("--stay_on_fatal, -y\n"
3535115240jeff	       "          This option will cause SM not to exit on fatal initialization\n"
3545115240jeff	       "          issues: if SM discovers duplicated guids or 12x link with\n"
3555115240jeff	       "          lane reversal badly configured.\n"
3565115240jeff	       "          By default, the SM will exit on these errors.\n\n");
3575115240jeff	printf("--daemon, -B\n"
3585115240jeff	       "          Run in daemon mode - OpenSM will run in the background.\n\n");
3595115240jeff	printf("--inactive, -I\n"
3605115240jeff	       "           Start SM in inactive rather than normal init SM state.\n\n");
3615115240jeff#ifdef ENABLE_OSM_PERF_MGR
3625115240jeff	printf("--perfmgr\n" "           Start with PerfMgr enabled.\n\n");
3635115240jeff	printf("--perfmgr_sweep_time_s <sec.>\n"
3645115240jeff	       "           PerfMgr sweep interval in seconds.\n\n");
3655115240jeff#endif
3665115240jeff	printf("--prefix_routes_file <path to file>\n"
3675115240jeff	       "          This option specifies the prefix routes file.\n"
3685115240jeff	       "          Prefix routes control how the SA responds to path record\n"
3695115240jeff	       "          queries for off-subnet DGIDs.  Default file is:\n"
3705115240jeff	       "              " OSM_DEFAULT_PREFIX_ROUTES_FILE "\n\n");
3715115240jeff	printf("--consolidate_ipv6_snm_req\n"
372c187222hselasky	       "          Use shared MLID for IPv6 Solicited Node Multicast groups\n"
373c187222hselasky	       "          per MGID scope and P_Key.\n\n");
374c187222hselasky	printf("--guid_routing_order_no_scatter\n"
375c187222hselasky	       "          Don't use scatter for ports defined in guid_routing_order file\n\n");
376c187222hselasky	printf("--log_prefix <prefix text>\n"
377c187222hselasky	       "          Prefix to syslog messages from OpenSM.\n\n");
3785115240jeff	printf("--verbose, -v\n"
3795115240jeff	       "          This option increases the log verbosity level.\n"
3805115240jeff	       "          The -v option may be specified multiple times\n"
3815115240jeff	       "          to further increase the verbosity level.\n"
3825115240jeff	       "          See the -D option for more information about\n"
3835115240jeff	       "          log verbosity.\n\n");
3845115240jeff	printf("--V, -V\n"
3855115240jeff	       "          This option sets the maximum verbosity level and\n"
3865115240jeff	       "          forces log flushing.\n"
3875115240jeff	       "          The -V is equivalent to '-D 0xFF -d 2'.\n"
3885115240jeff	       "          See the -D option for more information about\n"
3895115240jeff	       "          log verbosity.\n\n");
3905115240jeff	printf("--D, -D <flags>\n"
3915115240jeff	       "          This option sets the log verbosity level.\n"
3925115240jeff	       "          A flags field must follow the -D option.\n"
3935115240jeff	       "          A bit set/clear in the flags enables/disables a\n"
3945115240jeff	       "          specific log level as follows:\n"
3955115240jeff	       "          BIT    LOG LEVEL ENABLED\n"
3965115240jeff	       "          ----   -----------------\n"
3975115240jeff	       "          0x01 - ERROR (error messages)\n"
3985115240jeff	       "          0x02 - INFO (basic messages, low volume)\n"
3995115240jeff	       "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
4005115240jeff	       "          0x08 - DEBUG (diagnostic, high volume)\n"
4015115240jeff	       "          0x10 - FUNCS (function entry/exit, very high volume)\n"
4025115240jeff	       "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
4035115240jeff	       "          0x40 - ROUTING (dump FDB routing information)\n"
4045115240jeff	       "          0x80 - currently unused.\n"
4055115240jeff	       "          Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
4065115240jeff	       "          Specifying -D 0 disables all messages.\n"
4075115240jeff	       "          Specifying -D 0xFF enables all messages (see -V).\n"
4085115240jeff	       "          High verbosity levels may require increasing\n"
4095115240jeff	       "          the transaction timeout with the -t option.\n\n");
4105115240jeff	printf("--debug, -d <number>\n"
4115115240jeff	       "          This option specifies a debug option.\n"
4125115240jeff	       "          These options are not normally needed.\n"
4135115240jeff	       "          The number following -d selects the debug\n"
4145115240jeff	       "          option to enable as follows:\n"
4155115240jeff	       "          OPT   Description\n"
4165115240jeff	       "          ---    -----------------\n"
4175115240jeff	       "          -d0  - Ignore other SM nodes\n"
4185115240jeff	       "          -d1  - Force single threaded dispatching\n"
4195115240jeff	       "          -d2  - Force log flushing after each log message\n"
4205115240jeff	       "          -d3  - Disable multicast support\n"
4215115240jeff	       "          -d10 - Put OpenSM in testability mode\n"
4225115240jeff	       "          Without -d, no debug options are enabled\n\n");
4235115240jeff	printf("--help, -h, -?\n"
4245115240jeff	       "          Display this usage info then exit.\n\n");
4255115240jeff	fflush(stdout);
4265115240jeff	exit(2);
4275115240jeff}
4285115240jeff
4295115240jeffstatic ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid)
4305115240jeff{
431c187222hselasky	ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS];
432c187222hselasky	uint32_t num_ports = MAX_LOCAL_IBPORTS;
4335115240jeff	uint32_t i, choice = 0;
4345115240jeff	ib_api_status_t status;
4355115240jeff
436c187222hselasky	for (i = 0; i < num_ports; i++) {
437c187222hselasky		attr_array[i].num_pkeys = 0;
438c187222hselasky		attr_array[i].p_pkey_table = NULL;
439c187222hselasky		attr_array[i].num_gids = 0;
440c187222hselasky		attr_array[i].p_gid_table = NULL;
441c187222hselasky	}
442c187222hselasky
443c187222hselasky	/* Call the transport layer for a list of local port GUID values */
444c187222hselasky	status = osm_vendor_get_all_port_attr(p_osm->p_vendor, attr_array,
445c187222hselasky					      &num_ports);
4465115240jeff	if (status != IB_SUCCESS) {
4475115240jeff		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
4485115240jeff		       status);
449c187222hselasky		return 0;
4505115240jeff	}
4515115240jeff
4525115240jeff	/* if num_ports is 0 - return 0 */
4535115240jeff	if (num_ports == 0) {
4545115240jeff		printf("\nNo local ports detected!\n");
455c187222hselasky		return 0;
4565115240jeff	}
4575115240jeff	/* If num_ports is 1, then there is only one possible port to use.
4585115240jeff	 * Use it. */
4595115240jeff	if (num_ports == 1) {
4605115240jeff		printf("Using default GUID 0x%" PRIx64 "\n",
4615115240jeff		       cl_hton64(attr_array[0].port_guid));
462c187222hselasky		return attr_array[0].port_guid;
4635115240jeff	}
4645115240jeff	/* If port_guid is 0 - use the first connected port */
4655115240jeff	if (port_guid == 0) {
4665115240jeff		for (i = 0; i < num_ports; i++)
4675115240jeff			if (attr_array[i].link_state > IB_LINK_DOWN)
4685115240jeff				break;
4695115240jeff		if (i == num_ports)
4705115240jeff			i = 0;
4715115240jeff		printf("Using default GUID 0x%" PRIx64 "\n",
4725115240jeff		       cl_hton64(attr_array[i].port_guid));
473c187222hselasky		return attr_array[i].port_guid;
4745115240jeff	}
4755115240jeff
4765115240jeff	if (p_osm->subn.opt.daemon)
4775115240jeff		return 0;
4785115240jeff
4795115240jeff	/* More than one possible port - list all ports and let the user
4805115240jeff	 * to choose. */
481c187222hselasky	while (1) {
4825115240jeff		printf("\nChoose a local port number with which to bind:\n\n");
4835115240jeff		for (i = 0; i < num_ports; i++)
4845115240jeff			/* Print the index + 1 since by convention, port
4855115240jeff			 * numbers start with 1 on host channel adapters. */
486c187222hselasky			printf("\t%u: GUID 0x%" PRIx64 ", lid %u, state %s\n",
487c187222hselasky			       i + 1, cl_ntoh64(attr_array[i].port_guid),
4885115240jeff			       attr_array[i].lid,
4895115240jeff			       ib_get_port_state_str(attr_array[i].link_state));
490c187222hselasky		printf("\n\t0: Exit\n");
491c187222hselasky		printf("\nEnter choice (0-%u): ", i);
4925115240jeff		fflush(stdout);
493c187222hselasky		if (scanf("%u", &choice) <= 0) {
494c187222hselasky			char junk[128];
4958dd5aa9slavash			if (scanf("%127s", junk) <= 0)
496c187222hselasky				printf("\nError: Cannot scan!\n");
497c187222hselasky		} else if (choice == 0)
498c187222hselasky			return 0;
499c187222hselasky		else if (choice <= num_ports)
500c187222hselasky			break;
501c187222hselasky		printf("\nError: Lame choice! Please try again.\n");
5025115240jeff	}
503c187222hselasky	choice--;
5045115240jeff	printf("Choice guid=0x%" PRIx64 "\n",
5055115240jeff	       cl_ntoh64(attr_array[choice].port_guid));
506c187222hselasky	return attr_array[choice].port_guid;
5075115240jeff}
5085115240jeff
509c187222hselaskystatic void remove_pidfile(void)
510c187222hselasky{
511c187222hselasky	if (pidfile)
512c187222hselasky		unlink(pidfile);
513c187222hselasky}
5145115240jeff
5155115240jeffstatic int daemonize(osm_opensm_t * osm)
5165115240jeff{
5175115240jeff	pid_t pid;
5185115240jeff	int fd;
519c187222hselasky	FILE *f;
5205115240jeff
5215115240jeff	fd = open("/dev/null", O_WRONLY);
5225115240jeff	if (fd < 0) {
5235115240jeff		perror("open");
5245115240jeff		return -1;
5255115240jeff	}
5265115240jeff
5275115240jeff	if ((pid = fork()) < 0) {
5285115240jeff		perror("fork");
5295115240jeff		exit(-1);
5305115240jeff	} else if (pid > 0)
5315115240jeff		exit(0);
5325115240jeff
5335115240jeff	setsid();
5345115240jeff
5355115240jeff	if ((pid = fork()) < 0) {
5365115240jeff		perror("fork");
5375115240jeff		exit(-1);
5385115240jeff	} else if (pid > 0)
5395115240jeff		exit(0);
5405115240jeff
541c187222hselasky	if (pidfile) {
542c187222hselasky		remove_pidfile();
543c187222hselasky		f = fopen(pidfile, "w");
544c187222hselasky		if (f) {
545c187222hselasky			fprintf(f, "%d\n", getpid());
546c187222hselasky			fclose(f);
547c187222hselasky		} else {
548c187222hselasky			perror("fopen");
549c187222hselasky			exit(1);
550c187222hselasky		}
551c187222hselasky	}
552c187222hselasky
5535115240jeff	close(0);
5545115240jeff	close(1);
5555115240jeff	close(2);
5565115240jeff
5575115240jeff	dup2(fd, 0);
5585115240jeff	dup2(fd, 1);
5595115240jeff	dup2(fd, 2);
5605115240jeff
5615115240jeff	return 0;
5625115240jeff}
5635115240jeff
5645115240jeffint osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm)
5655115240jeff{
5665115240jeff	int console_init_flag = 0;
5675115240jeff
5685115240jeff	if (is_console_enabled(p_opt)) {
5695115240jeff		if (!osm_console_init(p_opt, &p_osm->console, &p_osm->log))
5705115240jeff			console_init_flag = 1;
5715115240jeff	}
5725115240jeff
5735115240jeff	/*
5745115240jeff	   Sit here forever - dwell or do console i/o & cmds
5755115240jeff	 */
5765115240jeff	while (!osm_exit_flag) {
577c187222hselasky		if (console_init_flag) {
578c187222hselasky			if (osm_console(p_osm))
579c187222hselasky				console_init_flag = 0;
580c187222hselasky		} else
5815115240jeff			cl_thread_suspend(10000);
5825115240jeff
5835115240jeff		if (osm_usr1_flag) {
5845115240jeff			osm_usr1_flag = 0;
5855115240jeff			osm_log_reopen_file(&(p_osm->log));
5865115240jeff		}
5875115240jeff		if (osm_hup_flag) {
5885115240jeff			osm_hup_flag = 0;
5895115240jeff			/* a HUP signal should only start a new heavy sweep */
5905115240jeff			p_osm->subn.force_heavy_sweep = TRUE;
5915115240jeff			osm_opensm_sweep(p_osm);
5925115240jeff		}
5935115240jeff	}
5945115240jeff	if (is_console_enabled(p_opt))
5955115240jeff		osm_console_exit(&p_osm->console, &p_osm->log);
5965115240jeff	return 0;
5975115240jeff}
5985115240jeff
599c187222hselasky#define SET_STR_OPT(opt, val) do { \
600c187222hselasky	opt = val ? strdup(val) : NULL ; \
601c187222hselasky} while (0)
602c187222hselasky
6035115240jeffint main(int argc, char *argv[])
6045115240jeff{
6055115240jeff	osm_opensm_t osm;
6065115240jeff	osm_subn_opt_t opt;
6075115240jeff	ib_net64_t sm_key = 0;
6085115240jeff	ib_api_status_t status;
6095115240jeff	uint32_t temp, dbg_lvl;
6105115240jeff	boolean_t run_once_flag = FALSE;
6115115240jeff	int32_t vendor_debug = 0;
612c187222hselasky	int next_option;
6135115240jeff	char *conf_template = NULL;
614c187222hselasky	const char *config_file = NULL;
6155115240jeff	uint32_t val;
6165115240jeff	const char *const short_option =
617c187222hselasky	    "F:c:i:w:O:f:ed:D:g:l:L:s:t:a:u:m:X:R:zM:U:S:P:Y:ANZ:WBIQvVhoryxp:n:q:k:C:G:H:";
6185115240jeff
6195115240jeff	/*
6205115240jeff	   In the array below, the 2nd parameter specifies the number
6215115240jeff	   of arguments as follows:
6225115240jeff	   0: no arguments
6235115240jeff	   1: argument
6245115240jeff	   2: optional
6255115240jeff	 */
6265115240jeff	const struct option long_option[] = {
6275115240jeff		{"version", 0, NULL, 12},
6285115240jeff		{"config", 1, NULL, 'F'},
6295115240jeff		{"create-config", 1, NULL, 'c'},
6305115240jeff		{"debug", 1, NULL, 'd'},
6315115240jeff		{"guid", 1, NULL, 'g'},
6325115240jeff		{"ignore_guids", 1, NULL, 'i'},
633c187222hselasky		{"hop_weights_file", 1, NULL, 'w'},
634c187222hselasky		{"dimn_ports_file", 1, NULL, 'O'},
635c187222hselasky		{"port_search_ordering_file", 1, NULL, 'O'},
6365115240jeff		{"lmc", 1, NULL, 'l'},
6375115240jeff		{"sweep", 1, NULL, 's'},
6385115240jeff		{"timeout", 1, NULL, 't'},
6395115240jeff		{"verbose", 0, NULL, 'v'},
6405115240jeff		{"D", 1, NULL, 'D'},
6415115240jeff		{"log_file", 1, NULL, 'f'},
6425115240jeff		{"log_limit", 1, NULL, 'L'},
6435115240jeff		{"erase_log_file", 0, NULL, 'e'},
6445115240jeff		{"Pconfig", 1, NULL, 'P'},
6455115240jeff		{"no_part_enforce", 0, NULL, 'N'},
646c187222hselasky		{"part_enforce", 1, NULL, 'Z'},
647c187222hselasky		{"allow_both_pkeys", 0, NULL, 'W'},
6485115240jeff		{"qos", 0, NULL, 'Q'},
6495115240jeff		{"qos_policy_file", 1, NULL, 'Y'},
650c187222hselasky		{"congestion_control", 0, NULL, 128},
651c187222hselasky		{"cc_key", 1, NULL, 129},
6525115240jeff		{"maxsmps", 1, NULL, 'n'},
6535115240jeff		{"console", 1, NULL, 'q'},
6545115240jeff		{"V", 0, NULL, 'V'},
6555115240jeff		{"help", 0, NULL, 'h'},
6565115240jeff		{"once", 0, NULL, 'o'},
6575115240jeff		{"reassign_lids", 0, NULL, 'r'},
6585115240jeff		{"priority", 1, NULL, 'p'},
6595115240jeff		{"smkey", 1, NULL, 'k'},
6605115240jeff		{"routing_engine", 1, NULL, 'R'},
6615115240jeff		{"ucast_cache", 0, NULL, 'A'},
6625115240jeff		{"connect_roots", 0, NULL, 'z'},
6635115240jeff		{"lid_matrix_file", 1, NULL, 'M'},
6645115240jeff		{"lfts_file", 1, NULL, 'U'},
6655115240jeff		{"sadb_file", 1, NULL, 'S'},
6665115240jeff		{"root_guid_file", 1, NULL, 'a'},
6675115240jeff		{"cn_guid_file", 1, NULL, 'u'},
668c187222hselasky		{"io_guid_file", 1, NULL, 'G'},
669c187222hselasky		{"port-shifting", 0, NULL, 11},
670c187222hselasky		{"scatter-ports", 1, NULL, 14},
671c187222hselasky		{"max_reverse_hops", 1, NULL, 'H'},
6725115240jeff		{"ids_guid_file", 1, NULL, 'm'},
6735115240jeff		{"guid_routing_order_file", 1, NULL, 'X'},
6745115240jeff		{"stay_on_fatal", 0, NULL, 'y'},
6755115240jeff		{"honor_guid2lid", 0, NULL, 'x'},
676c187222hselasky#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
6775115240jeff		{"console-port", 1, NULL, 'C'},
6785115240jeff#endif
6795115240jeff		{"daemon", 0, NULL, 'B'},
680c187222hselasky		{"pidfile", 1, NULL, 'J'},
6815115240jeff		{"inactive", 0, NULL, 'I'},
6825115240jeff#ifdef ENABLE_OSM_PERF_MGR
6835115240jeff		{"perfmgr", 0, NULL, 1},
6845115240jeff		{"perfmgr_sweep_time_s", 1, NULL, 2},
6855115240jeff#endif
6865115240jeff		{"prefix_routes_file", 1, NULL, 3},
6875115240jeff		{"consolidate_ipv6_snm_req", 0, NULL, 4},
688c187222hselasky		{"do_mesh_analysis", 0, NULL, 5},
689c187222hselasky		{"lash_start_vl", 1, NULL, 6},
690c187222hselasky		{"sm_sl", 1, NULL, 7},
691c187222hselasky		{"retries", 1, NULL, 8},
692c187222hselasky		{"log_prefix", 1, NULL, 9},
693c187222hselasky		{"torus_config", 1, NULL, 10},
694c187222hselasky		{"guid_routing_order_no_scatter", 0, NULL, 13},
6955115240jeff		{NULL, 0, NULL, 0}	/* Required at the end of the array */
6965115240jeff	};
6975115240jeff
698c187222hselasky	/* force stdout to be line-buffered */
699c187222hselasky	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
700c187222hselasky
7015115240jeff	/* Make sure that the opensm and complib were compiled using
7025115240jeff	   same modes (debug/free) */
7035115240jeff	if (osm_is_debug() != cl_is_debug()) {
7045115240jeff		fprintf(stderr,
7055115240jeff			"ERROR: OpenSM and Complib were compiled using different modes\n");
7065115240jeff		fprintf(stderr, "ERROR: OpenSM debug:%d Complib debug:%d \n",
7075115240jeff			osm_is_debug(), cl_is_debug());
7085115240jeff		exit(1);
7095115240jeff	}
7105115240jeff
7115115240jeff	printf("-------------------------------------------------\n");
7125115240jeff	printf("%s\n", OSM_VERSION);
7135115240jeff
714c187222hselasky	do {
715c187222hselasky		next_option = getopt_long_only(argc, argv, short_option,
716c187222hselasky					       long_option, NULL);
717c187222hselasky		switch (next_option) {
718c187222hselasky		case 'F':
719c187222hselasky			config_file = optarg;
720c187222hselasky			printf("Config file is `%s`:\n", config_file);
721c187222hselasky			break;
722c187222hselasky		default:
723c187222hselasky			break;
724c187222hselasky		}
725c187222hselasky	} while (next_option != -1);
726c187222hselasky
727c187222hselasky	optind = 0;		/* reset command line */
728c187222hselasky
729c187222hselasky	if (!config_file)
730c187222hselasky		config_file = OSM_DEFAULT_CONFIG_FILE;
731c187222hselasky
7325115240jeff	osm_subn_set_default_opt(&opt);
7335115240jeff
734c187222hselasky	if (osm_subn_parse_conf_file(config_file, &opt) < 0)
735c187222hselasky		printf("\nFail to parse config file \'%s\'\n", config_file);
7365115240jeff
7375115240jeff	printf("Command Line Arguments:\n");
7385115240jeff	do {
7395115240jeff		next_option = getopt_long_only(argc, argv, short_option,
7405115240jeff					       long_option, NULL);
7415115240jeff		switch (next_option) {
742c187222hselasky		case 12:	/* --version - already printed above */
7435115240jeff			exit(0);
7445115240jeff			break;
7455115240jeff		case 'F':
7465115240jeff			break;
7475115240jeff		case 'c':
7485115240jeff			conf_template = optarg;
7495115240jeff			printf(" Creating config file template \'%s\'.\n",
7505115240jeff			       conf_template);
7515115240jeff			break;
7525115240jeff		case 'o':
7535115240jeff			/*
7545115240jeff			   Run once option.
7555115240jeff			 */
7565115240jeff			run_once_flag = TRUE;
7575115240jeff			printf(" Run Once\n");
7585115240jeff			break;
7595115240jeff
7605115240jeff		case 'r':
7615115240jeff			/*
7625115240jeff			   Reassign LIDs subnet option.
7635115240jeff			 */
7645115240jeff			opt.reassign_lids = TRUE;
7655115240jeff			printf(" Reassign LIDs\n");
7665115240jeff			break;
7675115240jeff
7685115240jeff		case 'i':
7695115240jeff			/*
7705115240jeff			   Specifies ignore guids file.
7715115240jeff			 */
772c187222hselasky			SET_STR_OPT(opt.port_prof_ignore_file, optarg);
7735115240jeff			printf(" Ignore Guids File = %s\n",
7745115240jeff			       opt.port_prof_ignore_file);
7755115240jeff			break;
7765115240jeff
777c187222hselasky		case 'w':
778c187222hselasky			SET_STR_OPT(opt.hop_weights_file, optarg);
779c187222hselasky			printf(" Hop Weights File = %s\n",
780c187222hselasky			       opt.hop_weights_file);
781c187222hselasky			break;
782c187222hselasky
783c187222hselasky		case 'O':
784c187222hselasky			SET_STR_OPT(opt.port_search_ordering_file, optarg);
785c187222hselasky			printf(" Port Search Ordering/Dimension Ports File = %s\n",
786c187222hselasky			       opt.port_search_ordering_file);
787c187222hselasky			break;
788c187222hselasky
7895115240jeff		case 'g':
7905115240jeff			/*
7915115240jeff			   Specifies port guid with which to bind.
7925115240jeff			 */
7935115240jeff			opt.guid = cl_hton64(strtoull(optarg, NULL, 16));
7945115240jeff			if (!opt.guid)
7955115240jeff				/* If guid is 0 - need to display the
7965115240jeff				 * guid list */
7975115240jeff				opt.guid = INVALID_GUID;
7985115240jeff			else
7995115240jeff				printf(" Guid <0x%" PRIx64 ">\n",
8005115240jeff				       cl_hton64(opt.guid));
8015115240jeff			break;
8025115240jeff
8035115240jeff		case 's':
8045115240jeff			val = strtol(optarg, NULL, 0);
8055115240jeff			/* Check that the number is not too large */
8065115240jeff			if (((uint32_t) (val * 1000000)) / 1000000 != val)
8075115240jeff				fprintf(stderr,
8085115240jeff					"ERROR: sweep interval given is too large. Ignoring it.\n");
8095115240jeff			else {
8105115240jeff				opt.sweep_interval = val;
8115115240jeff				printf(" sweep interval = %d\n",
8125115240jeff				       opt.sweep_interval);
8135115240jeff			}
8145115240jeff			break;
8155115240jeff
8165115240jeff		case 't':
817c187222hselasky			val = strtoul(optarg, NULL, 0);
818c187222hselasky			opt.transaction_timeout = strtoul(optarg, NULL, 0);
819c187222hselasky			if (val == 0)
820c187222hselasky				fprintf(stderr, "ERROR: timeout value 0 is invalid. Ignoring it.\n");
821c187222hselasky			else {
822c187222hselasky				opt.transaction_timeout = val;
823c187222hselasky				printf(" Transaction timeout = %u\n",
824c187222hselasky				       opt.transaction_timeout);
825c187222hselasky			}
8265115240jeff			break;
8275115240jeff
8285115240jeff		case 'n':
829c187222hselasky			opt.max_wire_smps = strtoul(optarg, NULL, 0);
830c187222hselasky			if (opt.max_wire_smps == 0 ||
831c187222hselasky			    opt.max_wire_smps > 0x7FFFFFFF)
8325115240jeff				opt.max_wire_smps = 0x7FFFFFFF;
8335115240jeff			printf(" Max wire smp's = %d\n", opt.max_wire_smps);
8345115240jeff			break;
8355115240jeff
8365115240jeff		case 'q':
8375115240jeff			/*
8385115240jeff			 * OpenSM interactive console
8395115240jeff			 */
8405115240jeff			if (strcmp(optarg, OSM_DISABLE_CONSOLE) == 0
8415115240jeff			    || strcmp(optarg, OSM_LOCAL_CONSOLE) == 0
8425115240jeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
8435115240jeff			    || strcmp(optarg, OSM_REMOTE_CONSOLE) == 0
844c187222hselasky#endif
845c187222hselasky#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
8465115240jeff			    || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0
8475115240jeff#endif
8485115240jeff			    )
849c187222hselasky				SET_STR_OPT(opt.console, optarg);
8505115240jeff			else
8515115240jeff				printf("-console %s option not understood\n",
8525115240jeff				       optarg);
8535115240jeff			break;
8545115240jeff
855c187222hselasky#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
8565115240jeff		case 'C':
8575115240jeff			opt.console_port = strtol(optarg, NULL, 0);
8585115240jeff			break;
8595115240jeff#endif
8605115240jeff
8615115240jeff		case 'd':
8625115240jeff			dbg_lvl = strtol(optarg, NULL, 0);
8635115240jeff			printf(" d level = 0x%x\n", dbg_lvl);
8645115240jeff			if (dbg_lvl == 0) {
8655115240jeff				printf(" Debug mode: Ignore Other SMs\n");
8665115240jeff				opt.ignore_other_sm = TRUE;
8675115240jeff			} else if (dbg_lvl == 1) {
8685115240jeff				printf(" Debug mode: Forcing Single Thread\n");
8695115240jeff				opt.single_thread = TRUE;
8705115240jeff			} else if (dbg_lvl == 2) {
8715115240jeff				printf(" Debug mode: Force Log Flush\n");
8725115240jeff				opt.force_log_flush = TRUE;
8735115240jeff			} else if (dbg_lvl == 3) {
8745115240jeff				printf
8755115240jeff				    (" Debug mode: Disable multicast support\n");
8765115240jeff				opt.disable_multicast = TRUE;
8775115240jeff			}
8785115240jeff			/*
8795115240jeff			 * NOTE: Debug level 4 used to be used for memory
8805115240jeff			 * tracking but this is now deprecated
8815115240jeff			 */
8825115240jeff			else if (dbg_lvl == 5)
8835115240jeff				vendor_debug++;
8845115240jeff			else
8855115240jeff				printf(" OpenSM: Unknown debug option %d"
8865115240jeff				       " ignored\n", dbg_lvl);
8875115240jeff			break;
8885115240jeff
8895115240jeff		case 'l':
890c187222hselasky			temp = strtoul(optarg, NULL, 0);
8915115240jeff			if (temp > 7) {
8925115240jeff				fprintf(stderr,
8935115240jeff					"ERROR: LMC must be 7 or less.\n");
894c187222hselasky				return -1;
8955115240jeff			}
8965115240jeff			opt.lmc = (uint8_t) temp;
8975115240jeff			printf(" LMC = %d\n", temp);
8985115240jeff			break;
8995115240jeff
9005115240jeff		case 'D':
9015115240jeff			opt.log_flags = strtol(optarg, NULL, 0);
9025115240jeff			printf(" verbose option -D = 0x%x\n", opt.log_flags);
9035115240jeff			break;
9045115240jeff
9055115240jeff		case 'f':
906c187222hselasky			SET_STR_OPT(opt.log_file, optarg);
9075115240jeff			break;
9085115240jeff
9095115240jeff		case 'L':
910c187222hselasky			opt.log_max_size = strtoul(optarg, NULL, 0);
911c187222hselasky			printf(" Log file max size is %u MBytes\n",
9125115240jeff			       opt.log_max_size);
9135115240jeff			break;
9145115240jeff
9155115240jeff		case 'e':
9165115240jeff			opt.accum_log_file = FALSE;
9175115240jeff			printf(" Creating new log file\n");
9185115240jeff			break;
9195115240jeff
920c187222hselasky		case 'J':
921c187222hselasky			pidfile = optarg;
922c187222hselasky			break;
923c187222hselasky
9245115240jeff		case 'P':
925c187222hselasky			SET_STR_OPT(opt.partition_config_file, optarg);
9265115240jeff			break;
9275115240jeff
9285115240jeff		case 'N':
9295115240jeff			opt.no_partition_enforcement = TRUE;
9305115240jeff			break;
9315115240jeff
932c187222hselasky		case 'Z':
933c187222hselasky			if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0
934c187222hselasky			    || strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0
935c187222hselasky			    || strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0
936c187222hselasky			    || strcmp(optarg, OSM_PARTITION_ENFORCE_OFF) == 0) {
937c187222hselasky				SET_STR_OPT(opt.part_enforce, optarg);
938c187222hselasky				if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0)
939c187222hselasky					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH;
940c187222hselasky				else if (strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0)
941c187222hselasky					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_IN;
942c187222hselasky				else if (strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0)
943c187222hselasky					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OUT;
944c187222hselasky				else
945c187222hselasky					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF;
946c187222hselasky			} else
947c187222hselasky				printf("-part_enforce %s option not understood\n",
948c187222hselasky				       optarg);
949c187222hselasky			break;
950c187222hselasky
951c187222hselasky		case 'W':
952c187222hselasky			opt.allow_both_pkeys = TRUE;
953c187222hselasky			break;
954c187222hselasky
9555115240jeff		case 'Q':
9565115240jeff			opt.qos = TRUE;
9575115240jeff			break;
9585115240jeff
9595115240jeff		case 'Y':
960c187222hselasky			SET_STR_OPT(opt.qos_policy_file, optarg);
9615115240jeff			printf(" QoS policy file \'%s\'\n", optarg);
9625115240jeff			break;
9635115240jeff
964c187222hselasky		case 128:
965c187222hselasky			opt.congestion_control = TRUE;
966c187222hselasky			break;
967c187222hselasky
968c187222hselasky		case 129:
969c187222hselasky			opt.cc_key = strtoull(optarg, NULL, 0);
970c187222hselasky			printf(" CC Key 0x%" PRIx64 "\n", opt.cc_key);
971c187222hselasky			break;
972c187222hselasky
9735115240jeff		case 'y':
9745115240jeff			opt.exit_on_fatal = FALSE;
9755115240jeff			printf(" Staying on fatal initialization errors\n");
9765115240jeff			break;
9775115240jeff
9785115240jeff		case 'v':
9795115240jeff			opt.log_flags = (opt.log_flags << 1) | 1;
9805115240jeff			printf(" Verbose option -v (log flags = 0x%X)\n",
9815115240jeff			       opt.log_flags);
9825115240jeff			break;
9835115240jeff
9845115240jeff		case 'V':
9855115240jeff			opt.log_flags = 0xFF;
9865115240jeff			opt.force_log_flush = TRUE;
9875115240jeff			printf(" Big V selected\n");
9885115240jeff			break;
9895115240jeff
9905115240jeff		case 'p':
991c187222hselasky			temp = strtoul(optarg, NULL, 0);
992c187222hselasky			if (temp > 15) {
9935115240jeff				fprintf(stderr,
9945115240jeff					"ERROR: priority must be between 0 and 15\n");
995c187222hselasky				return -1;
9965115240jeff			}
9975115240jeff			opt.sm_priority = (uint8_t) temp;
9985115240jeff			printf(" Priority = %d\n", temp);
9995115240jeff			break;
10005115240jeff
10015115240jeff		case 'k':
10025115240jeff			sm_key = cl_hton64(strtoull(optarg, NULL, 16));
10035115240jeff			printf(" SM Key <0x%" PRIx64 ">\n", cl_hton64(sm_key));
10045115240jeff			opt.sm_key = sm_key;
10055115240jeff			break;
10065115240jeff
10075115240jeff		case 'R':
1008c187222hselasky			SET_STR_OPT(opt.routing_engine_names, optarg);
10095115240jeff			printf(" Activate \'%s\' routing engine(s)\n", optarg);
10105115240jeff			break;
10115115240jeff
10125115240jeff		case 'z':
10135115240jeff			opt.connect_roots = TRUE;
10145115240jeff			printf(" Connect roots option is on\n");
10155115240jeff			break;
10165115240jeff
10175115240jeff		case 'A':
10185115240jeff			opt.use_ucast_cache = TRUE;
10195115240jeff			printf(" Unicast routing cache option is on\n");
10205115240jeff			break;
10215115240jeff
10225115240jeff		case 'M':
1023c187222hselasky			SET_STR_OPT(opt.lid_matrix_dump_file, optarg);
10245115240jeff			printf(" Lid matrix dump file is \'%s\'\n", optarg);
10255115240jeff			break;
10265115240jeff
10275115240jeff		case 'U':
1028c187222hselasky			SET_STR_OPT(opt.lfts_file, optarg);
10295115240jeff			printf(" LFTs file is \'%s\'\n", optarg);
10305115240jeff			break;
10315115240jeff
10325115240jeff		case 'S':
1033c187222hselasky			SET_STR_OPT(opt.sa_db_file, optarg);
10345115240jeff			printf(" SA DB file is \'%s\'\n", optarg);
10355115240jeff			break;
10365115240jeff
10375115240jeff		case 'a':
1038c187222hselasky			SET_STR_OPT(opt.root_guid_file, optarg);
10395115240jeff			printf(" Root Guid File: %s\n", opt.root_guid_file);
10405115240jeff			break;
10415115240jeff
10425115240jeff		case 'u':
1043c187222hselasky			SET_STR_OPT(opt.cn_guid_file, optarg);
10445115240jeff			printf(" Compute Node Guid File: %s\n",
10455115240jeff			       opt.cn_guid_file);
10465115240jeff			break;
10475115240jeff
1048c187222hselasky		case 'G':
1049c187222hselasky			SET_STR_OPT(opt.io_guid_file, optarg);
1050c187222hselasky			printf(" I/O Node Guid File: %s\n", opt.io_guid_file);
1051c187222hselasky			break;
1052c187222hselasky		case 11:
1053c187222hselasky			opt.port_shifting = TRUE;
1054c187222hselasky			printf(" Port Shifting is on\n");
1055c187222hselasky			break;
1056c187222hselasky		case 14:
1057c187222hselasky			opt.scatter_ports = strtol(optarg, NULL, 0);
1058c187222hselasky			printf(" Scatter Ports is on\n");
1059c187222hselasky			break;
1060c187222hselasky		case 'H':
1061c187222hselasky			opt.max_reverse_hops = atoi(optarg);
1062c187222hselasky			printf(" Max Reverse Hops: %d\n", opt.max_reverse_hops);
1063c187222hselasky			break;
10645115240jeff		case 'm':
1065c187222hselasky			SET_STR_OPT(opt.ids_guid_file, optarg);
10665115240jeff			printf(" IDs Guid File: %s\n", opt.ids_guid_file);
10675115240jeff			break;
10685115240jeff
10695115240jeff		case 'X':
1070c187222hselasky			SET_STR_OPT(opt.guid_routing_order_file, optarg);
1071c187222hselasky			printf(" GUID Routing Order File: %s\n",
1072c187222hselasky			       opt.guid_routing_order_file);
10735115240jeff			break;
10745115240jeff
10755115240jeff		case 'x':
10765115240jeff			opt.honor_guid2lid_file = TRUE;
10775115240jeff			printf(" Honor guid2lid file, if possible\n");
10785115240jeff			break;
10795115240jeff
10805115240jeff		case 'B':
10815115240jeff			opt.daemon = TRUE;
10825115240jeff			printf(" Daemon mode\n");
10835115240jeff			break;
10845115240jeff
10855115240jeff		case 'I':
10865115240jeff			opt.sm_inactive = TRUE;
10875115240jeff			printf(" SM started in inactive state\n");
10885115240jeff			break;
10895115240jeff
10905115240jeff#ifdef ENABLE_OSM_PERF_MGR
10915115240jeff		case 1:
10925115240jeff			opt.perfmgr = TRUE;
10935115240jeff			break;
10945115240jeff		case 2:
10955115240jeff			opt.perfmgr_sweep_time_s = atoi(optarg);
10965115240jeff			break;
10975115240jeff#endif				/* ENABLE_OSM_PERF_MGR */
10985115240jeff
10995115240jeff		case 3:
1100c187222hselasky			SET_STR_OPT(opt.prefix_routes_file, optarg);
11015115240jeff			break;
11025115240jeff		case 4:
11035115240jeff			opt.consolidate_ipv6_snm_req = TRUE;
11045115240jeff			break;
1105c187222hselasky		case 5:
1106c187222hselasky			opt.do_mesh_analysis = TRUE;
1107c187222hselasky			break;
1108c187222hselasky		case 6:
1109c187222hselasky			temp = strtoul(optarg, NULL, 0);
1110c187222hselasky			if (temp >= IB_MAX_NUM_VLS) {
1111c187222hselasky				fprintf(stderr,
1112c187222hselasky					"ERROR: starting lash vl must be between 0 and 15\n");
1113c187222hselasky				return -1;
1114c187222hselasky			}
1115c187222hselasky			opt.lash_start_vl = (uint8_t) temp;
1116c187222hselasky			printf(" LASH starting VL = %d\n", opt.lash_start_vl);
1117c187222hselasky			break;
1118c187222hselasky		case 7:
1119c187222hselasky			temp = strtoul(optarg, NULL, 0);
1120c187222hselasky			if (temp > 15) {
1121c187222hselasky				fprintf(stderr,
1122c187222hselasky					"ERROR: SM's SL must be between 0 and 15\n");
1123c187222hselasky				return -1;
1124c187222hselasky			}
1125c187222hselasky			opt.sm_sl = (uint8_t) temp;
1126c187222hselasky			printf(" SMSL = %d\n", opt.sm_sl);
1127c187222hselasky			break;
1128c187222hselasky		case 8:
1129c187222hselasky			opt.transaction_retries = strtoul(optarg, NULL, 0);
1130c187222hselasky			printf(" Transaction retries = %u\n",
1131c187222hselasky			       opt.transaction_retries);
1132c187222hselasky			break;
1133c187222hselasky		case 9:
1134