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 *
6219820Sjeff * This software is available to you under a choice of one of two
7219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
8219820Sjeff * General Public License (GPL) Version 2, available from the file
9219820Sjeff * COPYING in the main directory of this source tree, or the
10219820Sjeff * OpenIB.org BSD license below:
11219820Sjeff *
12219820Sjeff *     Redistribution and use in source and binary forms, with or
13219820Sjeff *     without modification, are permitted provided that the following
14219820Sjeff *     conditions are met:
15219820Sjeff *
16219820Sjeff *      - Redistributions of source code must retain the above
17219820Sjeff *        copyright notice, this list of conditions and the following
18219820Sjeff *        disclaimer.
19219820Sjeff *
20219820Sjeff *      - Redistributions in binary form must reproduce the above
21219820Sjeff *        copyright notice, this list of conditions and the following
22219820Sjeff *        disclaimer in the documentation and/or other materials
23219820Sjeff *        provided with the distribution.
24219820Sjeff *
25219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32219820Sjeff * SOFTWARE.
33219820Sjeff *
34219820Sjeff */
35219820Sjeff
36219820Sjeff/*
37219820Sjeff * Abstract:
38219820Sjeff *    Command line interface for opensm.
39219820Sjeff */
40219820Sjeff
41219820Sjeff#if HAVE_CONFIG_H
42219820Sjeff#  include <config.h>
43219820Sjeff#endif				/* HAVE_CONFIG_H */
44219820Sjeff
45219820Sjeff#include <stdio.h>
46219820Sjeff#include <stdlib.h>
47219820Sjeff#include <getopt.h>
48219820Sjeff#include <unistd.h>
49219820Sjeff#include <signal.h>
50219820Sjeff#include <sys/types.h>
51219820Sjeff#include <sys/stat.h>
52219820Sjeff#include <fcntl.h>
53219820Sjeff#include <complib/cl_types.h>
54219820Sjeff#include <complib/cl_debug.h>
55219820Sjeff#include <vendor/osm_vendor_api.h>
56219820Sjeff#include <opensm/osm_version.h>
57219820Sjeff#include <opensm/osm_opensm.h>
58219820Sjeff#include <opensm/osm_console.h>
59219820Sjeff#include <opensm/osm_console_io.h>
60219820Sjeff#include <opensm/osm_perfmgr.h>
61219820Sjeff
62219820Sjeffvolatile unsigned int osm_exit_flag = 0;
63219820Sjeff
64219820Sjeffstatic volatile unsigned int osm_hup_flag = 0;
65219820Sjeffstatic volatile unsigned int osm_usr1_flag = 0;
66219820Sjeff
67219820Sjeff#define GUID_ARRAY_SIZE 64
68219820Sjeff#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
69219820Sjeff
70219820Sjeffstatic void mark_exit_flag(int signum)
71219820Sjeff{
72219820Sjeff	if (!osm_exit_flag)
73219820Sjeff		printf("OpenSM: Got signal %d - exiting...\n", signum);
74219820Sjeff	osm_exit_flag = 1;
75219820Sjeff}
76219820Sjeff
77219820Sjeffstatic void mark_hup_flag(int signum)
78219820Sjeff{
79219820Sjeff	osm_hup_flag = 1;
80219820Sjeff}
81219820Sjeff
82219820Sjeffstatic void mark_usr1_flag(int signum)
83219820Sjeff{
84219820Sjeff	osm_usr1_flag = 1;
85219820Sjeff}
86219820Sjeff
87219820Sjeffstatic sigset_t saved_sigset;
88219820Sjeff
89219820Sjeffstatic void block_signals()
90219820Sjeff{
91219820Sjeff	sigset_t set;
92219820Sjeff
93219820Sjeff	sigemptyset(&set);
94219820Sjeff	sigaddset(&set, SIGINT);
95219820Sjeff	sigaddset(&set, SIGTERM);
96219820Sjeff	sigaddset(&set, SIGHUP);
97219820Sjeff#ifndef HAVE_OLD_LINUX_THREADS
98219820Sjeff	sigaddset(&set, SIGUSR1);
99219820Sjeff#endif
100219820Sjeff	pthread_sigmask(SIG_SETMASK, &set, &saved_sigset);
101219820Sjeff}
102219820Sjeff
103219820Sjeffstatic void setup_signals()
104219820Sjeff{
105219820Sjeff	struct sigaction act;
106219820Sjeff
107219820Sjeff	sigemptyset(&act.sa_mask);
108219820Sjeff	act.sa_handler = mark_exit_flag;
109219820Sjeff	act.sa_flags = 0;
110219820Sjeff	sigaction(SIGINT, &act, NULL);
111219820Sjeff	sigaction(SIGTERM, &act, NULL);
112219820Sjeff	act.sa_handler = mark_hup_flag;
113219820Sjeff	sigaction(SIGHUP, &act, NULL);
114219820Sjeff	sigaction(SIGCONT, &act, NULL);
115219820Sjeff#ifndef HAVE_OLD_LINUX_THREADS
116219820Sjeff	act.sa_handler = mark_usr1_flag;
117219820Sjeff	sigaction(SIGUSR1, &act, NULL);
118219820Sjeff#endif
119219820Sjeff	pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL);
120219820Sjeff}
121219820Sjeff
122219820Sjeff/**********************************************************************
123219820Sjeff **********************************************************************/
124219820Sjeff
125219820Sjeffstatic void show_usage(void)
126219820Sjeff{
127219820Sjeff	printf("\n------- OpenSM - Usage and options ----------------------\n");
128219820Sjeff	printf("Usage:   opensm [options]\n");
129219820Sjeff	printf("Options:\n");
130219820Sjeff	printf("--version\n          Prints OpenSM version and exits.\n\n");
131219820Sjeff	printf("--config, -F <file-name>\n"
132219820Sjeff	       "          The name of the OpenSM config file. When not specified\n"
133219820Sjeff	       "          " OSM_DEFAULT_CONFIG_FILE " will be used (if exists).\n\n");
134219820Sjeff	printf("--create-config, -c <file-name>\n"
135219820Sjeff	       "          OpenSM will dump its configuration to the specified file and exit.\n"
136219820Sjeff	       "          This is a way to generate OpenSM configuration file template.\n\n");
137219820Sjeff	printf("--guid, -g <GUID in hex>\n"
138219820Sjeff	       "          This option specifies the local port GUID value\n"
139219820Sjeff	       "          with which OpenSM should bind.  OpenSM may be\n"
140219820Sjeff	       "          bound to 1 port at a time.\n"
141219820Sjeff	       "          If GUID given is 0, OpenSM displays a list\n"
142219820Sjeff	       "          of possible port GUIDs and waits for user input.\n"
143219820Sjeff	       "          Without -g, OpenSM tries to use the default port.\n\n");
144219820Sjeff	printf("--lmc, -l <LMC>\n"
145219820Sjeff	       "          This option specifies the subnet's LMC value.\n"
146219820Sjeff	       "          The number of LIDs assigned to each port is 2^LMC.\n"
147219820Sjeff	       "          The LMC value must be in the range 0-7.\n"
148219820Sjeff	       "          LMC values > 0 allow multiple paths between ports.\n"
149219820Sjeff	       "          LMC values > 0 should only be used if the subnet\n"
150219820Sjeff	       "          topology actually provides multiple paths between\n"
151219820Sjeff	       "          ports, i.e. multiple interconnects between switches.\n"
152219820Sjeff	       "          Without -l, OpenSM defaults to LMC = 0, which allows\n"
153219820Sjeff	       "          one path between any two ports.\n\n");
154219820Sjeff	printf("--priority, -p <PRIORITY>\n"
155219820Sjeff	       "          This option specifies the SM's PRIORITY.\n"
156219820Sjeff	       "          This will effect the handover cases, where master\n"
157219820Sjeff	       "          is chosen by priority and GUID.  Range goes\n"
158219820Sjeff	       "          from 0 (lowest priority) to 15 (highest).\n\n");
159219820Sjeff	printf("--smkey, -k <SM_Key>\n"
160219820Sjeff	       "          This option specifies the SM's SM_Key (64 bits).\n"
161219820Sjeff	       "          This will effect SM authentication.\n"
162219820Sjeff	       "          Note that OpenSM version 3.2.1 and below used the\n"
163219820Sjeff	       "          default value '1' in a host byte order, it is fixed\n"
164219820Sjeff	       "          now but you may need this option to interoperate\n"
165219820Sjeff	       "          with old OpenSM running on a little endian machine.\n\n");
166219820Sjeff	printf("--reassign_lids, -r\n"
167219820Sjeff	       "          This option causes OpenSM to reassign LIDs to all\n"
168219820Sjeff	       "          end nodes. Specifying -r on a running subnet\n"
169219820Sjeff	       "          may disrupt subnet traffic.\n"
170219820Sjeff	       "          Without -r, OpenSM attempts to preserve existing\n"
171219820Sjeff	       "          LID assignments resolving multiple use of same LID.\n\n");
172219820Sjeff	printf("--routing_engine, -R <engine name>\n"
173219820Sjeff	       "          This option chooses routing engine(s) to use instead of default\n"
174219820Sjeff	       "          Min Hop algorithm.  Multiple routing engines can be specified\n"
175219820Sjeff	       "          separated by commas so that specific ordering of routing\n"
176219820Sjeff	       "          algorithms will be tried if earlier routing engines fail.\n"
177219820Sjeff	       "          Supported engines: updn, file, ftree, lash, dor\n\n");
178219820Sjeff	printf("--connect_roots, -z\n"
179219820Sjeff	       "          This option enforces a routing engine (currently\n"
180219820Sjeff	       "          up/down only) to make connectivity between root switches\n"
181219820Sjeff	       "          and in this way be IBA compliant. In many cases,\n"
182219820Sjeff	       "          this can violate \"pure\" deadlock free algorithm, so\n"
183219820Sjeff	       "          use it carefully.\n\n");
184219820Sjeff	printf("--ucast_cache, -A\n"
185219820Sjeff	       "          This option enables unicast routing cache to prevent\n"
186219820Sjeff	       "          routing recalculation (which is a heavy task in a\n"
187219820Sjeff	       "          large cluster) when there was no topology change\n"
188219820Sjeff	       "          detected during the heavy sweep, or when the topology\n"
189219820Sjeff	       "          change does not require new routing calculation,\n"
190219820Sjeff	       "          e.g. in case of host reboot.\n"
191219820Sjeff	       "          This option becomes very handy when the cluster size\n"
192219820Sjeff	       "          is thousands of nodes.\n\n");
193219820Sjeff	printf("--lid_matrix_file, -M <file name>\n"
194219820Sjeff	       "          This option specifies the name of the lid matrix dump file\n"
195219820Sjeff	       "          from where switch lid matrices (min hops tables will be\n"
196219820Sjeff	       "          loaded.\n\n");
197219820Sjeff	printf("--lfts_file, -U <file name>\n"
198219820Sjeff	       "          This option specifies the name of the LFTs file\n"
199219820Sjeff	       "          from where switch forwarding tables will be loaded.\n\n");
200219820Sjeff	printf("--sadb_file, -S <file name>\n"
201219820Sjeff	       "          This option specifies the name of the SA DB dump file\n"
202219820Sjeff	       "          from where SA database will be loaded.\n\n");
203219820Sjeff	printf("--root_guid_file, -a <path to file>\n"
204219820Sjeff	       "          Set the root nodes for the Up/Down or Fat-Tree routing\n"
205219820Sjeff	       "          algorithm to the guids provided in the given file (one\n"
206219820Sjeff	       "          to a line)\n" "\n");
207219820Sjeff	printf("--cn_guid_file, -u <path to file>\n"
208219820Sjeff	       "          Set the compute nodes for the Fat-Tree routing algorithm\n"
209219820Sjeff	       "          to the guids provided in the given file (one to a line)\n\n");
210219820Sjeff	printf("--ids_guid_file, -m <path to file>\n"
211219820Sjeff	       "          Name of the map file with set of the IDs which will be used\n"
212219820Sjeff	       "          by Up/Down routing algorithm instead of node GUIDs\n"
213219820Sjeff	       "          (format: <guid> <id> per line)\n\n");
214219820Sjeff	printf("--guid_routing_order_file, -X <path to file>\n"
215219820Sjeff	       "          Set the order port guids will be routed for the MinHop\n"
216219820Sjeff	       "          and Up/Down routing algorithms to the guids provided in the\n"
217219820Sjeff	       "          given file (one to a line)\n\n");
218219820Sjeff	printf("--once, -o\n"
219219820Sjeff	       "          This option causes OpenSM to configure the subnet\n"
220219820Sjeff	       "          once, then exit.  Ports remain in the ACTIVE state.\n\n");
221219820Sjeff	printf("--sweep, -s <interval>\n"
222219820Sjeff	       "          This option specifies the number of seconds between\n"
223219820Sjeff	       "          subnet sweeps.  Specifying -s 0 disables sweeping.\n"
224219820Sjeff	       "          Without -s, OpenSM defaults to a sweep interval of\n"
225219820Sjeff	       "          10 seconds.\n\n");
226219820Sjeff	printf("--timeout, -t <milliseconds>\n"
227219820Sjeff	       "          This option specifies the time in milliseconds\n"
228219820Sjeff	       "          used for transaction timeouts.\n"
229219820Sjeff	       "          Specifying -t 0 disables timeouts.\n"
230219820Sjeff	       "          Without -t, OpenSM defaults to a timeout value of\n"
231219820Sjeff	       "          200 milliseconds.\n\n");
232219820Sjeff	printf("--maxsmps, -n <number>\n"
233219820Sjeff	       "          This option specifies the number of VL15 SMP MADs\n"
234219820Sjeff	       "          allowed on the wire at any one time.\n"
235219820Sjeff	       "          Specifying --maxsmps 0 allows unlimited outstanding\n"
236219820Sjeff	       "          SMPs.\n"
237219820Sjeff	       "          Without --maxsmps, OpenSM defaults to a maximum of\n"
238219820Sjeff	       "          4 outstanding SMPs.\n\n");
239219820Sjeff	printf("--console, -q [off|local"
240219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
241219820Sjeff	       "|socket|loopback"
242219820Sjeff#endif
243219820Sjeff	       "]\n          This option activates the OpenSM console (default off).\n\n");
244219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
245219820Sjeff	printf("--console-port, -C <port>\n"
246219820Sjeff	       "          Specify an alternate telnet port for the console (default %d).\n\n",
247219820Sjeff	       OSM_DEFAULT_CONSOLE_PORT);
248219820Sjeff#endif
249219820Sjeff	printf("--ignore-guids, -i <equalize-ignore-guids-file>\n"
250219820Sjeff	       "          This option provides the means to define a set of ports\n"
251219820Sjeff	       "          (by guid) that will be ignored by the link load\n"
252219820Sjeff	       "          equalization algorithm.\n\n");
253219820Sjeff	printf("--honor_guid2lid, -x\n"
254219820Sjeff	       "          This option forces OpenSM to honor the guid2lid file,\n"
255219820Sjeff	       "          when it comes out of Standby state, if such file exists\n"
256219820Sjeff	       "          under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n");
257219820Sjeff	printf("--log_file, -f <log-file-name>\n"
258219820Sjeff	       "          This option defines the log to be the given file.\n"
259219820Sjeff	       "          By default, the log goes to /var/log/opensm.log.\n"
260219820Sjeff	       "          For the log to go to standard output use -f stdout.\n\n");
261219820Sjeff	printf("--log_limit, -L <size in MB>\n"
262219820Sjeff	       "          This option defines maximal log file size in MB. When\n"
263219820Sjeff	       "          specified the log file will be truncated upon reaching\n"
264219820Sjeff	       "          this limit.\n\n");
265219820Sjeff	printf("--erase_log_file, -e\n"
266219820Sjeff	       "          This option will cause deletion of the log file\n"
267219820Sjeff	       "          (if it previously exists). By default, the log file\n"
268219820Sjeff	       "          is accumulative.\n\n");
269219820Sjeff	printf("--Pconfig, -P <partition-config-file>\n"
270219820Sjeff	       "          This option defines the optional partition configuration file.\n"
271219820Sjeff	       "          The default name is \'"
272219820Sjeff	       OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n");
273219820Sjeff	printf("--no_part_enforce, -N\n"
274219820Sjeff	       "          This option disables partition enforcement on switch external ports.\n\n");
275219820Sjeff	printf("--qos, -Q\n" "          This option enables QoS setup.\n\n");
276219820Sjeff	printf("--qos_policy_file, -Y <QoS-policy-file>\n"
277219820Sjeff	       "          This option defines the optional QoS policy file.\n"
278219820Sjeff	       "          The default name is \'" OSM_DEFAULT_QOS_POLICY_FILE
279219820Sjeff	       "\'.\n\n");
280219820Sjeff	printf("--stay_on_fatal, -y\n"
281219820Sjeff	       "          This option will cause SM not to exit on fatal initialization\n"
282219820Sjeff	       "          issues: if SM discovers duplicated guids or 12x link with\n"
283219820Sjeff	       "          lane reversal badly configured.\n"
284219820Sjeff	       "          By default, the SM will exit on these errors.\n\n");
285219820Sjeff	printf("--daemon, -B\n"
286219820Sjeff	       "          Run in daemon mode - OpenSM will run in the background.\n\n");
287219820Sjeff	printf("--inactive, -I\n"
288219820Sjeff	       "           Start SM in inactive rather than normal init SM state.\n\n");
289219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
290219820Sjeff	printf("--perfmgr\n" "           Start with PerfMgr enabled.\n\n");
291219820Sjeff	printf("--perfmgr_sweep_time_s <sec.>\n"
292219820Sjeff	       "           PerfMgr sweep interval in seconds.\n\n");
293219820Sjeff#endif
294219820Sjeff	printf("--prefix_routes_file <path to file>\n"
295219820Sjeff	       "          This option specifies the prefix routes file.\n"
296219820Sjeff	       "          Prefix routes control how the SA responds to path record\n"
297219820Sjeff	       "          queries for off-subnet DGIDs.  Default file is:\n"
298219820Sjeff	       "              " OSM_DEFAULT_PREFIX_ROUTES_FILE "\n\n");
299219820Sjeff	printf("--consolidate_ipv6_snm_req\n"
300219820Sjeff	       "          Consolidate IPv6 Solicited Node Multicast group joins\n"
301219820Sjeff	       "          into 1 IB multicast group.\n\n");
302219820Sjeff	printf("--verbose, -v\n"
303219820Sjeff	       "          This option increases the log verbosity level.\n"
304219820Sjeff	       "          The -v option may be specified multiple times\n"
305219820Sjeff	       "          to further increase the verbosity level.\n"
306219820Sjeff	       "          See the -D option for more information about\n"
307219820Sjeff	       "          log verbosity.\n\n");
308219820Sjeff	printf("--V, -V\n"
309219820Sjeff	       "          This option sets the maximum verbosity level and\n"
310219820Sjeff	       "          forces log flushing.\n"
311219820Sjeff	       "          The -V is equivalent to '-D 0xFF -d 2'.\n"
312219820Sjeff	       "          See the -D option for more information about\n"
313219820Sjeff	       "          log verbosity.\n\n");
314219820Sjeff	printf("--D, -D <flags>\n"
315219820Sjeff	       "          This option sets the log verbosity level.\n"
316219820Sjeff	       "          A flags field must follow the -D option.\n"
317219820Sjeff	       "          A bit set/clear in the flags enables/disables a\n"
318219820Sjeff	       "          specific log level as follows:\n"
319219820Sjeff	       "          BIT    LOG LEVEL ENABLED\n"
320219820Sjeff	       "          ----   -----------------\n"
321219820Sjeff	       "          0x01 - ERROR (error messages)\n"
322219820Sjeff	       "          0x02 - INFO (basic messages, low volume)\n"
323219820Sjeff	       "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
324219820Sjeff	       "          0x08 - DEBUG (diagnostic, high volume)\n"
325219820Sjeff	       "          0x10 - FUNCS (function entry/exit, very high volume)\n"
326219820Sjeff	       "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
327219820Sjeff	       "          0x40 - ROUTING (dump FDB routing information)\n"
328219820Sjeff	       "          0x80 - currently unused.\n"
329219820Sjeff	       "          Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
330219820Sjeff	       "          Specifying -D 0 disables all messages.\n"
331219820Sjeff	       "          Specifying -D 0xFF enables all messages (see -V).\n"
332219820Sjeff	       "          High verbosity levels may require increasing\n"
333219820Sjeff	       "          the transaction timeout with the -t option.\n\n");
334219820Sjeff	printf("--debug, -d <number>\n"
335219820Sjeff	       "          This option specifies a debug option.\n"
336219820Sjeff	       "          These options are not normally needed.\n"
337219820Sjeff	       "          The number following -d selects the debug\n"
338219820Sjeff	       "          option to enable as follows:\n"
339219820Sjeff	       "          OPT   Description\n"
340219820Sjeff	       "          ---    -----------------\n"
341219820Sjeff	       "          -d0  - Ignore other SM nodes\n"
342219820Sjeff	       "          -d1  - Force single threaded dispatching\n"
343219820Sjeff	       "          -d2  - Force log flushing after each log message\n"
344219820Sjeff	       "          -d3  - Disable multicast support\n"
345219820Sjeff	       "          -d10 - Put OpenSM in testability mode\n"
346219820Sjeff	       "          Without -d, no debug options are enabled\n\n");
347219820Sjeff	printf("--help, -h, -?\n"
348219820Sjeff	       "          Display this usage info then exit.\n\n");
349219820Sjeff	fflush(stdout);
350219820Sjeff	exit(2);
351219820Sjeff}
352219820Sjeff
353219820Sjeff/**********************************************************************
354219820Sjeff **********************************************************************/
355219820Sjeffstatic ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid)
356219820Sjeff{
357219820Sjeff	ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
358219820Sjeff	uint32_t num_ports = GUID_ARRAY_SIZE;
359219820Sjeff	char junk[128];
360219820Sjeff	uint32_t i, choice = 0;
361219820Sjeff	boolean_t done_flag = FALSE;
362219820Sjeff	ib_api_status_t status;
363219820Sjeff
364219820Sjeff	/*
365219820Sjeff	   Call the transport layer for a list of local port
366219820Sjeff	   GUID values.
367219820Sjeff	 */
368219820Sjeff	status =
369219820Sjeff	    osm_vendor_get_all_port_attr(p_osm->p_vendor, attr_array,
370219820Sjeff					 &num_ports);
371219820Sjeff	if (status != IB_SUCCESS) {
372219820Sjeff		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
373219820Sjeff		       status);
374219820Sjeff		return (0);
375219820Sjeff	}
376219820Sjeff
377219820Sjeff	/* if num_ports is 0 - return 0 */
378219820Sjeff	if (num_ports == 0) {
379219820Sjeff		printf("\nNo local ports detected!\n");
380219820Sjeff		return (0);
381219820Sjeff	}
382219820Sjeff	/* If num_ports is 1, then there is only one possible port to use.
383219820Sjeff	 * Use it. */
384219820Sjeff	if (num_ports == 1) {
385219820Sjeff		printf("Using default GUID 0x%" PRIx64 "\n",
386219820Sjeff		       cl_hton64(attr_array[0].port_guid));
387219820Sjeff		return (attr_array[0].port_guid);
388219820Sjeff	}
389219820Sjeff	/* If port_guid is 0 - use the first connected port */
390219820Sjeff	if (port_guid == 0) {
391219820Sjeff		for (i = 0; i < num_ports; i++)
392219820Sjeff			if (attr_array[i].link_state > IB_LINK_DOWN)
393219820Sjeff				break;
394219820Sjeff		if (i == num_ports)
395219820Sjeff			i = 0;
396219820Sjeff		printf("Using default GUID 0x%" PRIx64 "\n",
397219820Sjeff		       cl_hton64(attr_array[i].port_guid));
398219820Sjeff		return (attr_array[i].port_guid);
399219820Sjeff	}
400219820Sjeff
401219820Sjeff	if (p_osm->subn.opt.daemon)
402219820Sjeff		return 0;
403219820Sjeff
404219820Sjeff	/* More than one possible port - list all ports and let the user
405219820Sjeff	 * to choose. */
406219820Sjeff	while (done_flag == FALSE) {
407219820Sjeff		printf("\nChoose a local port number with which to bind:\n\n");
408219820Sjeff		for (i = 0; i < num_ports; i++)
409219820Sjeff			/* Print the index + 1 since by convention, port
410219820Sjeff			 * numbers start with 1 on host channel adapters. */
411219820Sjeff			printf("\t%u: GUID 0x%" PRIx64
412219820Sjeff			       ", lid %u, state %s\n", i + 1,
413219820Sjeff			       cl_ntoh64(attr_array[i].port_guid),
414219820Sjeff			       attr_array[i].lid,
415219820Sjeff			       ib_get_port_state_str(attr_array[i].link_state));
416219820Sjeff		printf("\nEnter choice (1-%u): ", i);
417219820Sjeff		fflush(stdout);
418219820Sjeff		if (scanf("%u", &choice)) {
419219820Sjeff			if (choice > num_ports || choice < 1) {
420219820Sjeff				printf("\nError: Lame choice!\n");
421219820Sjeff				fflush(stdin);
422219820Sjeff			} else {
423219820Sjeff				choice--;
424219820Sjeff				done_flag = TRUE;
425219820Sjeff			}
426219820Sjeff		} else {
427219820Sjeff			/* get rid of the junk in the selection line */
428219820Sjeff			scanf("%s", junk);
429219820Sjeff			printf("\nError: Lame choice!\n");
430219820Sjeff			fflush(stdin);
431219820Sjeff		}
432219820Sjeff	}
433219820Sjeff	printf("Choice guid=0x%" PRIx64 "\n",
434219820Sjeff	       cl_ntoh64(attr_array[choice].port_guid));
435219820Sjeff	return (attr_array[choice].port_guid);
436219820Sjeff}
437219820Sjeff
438219820Sjeff/**********************************************************************
439219820Sjeff **********************************************************************/
440219820Sjeff
441219820Sjeffstatic int daemonize(osm_opensm_t * osm)
442219820Sjeff{
443219820Sjeff	pid_t pid;
444219820Sjeff	int fd;
445219820Sjeff
446219820Sjeff	fd = open("/dev/null", O_WRONLY);
447219820Sjeff	if (fd < 0) {
448219820Sjeff		perror("open");
449219820Sjeff		return -1;
450219820Sjeff	}
451219820Sjeff
452219820Sjeff	if ((pid = fork()) < 0) {
453219820Sjeff		perror("fork");
454219820Sjeff		exit(-1);
455219820Sjeff	} else if (pid > 0)
456219820Sjeff		exit(0);
457219820Sjeff
458219820Sjeff	setsid();
459219820Sjeff
460219820Sjeff	if ((pid = fork()) < 0) {
461219820Sjeff		perror("fork");
462219820Sjeff		exit(-1);
463219820Sjeff	} else if (pid > 0)
464219820Sjeff		exit(0);
465219820Sjeff
466219820Sjeff	close(0);
467219820Sjeff	close(1);
468219820Sjeff	close(2);
469219820Sjeff
470219820Sjeff	dup2(fd, 0);
471219820Sjeff	dup2(fd, 1);
472219820Sjeff	dup2(fd, 2);
473219820Sjeff
474219820Sjeff	return 0;
475219820Sjeff}
476219820Sjeff
477219820Sjeff/**********************************************************************
478219820Sjeff **********************************************************************/
479219820Sjeffint osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm)
480219820Sjeff{
481219820Sjeff	int console_init_flag = 0;
482219820Sjeff
483219820Sjeff	if (is_console_enabled(p_opt)) {
484219820Sjeff		if (!osm_console_init(p_opt, &p_osm->console, &p_osm->log))
485219820Sjeff			console_init_flag = 1;
486219820Sjeff	}
487219820Sjeff
488219820Sjeff	/*
489219820Sjeff	   Sit here forever - dwell or do console i/o & cmds
490219820Sjeff	 */
491219820Sjeff	while (!osm_exit_flag) {
492219820Sjeff		if (console_init_flag)
493219820Sjeff			osm_console(p_osm);
494219820Sjeff		else
495219820Sjeff			cl_thread_suspend(10000);
496219820Sjeff
497219820Sjeff		if (osm_usr1_flag) {
498219820Sjeff			osm_usr1_flag = 0;
499219820Sjeff			osm_log_reopen_file(&(p_osm->log));
500219820Sjeff		}
501219820Sjeff		if (osm_hup_flag) {
502219820Sjeff			osm_hup_flag = 0;
503219820Sjeff			/* a HUP signal should only start a new heavy sweep */
504219820Sjeff			p_osm->subn.force_heavy_sweep = TRUE;
505219820Sjeff			osm_opensm_sweep(p_osm);
506219820Sjeff		}
507219820Sjeff	}
508219820Sjeff	if (is_console_enabled(p_opt))
509219820Sjeff		osm_console_exit(&p_osm->console, &p_osm->log);
510219820Sjeff	return 0;
511219820Sjeff}
512219820Sjeff
513219820Sjeff/**********************************************************************
514219820Sjeff **********************************************************************/
515219820Sjeffint main(int argc, char *argv[])
516219820Sjeff{
517219820Sjeff	osm_opensm_t osm;
518219820Sjeff	osm_subn_opt_t opt;
519219820Sjeff	ib_net64_t sm_key = 0;
520219820Sjeff	ib_api_status_t status;
521219820Sjeff	uint32_t temp, dbg_lvl;
522219820Sjeff	boolean_t run_once_flag = FALSE;
523219820Sjeff	int32_t vendor_debug = 0;
524219820Sjeff	uint32_t next_option;
525219820Sjeff	char *conf_template = NULL;
526219820Sjeff	uint32_t val;
527219820Sjeff	unsigned config_file_done = 0;
528219820Sjeff	const char *const short_option =
529219820Sjeff	    "F:c:i:f:ed:D:g:l:L:s:t:a:u:m:X:R:zM:U:S:P:Y:ANBIQvVhoryxp:n:q:k:C:";
530219820Sjeff
531219820Sjeff	/*
532219820Sjeff	   In the array below, the 2nd parameter specifies the number
533219820Sjeff	   of arguments as follows:
534219820Sjeff	   0: no arguments
535219820Sjeff	   1: argument
536219820Sjeff	   2: optional
537219820Sjeff	 */
538219820Sjeff	const struct option long_option[] = {
539219820Sjeff		{"version", 0, NULL, 12},
540219820Sjeff		{"config", 1, NULL, 'F'},
541219820Sjeff		{"create-config", 1, NULL, 'c'},
542219820Sjeff		{"debug", 1, NULL, 'd'},
543219820Sjeff		{"guid", 1, NULL, 'g'},
544219820Sjeff		{"ignore_guids", 1, NULL, 'i'},
545219820Sjeff		{"lmc", 1, NULL, 'l'},
546219820Sjeff		{"sweep", 1, NULL, 's'},
547219820Sjeff		{"timeout", 1, NULL, 't'},
548219820Sjeff		{"verbose", 0, NULL, 'v'},
549219820Sjeff		{"D", 1, NULL, 'D'},
550219820Sjeff		{"log_file", 1, NULL, 'f'},
551219820Sjeff		{"log_limit", 1, NULL, 'L'},
552219820Sjeff		{"erase_log_file", 0, NULL, 'e'},
553219820Sjeff		{"Pconfig", 1, NULL, 'P'},
554219820Sjeff		{"no_part_enforce", 0, NULL, 'N'},
555219820Sjeff		{"qos", 0, NULL, 'Q'},
556219820Sjeff		{"qos_policy_file", 1, NULL, 'Y'},
557219820Sjeff		{"maxsmps", 1, NULL, 'n'},
558219820Sjeff		{"console", 1, NULL, 'q'},
559219820Sjeff		{"V", 0, NULL, 'V'},
560219820Sjeff		{"help", 0, NULL, 'h'},
561219820Sjeff		{"once", 0, NULL, 'o'},
562219820Sjeff		{"reassign_lids", 0, NULL, 'r'},
563219820Sjeff		{"priority", 1, NULL, 'p'},
564219820Sjeff		{"smkey", 1, NULL, 'k'},
565219820Sjeff		{"routing_engine", 1, NULL, 'R'},
566219820Sjeff		{"ucast_cache", 0, NULL, 'A'},
567219820Sjeff		{"connect_roots", 0, NULL, 'z'},
568219820Sjeff		{"lid_matrix_file", 1, NULL, 'M'},
569219820Sjeff		{"lfts_file", 1, NULL, 'U'},
570219820Sjeff		{"sadb_file", 1, NULL, 'S'},
571219820Sjeff		{"root_guid_file", 1, NULL, 'a'},
572219820Sjeff		{"cn_guid_file", 1, NULL, 'u'},
573219820Sjeff		{"ids_guid_file", 1, NULL, 'm'},
574219820Sjeff		{"guid_routing_order_file", 1, NULL, 'X'},
575219820Sjeff		{"stay_on_fatal", 0, NULL, 'y'},
576219820Sjeff		{"honor_guid2lid", 0, NULL, 'x'},
577219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
578219820Sjeff		{"console-port", 1, NULL, 'C'},
579219820Sjeff#endif
580219820Sjeff		{"daemon", 0, NULL, 'B'},
581219820Sjeff		{"inactive", 0, NULL, 'I'},
582219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
583219820Sjeff		{"perfmgr", 0, NULL, 1},
584219820Sjeff		{"perfmgr_sweep_time_s", 1, NULL, 2},
585219820Sjeff#endif
586219820Sjeff		{"prefix_routes_file", 1, NULL, 3},
587219820Sjeff		{"consolidate_ipv6_snm_req", 0, NULL, 4},
588219820Sjeff		{NULL, 0, NULL, 0}	/* Required at the end of the array */
589219820Sjeff	};
590219820Sjeff
591219820Sjeff	/* Make sure that the opensm and complib were compiled using
592219820Sjeff	   same modes (debug/free) */
593219820Sjeff	if (osm_is_debug() != cl_is_debug()) {
594219820Sjeff		fprintf(stderr,
595219820Sjeff			"ERROR: OpenSM and Complib were compiled using different modes\n");
596219820Sjeff		fprintf(stderr, "ERROR: OpenSM debug:%d Complib debug:%d \n",
597219820Sjeff			osm_is_debug(), cl_is_debug());
598219820Sjeff		exit(1);
599219820Sjeff	}
600219820Sjeff#if defined (_DEBUG_) && defined (OSM_VENDOR_INTF_OPENIB)
601219820Sjeff	enable_stack_dump(1);
602219820Sjeff#endif
603219820Sjeff
604219820Sjeff	printf("-------------------------------------------------\n");
605219820Sjeff	printf("%s\n", OSM_VERSION);
606219820Sjeff
607219820Sjeff	osm_subn_set_default_opt(&opt);
608219820Sjeff
609219820Sjeff	if (osm_subn_parse_conf_file(OSM_DEFAULT_CONFIG_FILE, &opt) < 0)
610219820Sjeff		printf("\nosm_subn_parse_conf_file failed!\n");
611219820Sjeff
612219820Sjeff	printf("Command Line Arguments:\n");
613219820Sjeff	do {
614219820Sjeff		next_option = getopt_long_only(argc, argv, short_option,
615219820Sjeff					       long_option, NULL);
616219820Sjeff		switch (next_option) {
617219820Sjeff		case 12: /* --version - already printed above */
618219820Sjeff			exit(0);
619219820Sjeff			break;
620219820Sjeff		case 'F':
621219820Sjeff			if (config_file_done)
622219820Sjeff				break;
623219820Sjeff			printf("Reloading config from `%s`:\n", optarg);
624219820Sjeff			if (osm_subn_parse_conf_file(optarg, &opt)) {
625219820Sjeff				printf("cannot parse config file.\n");
626219820Sjeff				exit(1);
627219820Sjeff			}
628219820Sjeff			printf("Rescaning command line:\n");
629219820Sjeff			config_file_done = 1;
630219820Sjeff			optind = 0;
631219820Sjeff			break;
632219820Sjeff		case 'c':
633219820Sjeff			conf_template = optarg;
634219820Sjeff			printf(" Creating config file template \'%s\'.\n",
635219820Sjeff			       conf_template);
636219820Sjeff			break;
637219820Sjeff		case 'o':
638219820Sjeff			/*
639219820Sjeff			   Run once option.
640219820Sjeff			 */
641219820Sjeff			run_once_flag = TRUE;
642219820Sjeff			printf(" Run Once\n");
643219820Sjeff			break;
644219820Sjeff
645219820Sjeff		case 'r':
646219820Sjeff			/*
647219820Sjeff			   Reassign LIDs subnet option.
648219820Sjeff			 */
649219820Sjeff			opt.reassign_lids = TRUE;
650219820Sjeff			printf(" Reassign LIDs\n");
651219820Sjeff			break;
652219820Sjeff
653219820Sjeff		case 'i':
654219820Sjeff			/*
655219820Sjeff			   Specifies ignore guids file.
656219820Sjeff			 */
657219820Sjeff			opt.port_prof_ignore_file = optarg;
658219820Sjeff			printf(" Ignore Guids File = %s\n",
659219820Sjeff			       opt.port_prof_ignore_file);
660219820Sjeff			break;
661219820Sjeff
662219820Sjeff		case 'g':
663219820Sjeff			/*
664219820Sjeff			   Specifies port guid with which to bind.
665219820Sjeff			 */
666219820Sjeff			opt.guid = cl_hton64(strtoull(optarg, NULL, 16));
667219820Sjeff			if (!opt.guid)
668219820Sjeff				/* If guid is 0 - need to display the
669219820Sjeff				 * guid list */
670219820Sjeff				opt.guid = INVALID_GUID;
671219820Sjeff			else
672219820Sjeff				printf(" Guid <0x%" PRIx64 ">\n",
673219820Sjeff				       cl_hton64(opt.guid));
674219820Sjeff			break;
675219820Sjeff
676219820Sjeff		case 's':
677219820Sjeff			val = strtol(optarg, NULL, 0);
678219820Sjeff			/* Check that the number is not too large */
679219820Sjeff			if (((uint32_t) (val * 1000000)) / 1000000 != val)
680219820Sjeff				fprintf(stderr,
681219820Sjeff					"ERROR: sweep interval given is too large. Ignoring it.\n");
682219820Sjeff			else {
683219820Sjeff				opt.sweep_interval = val;
684219820Sjeff				printf(" sweep interval = %d\n",
685219820Sjeff				       opt.sweep_interval);
686219820Sjeff			}
687219820Sjeff			break;
688219820Sjeff
689219820Sjeff		case 't':
690219820Sjeff			opt.transaction_timeout = strtol(optarg, NULL, 0);
691219820Sjeff			printf(" Transaction timeout = %d\n",
692219820Sjeff			       opt.transaction_timeout);
693219820Sjeff			break;
694219820Sjeff
695219820Sjeff		case 'n':
696219820Sjeff			opt.max_wire_smps = strtol(optarg, NULL, 0);
697219820Sjeff			if (opt.max_wire_smps <= 0)
698219820Sjeff				opt.max_wire_smps = 0x7FFFFFFF;
699219820Sjeff			printf(" Max wire smp's = %d\n", opt.max_wire_smps);
700219820Sjeff			break;
701219820Sjeff
702219820Sjeff		case 'q':
703219820Sjeff			/*
704219820Sjeff			 * OpenSM interactive console
705219820Sjeff			 */
706219820Sjeff			if (strcmp(optarg, OSM_DISABLE_CONSOLE) == 0
707219820Sjeff			    || strcmp(optarg, OSM_LOCAL_CONSOLE) == 0
708219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
709219820Sjeff			    || strcmp(optarg, OSM_REMOTE_CONSOLE) == 0
710219820Sjeff			    || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0
711219820Sjeff#endif
712219820Sjeff			    )
713219820Sjeff				opt.console = optarg;
714219820Sjeff			else
715219820Sjeff				printf("-console %s option not understood\n",
716219820Sjeff				       optarg);
717219820Sjeff			break;
718219820Sjeff
719219820Sjeff#ifdef ENABLE_OSM_CONSOLE_SOCKET
720219820Sjeff		case 'C':
721219820Sjeff			opt.console_port = strtol(optarg, NULL, 0);
722219820Sjeff			break;
723219820Sjeff#endif
724219820Sjeff
725219820Sjeff		case 'd':
726219820Sjeff			dbg_lvl = strtol(optarg, NULL, 0);
727219820Sjeff			printf(" d level = 0x%x\n", dbg_lvl);
728219820Sjeff			if (dbg_lvl == 0) {
729219820Sjeff				printf(" Debug mode: Ignore Other SMs\n");
730219820Sjeff				opt.ignore_other_sm = TRUE;
731219820Sjeff			} else if (dbg_lvl == 1) {
732219820Sjeff				printf(" Debug mode: Forcing Single Thread\n");
733219820Sjeff				opt.single_thread = TRUE;
734219820Sjeff			} else if (dbg_lvl == 2) {
735219820Sjeff				printf(" Debug mode: Force Log Flush\n");
736219820Sjeff				opt.force_log_flush = TRUE;
737219820Sjeff			} else if (dbg_lvl == 3) {
738219820Sjeff				printf
739219820Sjeff				    (" Debug mode: Disable multicast support\n");
740219820Sjeff				opt.disable_multicast = TRUE;
741219820Sjeff			}
742219820Sjeff			/*
743219820Sjeff			 * NOTE: Debug level 4 used to be used for memory
744219820Sjeff			 * tracking but this is now deprecated
745219820Sjeff			 */
746219820Sjeff			else if (dbg_lvl == 5)
747219820Sjeff				vendor_debug++;
748219820Sjeff			else
749219820Sjeff				printf(" OpenSM: Unknown debug option %d"
750219820Sjeff				       " ignored\n", dbg_lvl);
751219820Sjeff			break;
752219820Sjeff
753219820Sjeff		case 'l':
754219820Sjeff			temp = strtol(optarg, NULL, 0);
755219820Sjeff			if (temp > 7) {
756219820Sjeff				fprintf(stderr,
757219820Sjeff					"ERROR: LMC must be 7 or less.\n");
758219820Sjeff				return (-1);
759219820Sjeff			}
760219820Sjeff			opt.lmc = (uint8_t) temp;
761219820Sjeff			printf(" LMC = %d\n", temp);
762219820Sjeff			break;
763219820Sjeff
764219820Sjeff		case 'D':
765219820Sjeff			opt.log_flags = strtol(optarg, NULL, 0);
766219820Sjeff			printf(" verbose option -D = 0x%x\n", opt.log_flags);
767219820Sjeff			break;
768219820Sjeff
769219820Sjeff		case 'f':
770219820Sjeff			opt.log_file = optarg;
771219820Sjeff			break;
772219820Sjeff
773219820Sjeff		case 'L':
774219820Sjeff			opt.log_max_size =
775219820Sjeff			    strtoul(optarg, NULL, 0) * (1024 * 1024);
776219820Sjeff			printf(" Log file max size is %lu bytes\n",
777219820Sjeff			       opt.log_max_size);
778219820Sjeff			break;
779219820Sjeff
780219820Sjeff		case 'e':
781219820Sjeff			opt.accum_log_file = FALSE;
782219820Sjeff			printf(" Creating new log file\n");
783219820Sjeff			break;
784219820Sjeff
785219820Sjeff		case 'P':
786219820Sjeff			opt.partition_config_file = optarg;
787219820Sjeff			break;
788219820Sjeff
789219820Sjeff		case 'N':
790219820Sjeff			opt.no_partition_enforcement = TRUE;
791219820Sjeff			break;
792219820Sjeff
793219820Sjeff		case 'Q':
794219820Sjeff			opt.qos = TRUE;
795219820Sjeff			break;
796219820Sjeff
797219820Sjeff		case 'Y':
798219820Sjeff			opt.qos_policy_file = optarg;
799219820Sjeff			printf(" QoS policy file \'%s\'\n", optarg);
800219820Sjeff			break;
801219820Sjeff
802219820Sjeff		case 'y':
803219820Sjeff			opt.exit_on_fatal = FALSE;
804219820Sjeff			printf(" Staying on fatal initialization errors\n");
805219820Sjeff			break;
806219820Sjeff
807219820Sjeff		case 'v':
808219820Sjeff			opt.log_flags = (opt.log_flags << 1) | 1;
809219820Sjeff			printf(" Verbose option -v (log flags = 0x%X)\n",
810219820Sjeff			       opt.log_flags);
811219820Sjeff			break;
812219820Sjeff
813219820Sjeff		case 'V':
814219820Sjeff			opt.log_flags = 0xFF;
815219820Sjeff			opt.force_log_flush = TRUE;
816219820Sjeff			printf(" Big V selected\n");
817219820Sjeff			break;
818219820Sjeff
819219820Sjeff		case 'p':
820219820Sjeff			temp = strtol(optarg, NULL, 0);
821219820Sjeff			if (0 > temp || 15 < temp) {
822219820Sjeff				fprintf(stderr,
823219820Sjeff					"ERROR: priority must be between 0 and 15\n");
824219820Sjeff				return (-1);
825219820Sjeff			}
826219820Sjeff			opt.sm_priority = (uint8_t) temp;
827219820Sjeff			printf(" Priority = %d\n", temp);
828219820Sjeff			break;
829219820Sjeff
830219820Sjeff		case 'k':
831219820Sjeff			sm_key = cl_hton64(strtoull(optarg, NULL, 16));
832219820Sjeff			printf(" SM Key <0x%" PRIx64 ">\n", cl_hton64(sm_key));
833219820Sjeff			opt.sm_key = sm_key;
834219820Sjeff			break;
835219820Sjeff
836219820Sjeff		case 'R':
837219820Sjeff			opt.routing_engine_names = optarg;
838219820Sjeff			printf(" Activate \'%s\' routing engine(s)\n", optarg);
839219820Sjeff			break;
840219820Sjeff
841219820Sjeff		case 'z':
842219820Sjeff			opt.connect_roots = TRUE;
843219820Sjeff			printf(" Connect roots option is on\n");
844219820Sjeff			break;
845219820Sjeff
846219820Sjeff		case 'A':
847219820Sjeff			opt.use_ucast_cache = TRUE;
848219820Sjeff			printf(" Unicast routing cache option is on\n");
849219820Sjeff			break;
850219820Sjeff
851219820Sjeff		case 'M':
852219820Sjeff			opt.lid_matrix_dump_file = optarg;
853219820Sjeff			printf(" Lid matrix dump file is \'%s\'\n", optarg);
854219820Sjeff			break;
855219820Sjeff
856219820Sjeff		case 'U':
857219820Sjeff			opt.lfts_file = optarg;
858219820Sjeff			printf(" LFTs file is \'%s\'\n", optarg);
859219820Sjeff			break;
860219820Sjeff
861219820Sjeff		case 'S':
862219820Sjeff			opt.sa_db_file = optarg;
863219820Sjeff			printf(" SA DB file is \'%s\'\n", optarg);
864219820Sjeff			break;
865219820Sjeff
866219820Sjeff		case 'a':
867219820Sjeff			/*
868219820Sjeff			   Specifies root guids file
869219820Sjeff			 */
870219820Sjeff			opt.root_guid_file = optarg;
871219820Sjeff			printf(" Root Guid File: %s\n", opt.root_guid_file);
872219820Sjeff			break;
873219820Sjeff
874219820Sjeff		case 'u':
875219820Sjeff			/*
876219820Sjeff			   Specifies compute node guids file
877219820Sjeff			 */
878219820Sjeff			opt.cn_guid_file = optarg;
879219820Sjeff			printf(" Compute Node Guid File: %s\n",
880219820Sjeff			       opt.cn_guid_file);
881219820Sjeff			break;
882219820Sjeff
883219820Sjeff		case 'm':
884219820Sjeff			/* Specifies ids guid file */
885219820Sjeff			opt.ids_guid_file = optarg;
886219820Sjeff			printf(" IDs Guid File: %s\n", opt.ids_guid_file);
887219820Sjeff			break;
888219820Sjeff
889219820Sjeff		case 'X':
890219820Sjeff			/* Specifies guid routing order file */
891219820Sjeff			opt.guid_routing_order_file = optarg;
892219820Sjeff			printf(" GUID Routing Order File: %s\n", opt.guid_routing_order_file);
893219820Sjeff			break;
894219820Sjeff
895219820Sjeff		case 'x':
896219820Sjeff			opt.honor_guid2lid_file = TRUE;
897219820Sjeff			printf(" Honor guid2lid file, if possible\n");
898219820Sjeff			break;
899219820Sjeff
900219820Sjeff		case 'B':
901219820Sjeff			opt.daemon = TRUE;
902219820Sjeff			printf(" Daemon mode\n");
903219820Sjeff			break;
904219820Sjeff
905219820Sjeff		case 'I':
906219820Sjeff			opt.sm_inactive = TRUE;
907219820Sjeff			printf(" SM started in inactive state\n");
908219820Sjeff			break;
909219820Sjeff
910219820Sjeff#ifdef ENABLE_OSM_PERF_MGR
911219820Sjeff		case 1:
912219820Sjeff			opt.perfmgr = TRUE;
913219820Sjeff			break;
914219820Sjeff		case 2:
915219820Sjeff			opt.perfmgr_sweep_time_s = atoi(optarg);
916219820Sjeff			break;
917219820Sjeff#endif				/* ENABLE_OSM_PERF_MGR */
918219820Sjeff
919219820Sjeff		case 3:
920219820Sjeff			opt.prefix_routes_file = optarg;
921219820Sjeff			break;
922219820Sjeff		case 4:
923219820Sjeff			opt.consolidate_ipv6_snm_req = TRUE;
924219820Sjeff			break;
925219820Sjeff		case 'h':
926219820Sjeff		case '?':
927219820Sjeff		case ':':
928219820Sjeff			show_usage();
929219820Sjeff			break;
930219820Sjeff
931219820Sjeff		case -1:
932219820Sjeff			break;	/* done with option */
933219820Sjeff		default:	/* something wrong */
934219820Sjeff			abort();
935219820Sjeff		}
936219820Sjeff	}
937219820Sjeff	while (next_option != -1);
938219820Sjeff
939219820Sjeff	if (opt.log_file != NULL)
940219820Sjeff		printf(" Log File: %s\n", opt.log_file);
941219820Sjeff	/* Done with options description */
942219820Sjeff	printf("-------------------------------------------------\n");
943219820Sjeff
944219820Sjeff	if (conf_template) {
945219820Sjeff		status = osm_subn_write_conf_file(conf_template, &opt);
946219820Sjeff		if (status)
947219820Sjeff			printf("\nosm_subn_write_conf_file failed!\n");
948219820Sjeff		exit(status);
949219820Sjeff	}
950219820Sjeff
951219820Sjeff	osm_subn_verify_config(&opt);
952219820Sjeff
953219820Sjeff	if (vendor_debug)
954219820Sjeff		osm_vendor_set_debug(osm.p_vendor, vendor_debug);
955219820Sjeff
956219820Sjeff	block_signals();
957219820Sjeff
958219820Sjeff	if (opt.daemon)
959219820Sjeff		daemonize(&osm);
960219820Sjeff
961219820Sjeff	complib_init();
962219820Sjeff
963219820Sjeff	status = osm_opensm_init(&osm, &opt);
964219820Sjeff	if (status != IB_SUCCESS) {
965219820Sjeff		const char *err_str = ib_get_err_str(status);
966219820Sjeff		if (err_str == NULL)
967219820Sjeff			err_str = "Unknown Error Type";
968219820Sjeff		printf("\nError from osm_opensm_init: %s.\n", err_str);
969219820Sjeff		/* We will just exit, and not go to Exit, since we don't
970219820Sjeff		   want the destroy to be called. */
971219820Sjeff		complib_exit();
972219820Sjeff		return (status);
973219820Sjeff	}
974219820Sjeff
975219820Sjeff	/*
976219820Sjeff	   If the user didn't specify a GUID on the command line,
977219820Sjeff	   then get a port GUID value with which to bind.
978219820Sjeff	 */
979219820Sjeff	if (opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID))
980219820Sjeff		opt.guid = get_port_guid(&osm, opt.guid);
981219820Sjeff
982219820Sjeff	status = osm_opensm_bind(&osm, opt.guid);
983219820Sjeff	if (status != IB_SUCCESS) {
984219820Sjeff		printf("\nError from osm_opensm_bind (0x%X)\n", status);
985219820Sjeff		printf
986219820Sjeff		    ("Perhaps another instance of OpenSM is already running\n");
987219820Sjeff		goto Exit;
988219820Sjeff	}
989219820Sjeff
990219820Sjeff	setup_signals();
991219820Sjeff
992219820Sjeff	osm_opensm_sweep(&osm);
993219820Sjeff
994219820Sjeff	if (run_once_flag == TRUE) {
995219820Sjeff		while (!osm_exit_flag) {
996219820Sjeff			status =
997219820Sjeff			    osm_opensm_wait_for_subnet_up(&osm,
998219820Sjeff							  osm.subn.opt.
999219820Sjeff							  sweep_interval *
1000219820Sjeff							  1000000, TRUE);
1001219820Sjeff			if (!status)
1002219820Sjeff				osm_exit_flag = 1;
1003219820Sjeff		}
1004219820Sjeff	} else {
1005219820Sjeff		/*
1006219820Sjeff		 *         Sit here until signaled to exit
1007219820Sjeff		 */
1008219820Sjeff		osm_manager_loop(&opt, &osm);
1009219820Sjeff	}
1010219820Sjeff
1011219820Sjeff	if (osm.mad_pool.mads_out) {
1012219820Sjeff		fprintf(stdout,
1013219820Sjeff			"There are still %u MADs out. Forcing the exit of the OpenSM application...\n",
1014219820Sjeff			osm.mad_pool.mads_out);
1015219820Sjeff#ifdef HAVE_LIBPTHREAD
1016219820Sjeff		pthread_cond_signal(&osm.stats.cond);
1017219820Sjeff#else
1018219820Sjeff		cl_event_signal(&osm.stats.event);
1019219820Sjeff#endif
1020219820Sjeff	}
1021219820Sjeff
1022219820SjeffExit:
1023219820Sjeff	osm_opensm_destroy(&osm);
1024219820Sjeff	complib_exit();
1025219820Sjeff
1026219820Sjeff	exit(0);
1027219820Sjeff}
1028