1/*
2 * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2002-2011 Mellanox Technologies LTD. All rights reserved.
4 * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
5 * Copyright (c) 2009 HNR Consulting. All rights reserved.
6 * Copyright (c) 2009 System Fabric Works, Inc. All rights reserved.
7 * Copyright (c) 2009-2011 ZIH, TU Dresden, Federal Republic of Germany. All rights reserved.
8 *
9 * This software is available to you under a choice of one of two
10 * licenses.  You may choose to be licensed under the terms of the GNU
11 * General Public License (GPL) Version 2, available from the file
12 * COPYING in the main directory of this source tree, or the
13 * OpenIB.org BSD license below:
14 *
15 *     Redistribution and use in source and binary forms, with or
16 *     without modification, are permitted provided that the following
17 *     conditions are met:
18 *
19 *      - Redistributions of source code must retain the above
20 *        copyright notice, this list of conditions and the following
21 *        disclaimer.
22 *
23 *      - Redistributions in binary form must reproduce the above
24 *        copyright notice, this list of conditions and the following
25 *        disclaimer in the documentation and/or other materials
26 *        provided with the distribution.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
32 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
33 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
34 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
35 * SOFTWARE.
36 *
37 */
38
39/*
40 * Abstract:
41 *    Command line interface for opensm.
42 */
43
44#if HAVE_CONFIG_H
45#  include <config.h>
46#endif				/* HAVE_CONFIG_H */
47
48#include <stdio.h>
49#include <stdlib.h>
50#include <getopt.h>
51#include <unistd.h>
52#include <signal.h>
53#include <sys/types.h>
54#include <sys/stat.h>
55#include <fcntl.h>
56#include <complib/cl_types.h>
57#include <complib/cl_debug.h>
58#include <opensm/osm_file_ids.h>
59#define FILE_ID OSM_FILE_MAIN_C
60#include <vendor/osm_vendor_api.h>
61#include <opensm/osm_version.h>
62#include <opensm/osm_opensm.h>
63#include <opensm/osm_console.h>
64#include <opensm/osm_console_io.h>
65#include <opensm/osm_perfmgr.h>
66
67volatile unsigned int osm_exit_flag = 0;
68
69static volatile unsigned int osm_hup_flag = 0;
70static volatile unsigned int osm_usr1_flag = 0;
71static char *pidfile;
72
73#define MAX_LOCAL_IBPORTS 64
74#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
75
76static void mark_exit_flag(int signum)
77{
78	if (!osm_exit_flag)
79		printf("OpenSM: Got signal %d - exiting...\n", signum);
80	osm_exit_flag = 1;
81}
82
83static void mark_hup_flag(int signum)
84{
85	osm_hup_flag = 1;
86}
87
88static void mark_usr1_flag(int signum)
89{
90	osm_usr1_flag = 1;
91}
92
93static sigset_t saved_sigset;
94
95static void block_signals()
96{
97	sigset_t set;
98
99	sigemptyset(&set);
100	sigaddset(&set, SIGINT);
101	sigaddset(&set, SIGTERM);
102	sigaddset(&set, SIGHUP);
103#ifndef HAVE_OLD_LINUX_THREADS
104	sigaddset(&set, SIGUSR1);
105#endif
106	pthread_sigmask(SIG_SETMASK, &set, &saved_sigset);
107}
108
109static void setup_signals()
110{
111	struct sigaction act;
112
113	sigemptyset(&act.sa_mask);
114	act.sa_handler = mark_exit_flag;
115	act.sa_flags = 0;
116	sigaction(SIGINT, &act, NULL);
117	sigaction(SIGTERM, &act, NULL);
118	act.sa_handler = mark_hup_flag;
119	sigaction(SIGHUP, &act, NULL);
120	sigaction(SIGCONT, &act, NULL);
121#ifndef HAVE_OLD_LINUX_THREADS
122	act.sa_handler = mark_usr1_flag;
123	sigaction(SIGUSR1, &act, NULL);
124#endif
125	pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL);
126}
127
128static void show_usage(void)
129{
130	printf("\n------- OpenSM - Usage and options ----------------------\n");
131	printf("Usage:   opensm [options]\n");
132	printf("Options:\n");
133	printf("--version\n          Prints OpenSM version and exits.\n\n");
134	printf("--config, -F <file-name>\n"
135	       "          The name of the OpenSM config file. When not specified\n"
136	       "          " OSM_DEFAULT_CONFIG_FILE
137	       " will be used (if exists).\n\n");
138	printf("--create-config, -c <file-name>\n"
139	       "          OpenSM will dump its configuration to the specified file and exit.\n"
140	       "          This is a way to generate OpenSM configuration file template.\n\n");
141	printf("--guid, -g <GUID in hex>\n"
142	       "          This option specifies the local port GUID value\n"
143	       "          with which OpenSM should bind.  OpenSM may be\n"
144	       "          bound to 1 port at a time.\n"
145	       "          If GUID given is 0, OpenSM displays a list\n"
146	       "          of possible port GUIDs and waits for user input.\n"
147	       "          Without -g, OpenSM tries to use the default port.\n\n");
148	printf("--lmc, -l <LMC>\n"
149	       "          This option specifies the subnet's LMC value.\n"
150	       "          The number of LIDs assigned to each port is 2^LMC.\n"
151	       "          The LMC value must be in the range 0-7.\n"
152	       "          LMC values > 0 allow multiple paths between ports.\n"
153	       "          LMC values > 0 should only be used if the subnet\n"
154	       "          topology actually provides multiple paths between\n"
155	       "          ports, i.e. multiple interconnects between switches.\n"
156	       "          Without -l, OpenSM defaults to LMC = 0, which allows\n"
157	       "          one path between any two ports.\n\n");
158	printf("--priority, -p <PRIORITY>\n"
159	       "          This option specifies the SM's PRIORITY.\n"
160	       "          This will effect the handover cases, where master\n"
161	       "          is chosen by priority and GUID.  Range goes\n"
162	       "          from 0 (lowest priority) to 15 (highest).\n\n");
163	printf("--smkey, -k <SM_Key>\n"
164	       "          This option specifies the SM's SM_Key (64 bits).\n"
165	       "          This will effect SM authentication.\n"
166	       "          Note that OpenSM version 3.2.1 and below used the\n"
167	       "          default value '1' in a host byte order, it is fixed\n"
168	       "          now but you may need this option to interoperate\n"
169	       "          with old OpenSM running on a little endian machine.\n\n");
170	printf("--reassign_lids, -r\n"
171	       "          This option causes OpenSM to reassign LIDs to all\n"
172	       "          end nodes. Specifying -r on a running subnet\n"
173	       "          may disrupt subnet traffic.\n"
174	       "          Without -r, OpenSM attempts to preserve existing\n"
175	       "          LID assignments resolving multiple use of same LID.\n\n");
176	printf("--routing_engine, -R <engine name>\n"
177	       "          This option chooses routing engine(s) to use instead of default\n"
178	       "          Min Hop algorithm.  Multiple routing engines can be specified\n"
179	       "          separated by commas so that specific ordering of routing\n"
180	       "          algorithms will be tried if earlier routing engines fail.\n"
181	       "          If all configured routing engines fail, OpenSM will always\n"
182	       "          attempt to route with Min Hop unless 'no_fallback' is\n"
183	       "          included in the list of routing engines.\n"
184	       "          Supported engines: updn, dnup, file, ftree, lash, dor, torus-2QoS, dfsssp, sssp\n\n");
185	printf("--do_mesh_analysis\n"
186	       "          This option enables additional analysis for the lash\n"
187	       "          routing engine to precondition switch port assignments\n"
188	       "          in regular cartesian meshes which may reduce the number\n"
189	       "          of SLs required to give a deadlock free routing\n\n");
190	printf("--lash_start_vl <vl number>\n"
191	       "          Sets the starting VL to use for the lash routing algorithm.\n"
192	       "          Defaults to 0.\n");
193	printf("--sm_sl <sl number>\n"
194	       "          Sets the SL to use to communicate with the SM/SA. Defaults to 0.\n\n");
195	printf("--connect_roots, -z\n"
196	       "          This option enforces routing engines (up/down and \n"
197	       "          fat-tree) to make connectivity between root switches\n"
198	       "          and in this way be IBA compliant. In many cases,\n"
199	       "          this can violate \"pure\" deadlock free algorithm, so\n"
200	       "          use it carefully.\n\n");
201	printf("--ucast_cache, -A\n"
202	       "          This option enables unicast routing cache to prevent\n"
203	       "          routing recalculation (which is a heavy task in a\n"
204	       "          large cluster) when there was no topology change\n"
205	       "          detected during the heavy sweep, or when the topology\n"
206	       "          change does not require new routing calculation,\n"
207	       "          e.g. in case of host reboot.\n"
208	       "          This option becomes very handy when the cluster size\n"
209	       "          is thousands of nodes.\n\n");
210	printf("--lid_matrix_file, -M <file name>\n"
211	       "          This option specifies the name of the lid matrix dump file\n"
212	       "          from where switch lid matrices (min hops tables will be\n"
213	       "          loaded.\n\n");
214	printf("--lfts_file, -U <file name>\n"
215	       "          This option specifies the name of the LFTs file\n"
216	       "          from where switch forwarding tables will be loaded when using \"file\"\n"
217	       "          routing engine.\n\n");
218	printf("--sadb_file, -S <file name>\n"
219	       "          This option specifies the name of the SA DB dump file\n"
220	       "          from where SA database will be loaded.\n\n");
221	printf("--root_guid_file, -a <path to file>\n"
222	       "          Set the root nodes for the Up/Down or Fat-Tree routing\n"
223	       "          algorithm to the guids provided in the given file (one\n"
224	       "          to a line)\n" "\n");
225	printf("--cn_guid_file, -u <path to file>\n"
226	       "          Set the compute nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n"
227	       "          to the port GUIDs provided in the given file (one to a line)\n\n");
228	printf("--io_guid_file, -G <path to file>\n"
229	       "          Set the I/O nodes for the Fat-Tree or DFSSSP/SSSP routing algorithms\n"
230	       "          to the port GUIDs provided in the given file (one to a line)\n\n");
231	printf("--port-shifting\n"
232	       "          Attempt to shift port routes around to remove alignment problems\n"
233	       "          in routing tables\n\n");
234	printf("--scatter-ports <random seed>\n"
235	       "          Randomize best port chosen for a route\n"
236	       "          Assign ports in a random order instead of round-robin\n"
237	       "          If zero disable (default), otherwise use the value as a random seed\n\n");
238	printf("--max_reverse_hops, -H <hop_count>\n"
239	       "          Set the max number of hops the wrong way around\n"
240	       "          an I/O node is allowed to do (connectivity for I/O nodes on top swithces)\n\n");
241	printf("--ids_guid_file, -m <path to file>\n"
242	       "          Name of the map file with set of the IDs which will be used\n"
243	       "          by Up/Down routing algorithm instead of node GUIDs\n"
244	       "          (format: <guid> <id> per line)\n\n");
245	printf("--guid_routing_order_file, -X <path to file>\n"
246	       "          Set the order port guids will be routed for the MinHop\n"
247	       "          and Up/Down routing algorithms to the guids provided in the\n"
248	       "          given file (one to a line)\n\n");
249	printf("--torus_config <path to file>\n"
250	       "          This option defines the file name for the extra configuration\n"
251	       "          info needed for the torus-2QoS routing engine.   The default\n"
252	       "          name is \'"OSM_DEFAULT_TORUS_CONF_FILE"\'\n\n");
253	printf("--once, -o\n"
254	       "          This option causes OpenSM to configure the subnet\n"
255	       "          once, then exit.  Ports remain in the ACTIVE state.\n\n");
256	printf("--sweep, -s <interval>\n"
257	       "          This option specifies the number of seconds between\n"
258	       "          subnet sweeps.  Specifying -s 0 disables sweeping.\n"
259	       "          Without -s, OpenSM defaults to a sweep interval of\n"
260	       "          10 seconds.\n\n");
261	printf("--timeout, -t <milliseconds>\n"
262	       "          This option specifies the time in milliseconds\n"
263	       "          used for transaction timeouts.\n"
264	       "          Timeout values should be > 0.\n"
265	       "          Without -t, OpenSM defaults to a timeout value of\n"
266	       "          200 milliseconds.\n\n");
267	printf("--retries <number>\n"
268	       "          This option specifies the number of retries used\n"
269	       "          for transactions.\n"
270	       "          Without --retries, OpenSM defaults to %u retries\n"
271	       "          for transactions.\n\n", OSM_DEFAULT_RETRY_COUNT);
272	printf("--maxsmps, -n <number>\n"
273	       "          This option specifies the number of VL15 SMP MADs\n"
274	       "          allowed on the wire at any one time.\n"
275	       "          Specifying --maxsmps 0 allows unlimited outstanding\n"
276	       "          SMPs.\n"
277	       "          Without --maxsmps, OpenSM defaults to a maximum of\n"
278	       "          4 outstanding SMPs.\n\n");
279	printf("--console, -q [off|local"
280#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
281	       "|loopback"
282#endif
283#ifdef ENABLE_OSM_CONSOLE_SOCKET
284	       "|socket"
285#endif
286	       "]\n          This option activates the OpenSM console (default off).\n\n");
287#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
288	printf("--console-port, -C <port>\n"
289	       "          Specify an alternate telnet port for the console (default %d).\n\n",
290	       OSM_DEFAULT_CONSOLE_PORT);
291#endif
292	printf("--ignore_guids, -i <equalize-ignore-guids-file>\n"
293	       "          This option provides the means to define a set of ports\n"
294	       "          (by guid) that will be ignored by the link load\n"
295	       "          equalization algorithm.\n\n");
296	printf("--hop_weights_file, -w <path to file>\n"
297	       "          This option provides the means to define a weighting\n"
298	       "          factor per port for customizing the least weight\n"
299	       "          hops for the routing.\n\n");
300	printf("--port_search_ordering_file, -O <path to file>\n"
301	       "          This option provides the means to define a mapping\n"
302	       "          between ports and dimension (Order) for controlling\n"
303	       "          Dimension Order Routing (DOR).\n"
304	       "          Moreover this option provides the means to define non\n"
305	       "          default routing port order.\n\n");
306	printf("--dimn_ports_file, -O <path to file> (DEPRECATED)\n"
307	       "          Use --port_search_ordering_file instead.\n"
308	       "          This option provides the means to define a mapping\n"
309	       "          between ports and dimension (Order) for controlling\n"
310	       "          Dimension Order Routing (DOR).\n\n");
311	printf("--honor_guid2lid, -x\n"
312	       "          This option forces OpenSM to honor the guid2lid file,\n"
313	       "          when it comes out of Standby state, if such file exists\n"
314	       "          under OSM_CACHE_DIR, and is valid. By default, this is FALSE.\n\n");
315	printf("--log_file, -f <log-file-name>\n"
316	       "          This option defines the log to be the given file.\n"
317	       "          By default, the log goes to /var/log/opensm.log.\n"
318	       "          For the log to go to standard output use -f stdout.\n\n");
319	printf("--log_limit, -L <size in MB>\n"
320	       "          This option defines maximal log file size in MB. When\n"
321	       "          specified the log file will be truncated upon reaching\n"
322	       "          this limit.\n\n");
323	printf("--erase_log_file, -e\n"
324	       "          This option will cause deletion of the log file\n"
325	       "          (if it previously exists). By default, the log file\n"
326	       "          is accumulative.\n\n");
327	printf("--Pconfig, -P <partition-config-file>\n"
328	       "          This option defines the optional partition configuration file.\n"
329	       "          The default name is \'"
330	       OSM_DEFAULT_PARTITION_CONFIG_FILE "\'.\n\n");
331	printf("--no_part_enforce, -N (DEPRECATED)\n"
332	       "          Use --part_enforce instead.\n"
333	       "          This option disables partition enforcement on switch external ports.\n\n");
334	printf("--part_enforce, -Z [both, in, out, off]\n"
335	       "          This option indicates the partition enforcement type (for switches)\n"
336	       "          Enforcement type can be outbound only (out), inbound only (in), both or\n"
337	       "          disabled (off). Default is both.\n\n");
338	printf("--allow_both_pkeys, -W\n"
339	       "          This option indicates whether both full and limited membership\n"
340	       "          on the same partition can be configured in the PKeyTable.\n"
341	       "          Default is not to allow both pkeys.\n\n");
342	printf("--qos, -Q\n" "          This option enables QoS setup.\n\n");
343	printf("--qos_policy_file, -Y <QoS-policy-file>\n"
344	       "          This option defines the optional QoS policy file.\n"
345	       "          The default name is \'" OSM_DEFAULT_QOS_POLICY_FILE
346	       "\'.\n\n");
347	printf("--congestion_control\n"
348	       "          (EXPERIMENTAL) This option enables congestion control configuration.\n\n");
349	printf("--cc_key <key>\n"
350	       "          (EXPERIMENTAL) This option configures the CCkey to use when configuring\n"
351	       "          congestion control.\n\n");
352	printf("--stay_on_fatal, -y\n"
353	       "          This option will cause SM not to exit on fatal initialization\n"
354	       "          issues: if SM discovers duplicated guids or 12x link with\n"
355	       "          lane reversal badly configured.\n"
356	       "          By default, the SM will exit on these errors.\n\n");
357	printf("--daemon, -B\n"
358	       "          Run in daemon mode - OpenSM will run in the background.\n\n");
359	printf("--inactive, -I\n"
360	       "           Start SM in inactive rather than normal init SM state.\n\n");
361#ifdef ENABLE_OSM_PERF_MGR
362	printf("--perfmgr\n" "           Start with PerfMgr enabled.\n\n");
363	printf("--perfmgr_sweep_time_s <sec.>\n"
364	       "           PerfMgr sweep interval in seconds.\n\n");
365#endif
366	printf("--prefix_routes_file <path to file>\n"
367	       "          This option specifies the prefix routes file.\n"
368	       "          Prefix routes control how the SA responds to path record\n"
369	       "          queries for off-subnet DGIDs.  Default file is:\n"
370	       "              " OSM_DEFAULT_PREFIX_ROUTES_FILE "\n\n");
371	printf("--consolidate_ipv6_snm_req\n"
372	       "          Use shared MLID for IPv6 Solicited Node Multicast groups\n"
373	       "          per MGID scope and P_Key.\n\n");
374	printf("--guid_routing_order_no_scatter\n"
375	       "          Don't use scatter for ports defined in guid_routing_order file\n\n");
376	printf("--log_prefix <prefix text>\n"
377	       "          Prefix to syslog messages from OpenSM.\n\n");
378	printf("--verbose, -v\n"
379	       "          This option increases the log verbosity level.\n"
380	       "          The -v option may be specified multiple times\n"
381	       "          to further increase the verbosity level.\n"
382	       "          See the -D option for more information about\n"
383	       "          log verbosity.\n\n");
384	printf("--V, -V\n"
385	       "          This option sets the maximum verbosity level and\n"
386	       "          forces log flushing.\n"
387	       "          The -V is equivalent to '-D 0xFF -d 2'.\n"
388	       "          See the -D option for more information about\n"
389	       "          log verbosity.\n\n");
390	printf("--D, -D <flags>\n"
391	       "          This option sets the log verbosity level.\n"
392	       "          A flags field must follow the -D option.\n"
393	       "          A bit set/clear in the flags enables/disables a\n"
394	       "          specific log level as follows:\n"
395	       "          BIT    LOG LEVEL ENABLED\n"
396	       "          ----   -----------------\n"
397	       "          0x01 - ERROR (error messages)\n"
398	       "          0x02 - INFO (basic messages, low volume)\n"
399	       "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
400	       "          0x08 - DEBUG (diagnostic, high volume)\n"
401	       "          0x10 - FUNCS (function entry/exit, very high volume)\n"
402	       "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
403	       "          0x40 - ROUTING (dump FDB routing information)\n"
404	       "          0x80 - currently unused.\n"
405	       "          Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
406	       "          Specifying -D 0 disables all messages.\n"
407	       "          Specifying -D 0xFF enables all messages (see -V).\n"
408	       "          High verbosity levels may require increasing\n"
409	       "          the transaction timeout with the -t option.\n\n");
410	printf("--debug, -d <number>\n"
411	       "          This option specifies a debug option.\n"
412	       "          These options are not normally needed.\n"
413	       "          The number following -d selects the debug\n"
414	       "          option to enable as follows:\n"
415	       "          OPT   Description\n"
416	       "          ---    -----------------\n"
417	       "          -d0  - Ignore other SM nodes\n"
418	       "          -d1  - Force single threaded dispatching\n"
419	       "          -d2  - Force log flushing after each log message\n"
420	       "          -d3  - Disable multicast support\n"
421	       "          -d10 - Put OpenSM in testability mode\n"
422	       "          Without -d, no debug options are enabled\n\n");
423	printf("--help, -h, -?\n"
424	       "          Display this usage info then exit.\n\n");
425	fflush(stdout);
426	exit(2);
427}
428
429static ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid)
430{
431	ib_port_attr_t attr_array[MAX_LOCAL_IBPORTS];
432	uint32_t num_ports = MAX_LOCAL_IBPORTS;
433	uint32_t i, choice = 0;
434	ib_api_status_t status;
435
436	for (i = 0; i < num_ports; i++) {
437		attr_array[i].num_pkeys = 0;
438		attr_array[i].p_pkey_table = NULL;
439		attr_array[i].num_gids = 0;
440		attr_array[i].p_gid_table = NULL;
441	}
442
443	/* Call the transport layer for a list of local port GUID values */
444	status = osm_vendor_get_all_port_attr(p_osm->p_vendor, attr_array,
445					      &num_ports);
446	if (status != IB_SUCCESS) {
447		printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
448		       status);
449		return 0;
450	}
451
452	/* if num_ports is 0 - return 0 */
453	if (num_ports == 0) {
454		printf("\nNo local ports detected!\n");
455		return 0;
456	}
457	/* If num_ports is 1, then there is only one possible port to use.
458	 * Use it. */
459	if (num_ports == 1) {
460		printf("Using default GUID 0x%" PRIx64 "\n",
461		       cl_hton64(attr_array[0].port_guid));
462		return attr_array[0].port_guid;
463	}
464	/* If port_guid is 0 - use the first connected port */
465	if (port_guid == 0) {
466		for (i = 0; i < num_ports; i++)
467			if (attr_array[i].link_state > IB_LINK_DOWN)
468				break;
469		if (i == num_ports)
470			i = 0;
471		printf("Using default GUID 0x%" PRIx64 "\n",
472		       cl_hton64(attr_array[i].port_guid));
473		return attr_array[i].port_guid;
474	}
475
476	if (p_osm->subn.opt.daemon)
477		return 0;
478
479	/* More than one possible port - list all ports and let the user
480	 * to choose. */
481	while (1) {
482		printf("\nChoose a local port number with which to bind:\n\n");
483		for (i = 0; i < num_ports; i++)
484			/* Print the index + 1 since by convention, port
485			 * numbers start with 1 on host channel adapters. */
486			printf("\t%u: GUID 0x%" PRIx64 ", lid %u, state %s\n",
487			       i + 1, cl_ntoh64(attr_array[i].port_guid),
488			       attr_array[i].lid,
489			       ib_get_port_state_str(attr_array[i].link_state));
490		printf("\n\t0: Exit\n");
491		printf("\nEnter choice (0-%u): ", i);
492		fflush(stdout);
493		if (scanf("%u", &choice) <= 0) {
494			char junk[128];
495			if (scanf("%127s", junk) <= 0)
496				printf("\nError: Cannot scan!\n");
497		} else if (choice == 0)
498			return 0;
499		else if (choice <= num_ports)
500			break;
501		printf("\nError: Lame choice! Please try again.\n");
502	}
503	choice--;
504	printf("Choice guid=0x%" PRIx64 "\n",
505	       cl_ntoh64(attr_array[choice].port_guid));
506	return attr_array[choice].port_guid;
507}
508
509static void remove_pidfile(void)
510{
511	if (pidfile)
512		unlink(pidfile);
513}
514
515static int daemonize(osm_opensm_t * osm)
516{
517	pid_t pid;
518	int fd;
519	FILE *f;
520
521	fd = open("/dev/null", O_WRONLY);
522	if (fd < 0) {
523		perror("open");
524		return -1;
525	}
526
527	if ((pid = fork()) < 0) {
528		perror("fork");
529		exit(-1);
530	} else if (pid > 0)
531		exit(0);
532
533	setsid();
534
535	if ((pid = fork()) < 0) {
536		perror("fork");
537		exit(-1);
538	} else if (pid > 0)
539		exit(0);
540
541	if (pidfile) {
542		remove_pidfile();
543		f = fopen(pidfile, "w");
544		if (f) {
545			fprintf(f, "%d\n", getpid());
546			fclose(f);
547		} else {
548			perror("fopen");
549			exit(1);
550		}
551	}
552
553	close(0);
554	close(1);
555	close(2);
556
557	dup2(fd, 0);
558	dup2(fd, 1);
559	dup2(fd, 2);
560
561	return 0;
562}
563
564int osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm)
565{
566	int console_init_flag = 0;
567
568	if (is_console_enabled(p_opt)) {
569		if (!osm_console_init(p_opt, &p_osm->console, &p_osm->log))
570			console_init_flag = 1;
571	}
572
573	/*
574	   Sit here forever - dwell or do console i/o & cmds
575	 */
576	while (!osm_exit_flag) {
577		if (console_init_flag) {
578			if (osm_console(p_osm))
579				console_init_flag = 0;
580		} else
581			cl_thread_suspend(10000);
582
583		if (osm_usr1_flag) {
584			osm_usr1_flag = 0;
585			osm_log_reopen_file(&(p_osm->log));
586		}
587		if (osm_hup_flag) {
588			osm_hup_flag = 0;
589			/* a HUP signal should only start a new heavy sweep */
590			p_osm->subn.force_heavy_sweep = TRUE;
591			osm_opensm_sweep(p_osm);
592		}
593	}
594	if (is_console_enabled(p_opt))
595		osm_console_exit(&p_osm->console, &p_osm->log);
596	return 0;
597}
598
599#define SET_STR_OPT(opt, val) do { \
600	opt = val ? strdup(val) : NULL ; \
601} while (0)
602
603int main(int argc, char *argv[])
604{
605	osm_opensm_t osm;
606	osm_subn_opt_t opt;
607	ib_net64_t sm_key = 0;
608	ib_api_status_t status;
609	uint32_t temp, dbg_lvl;
610	boolean_t run_once_flag = FALSE;
611	int32_t vendor_debug = 0;
612	int next_option;
613	char *conf_template = NULL;
614	const char *config_file = NULL;
615	uint32_t val;
616	const char *const short_option =
617	    "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:";
618
619	/*
620	   In the array below, the 2nd parameter specifies the number
621	   of arguments as follows:
622	   0: no arguments
623	   1: argument
624	   2: optional
625	 */
626	const struct option long_option[] = {
627		{"version", 0, NULL, 12},
628		{"config", 1, NULL, 'F'},
629		{"create-config", 1, NULL, 'c'},
630		{"debug", 1, NULL, 'd'},
631		{"guid", 1, NULL, 'g'},
632		{"ignore_guids", 1, NULL, 'i'},
633		{"hop_weights_file", 1, NULL, 'w'},
634		{"dimn_ports_file", 1, NULL, 'O'},
635		{"port_search_ordering_file", 1, NULL, 'O'},
636		{"lmc", 1, NULL, 'l'},
637		{"sweep", 1, NULL, 's'},
638		{"timeout", 1, NULL, 't'},
639		{"verbose", 0, NULL, 'v'},
640		{"D", 1, NULL, 'D'},
641		{"log_file", 1, NULL, 'f'},
642		{"log_limit", 1, NULL, 'L'},
643		{"erase_log_file", 0, NULL, 'e'},
644		{"Pconfig", 1, NULL, 'P'},
645		{"no_part_enforce", 0, NULL, 'N'},
646		{"part_enforce", 1, NULL, 'Z'},
647		{"allow_both_pkeys", 0, NULL, 'W'},
648		{"qos", 0, NULL, 'Q'},
649		{"qos_policy_file", 1, NULL, 'Y'},
650		{"congestion_control", 0, NULL, 128},
651		{"cc_key", 1, NULL, 129},
652		{"maxsmps", 1, NULL, 'n'},
653		{"console", 1, NULL, 'q'},
654		{"V", 0, NULL, 'V'},
655		{"help", 0, NULL, 'h'},
656		{"once", 0, NULL, 'o'},
657		{"reassign_lids", 0, NULL, 'r'},
658		{"priority", 1, NULL, 'p'},
659		{"smkey", 1, NULL, 'k'},
660		{"routing_engine", 1, NULL, 'R'},
661		{"ucast_cache", 0, NULL, 'A'},
662		{"connect_roots", 0, NULL, 'z'},
663		{"lid_matrix_file", 1, NULL, 'M'},
664		{"lfts_file", 1, NULL, 'U'},
665		{"sadb_file", 1, NULL, 'S'},
666		{"root_guid_file", 1, NULL, 'a'},
667		{"cn_guid_file", 1, NULL, 'u'},
668		{"io_guid_file", 1, NULL, 'G'},
669		{"port-shifting", 0, NULL, 11},
670		{"scatter-ports", 1, NULL, 14},
671		{"max_reverse_hops", 1, NULL, 'H'},
672		{"ids_guid_file", 1, NULL, 'm'},
673		{"guid_routing_order_file", 1, NULL, 'X'},
674		{"stay_on_fatal", 0, NULL, 'y'},
675		{"honor_guid2lid", 0, NULL, 'x'},
676#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
677		{"console-port", 1, NULL, 'C'},
678#endif
679		{"daemon", 0, NULL, 'B'},
680		{"pidfile", 1, NULL, 'J'},
681		{"inactive", 0, NULL, 'I'},
682#ifdef ENABLE_OSM_PERF_MGR
683		{"perfmgr", 0, NULL, 1},
684		{"perfmgr_sweep_time_s", 1, NULL, 2},
685#endif
686		{"prefix_routes_file", 1, NULL, 3},
687		{"consolidate_ipv6_snm_req", 0, NULL, 4},
688		{"do_mesh_analysis", 0, NULL, 5},
689		{"lash_start_vl", 1, NULL, 6},
690		{"sm_sl", 1, NULL, 7},
691		{"retries", 1, NULL, 8},
692		{"log_prefix", 1, NULL, 9},
693		{"torus_config", 1, NULL, 10},
694		{"guid_routing_order_no_scatter", 0, NULL, 13},
695		{NULL, 0, NULL, 0}	/* Required at the end of the array */
696	};
697
698	/* force stdout to be line-buffered */
699	setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
700
701	/* Make sure that the opensm and complib were compiled using
702	   same modes (debug/free) */
703	if (osm_is_debug() != cl_is_debug()) {
704		fprintf(stderr,
705			"ERROR: OpenSM and Complib were compiled using different modes\n");
706		fprintf(stderr, "ERROR: OpenSM debug:%d Complib debug:%d \n",
707			osm_is_debug(), cl_is_debug());
708		exit(1);
709	}
710
711	printf("-------------------------------------------------\n");
712	printf("%s\n", OSM_VERSION);
713
714	do {
715		next_option = getopt_long_only(argc, argv, short_option,
716					       long_option, NULL);
717		switch (next_option) {
718		case 'F':
719			config_file = optarg;
720			printf("Config file is `%s`:\n", config_file);
721			break;
722		default:
723			break;
724		}
725	} while (next_option != -1);
726
727	optind = 0;		/* reset command line */
728
729	if (!config_file)
730		config_file = OSM_DEFAULT_CONFIG_FILE;
731
732	osm_subn_set_default_opt(&opt);
733
734	if (osm_subn_parse_conf_file(config_file, &opt) < 0)
735		printf("\nFail to parse config file \'%s\'\n", config_file);
736
737	printf("Command Line Arguments:\n");
738	do {
739		next_option = getopt_long_only(argc, argv, short_option,
740					       long_option, NULL);
741		switch (next_option) {
742		case 12:	/* --version - already printed above */
743			exit(0);
744			break;
745		case 'F':
746			break;
747		case 'c':
748			conf_template = optarg;
749			printf(" Creating config file template \'%s\'.\n",
750			       conf_template);
751			break;
752		case 'o':
753			/*
754			   Run once option.
755			 */
756			run_once_flag = TRUE;
757			printf(" Run Once\n");
758			break;
759
760		case 'r':
761			/*
762			   Reassign LIDs subnet option.
763			 */
764			opt.reassign_lids = TRUE;
765			printf(" Reassign LIDs\n");
766			break;
767
768		case 'i':
769			/*
770			   Specifies ignore guids file.
771			 */
772			SET_STR_OPT(opt.port_prof_ignore_file, optarg);
773			printf(" Ignore Guids File = %s\n",
774			       opt.port_prof_ignore_file);
775			break;
776
777		case 'w':
778			SET_STR_OPT(opt.hop_weights_file, optarg);
779			printf(" Hop Weights File = %s\n",
780			       opt.hop_weights_file);
781			break;
782
783		case 'O':
784			SET_STR_OPT(opt.port_search_ordering_file, optarg);
785			printf(" Port Search Ordering/Dimension Ports File = %s\n",
786			       opt.port_search_ordering_file);
787			break;
788
789		case 'g':
790			/*
791			   Specifies port guid with which to bind.
792			 */
793			opt.guid = cl_hton64(strtoull(optarg, NULL, 16));
794			if (!opt.guid)
795				/* If guid is 0 - need to display the
796				 * guid list */
797				opt.guid = INVALID_GUID;
798			else
799				printf(" Guid <0x%" PRIx64 ">\n",
800				       cl_hton64(opt.guid));
801			break;
802
803		case 's':
804			val = strtol(optarg, NULL, 0);
805			/* Check that the number is not too large */
806			if (((uint32_t) (val * 1000000)) / 1000000 != val)
807				fprintf(stderr,
808					"ERROR: sweep interval given is too large. Ignoring it.\n");
809			else {
810				opt.sweep_interval = val;
811				printf(" sweep interval = %d\n",
812				       opt.sweep_interval);
813			}
814			break;
815
816		case 't':
817			val = strtoul(optarg, NULL, 0);
818			opt.transaction_timeout = strtoul(optarg, NULL, 0);
819			if (val == 0)
820				fprintf(stderr, "ERROR: timeout value 0 is invalid. Ignoring it.\n");
821			else {
822				opt.transaction_timeout = val;
823				printf(" Transaction timeout = %u\n",
824				       opt.transaction_timeout);
825			}
826			break;
827
828		case 'n':
829			opt.max_wire_smps = strtoul(optarg, NULL, 0);
830			if (opt.max_wire_smps == 0 ||
831			    opt.max_wire_smps > 0x7FFFFFFF)
832				opt.max_wire_smps = 0x7FFFFFFF;
833			printf(" Max wire smp's = %d\n", opt.max_wire_smps);
834			break;
835
836		case 'q':
837			/*
838			 * OpenSM interactive console
839			 */
840			if (strcmp(optarg, OSM_DISABLE_CONSOLE) == 0
841			    || strcmp(optarg, OSM_LOCAL_CONSOLE) == 0
842#ifdef ENABLE_OSM_CONSOLE_SOCKET
843			    || strcmp(optarg, OSM_REMOTE_CONSOLE) == 0
844#endif
845#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
846			    || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0
847#endif
848			    )
849				SET_STR_OPT(opt.console, optarg);
850			else
851				printf("-console %s option not understood\n",
852				       optarg);
853			break;
854
855#ifdef ENABLE_OSM_CONSOLE_LOOPBACK
856		case 'C':
857			opt.console_port = strtol(optarg, NULL, 0);
858			break;
859#endif
860
861		case 'd':
862			dbg_lvl = strtol(optarg, NULL, 0);
863			printf(" d level = 0x%x\n", dbg_lvl);
864			if (dbg_lvl == 0) {
865				printf(" Debug mode: Ignore Other SMs\n");
866				opt.ignore_other_sm = TRUE;
867			} else if (dbg_lvl == 1) {
868				printf(" Debug mode: Forcing Single Thread\n");
869				opt.single_thread = TRUE;
870			} else if (dbg_lvl == 2) {
871				printf(" Debug mode: Force Log Flush\n");
872				opt.force_log_flush = TRUE;
873			} else if (dbg_lvl == 3) {
874				printf
875				    (" Debug mode: Disable multicast support\n");
876				opt.disable_multicast = TRUE;
877			}
878			/*
879			 * NOTE: Debug level 4 used to be used for memory
880			 * tracking but this is now deprecated
881			 */
882			else if (dbg_lvl == 5)
883				vendor_debug++;
884			else
885				printf(" OpenSM: Unknown debug option %d"
886				       " ignored\n", dbg_lvl);
887			break;
888
889		case 'l':
890			temp = strtoul(optarg, NULL, 0);
891			if (temp > 7) {
892				fprintf(stderr,
893					"ERROR: LMC must be 7 or less.\n");
894				return -1;
895			}
896			opt.lmc = (uint8_t) temp;
897			printf(" LMC = %d\n", temp);
898			break;
899
900		case 'D':
901			opt.log_flags = strtol(optarg, NULL, 0);
902			printf(" verbose option -D = 0x%x\n", opt.log_flags);
903			break;
904
905		case 'f':
906			SET_STR_OPT(opt.log_file, optarg);
907			break;
908
909		case 'L':
910			opt.log_max_size = strtoul(optarg, NULL, 0);
911			printf(" Log file max size is %u MBytes\n",
912			       opt.log_max_size);
913			break;
914
915		case 'e':
916			opt.accum_log_file = FALSE;
917			printf(" Creating new log file\n");
918			break;
919
920		case 'J':
921			pidfile = optarg;
922			break;
923
924		case 'P':
925			SET_STR_OPT(opt.partition_config_file, optarg);
926			break;
927
928		case 'N':
929			opt.no_partition_enforcement = TRUE;
930			break;
931
932		case 'Z':
933			if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0
934			    || strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0
935			    || strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0
936			    || strcmp(optarg, OSM_PARTITION_ENFORCE_OFF) == 0) {
937				SET_STR_OPT(opt.part_enforce, optarg);
938				if (strcmp(optarg, OSM_PARTITION_ENFORCE_BOTH) == 0)
939					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_BOTH;
940				else if (strcmp(optarg, OSM_PARTITION_ENFORCE_IN) == 0)
941					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_IN;
942				else if (strcmp(optarg, OSM_PARTITION_ENFORCE_OUT) == 0)
943					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OUT;
944				else
945					opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF;
946			} else
947				printf("-part_enforce %s option not understood\n",
948				       optarg);
949			break;
950
951		case 'W':
952			opt.allow_both_pkeys = TRUE;
953			break;
954
955		case 'Q':
956			opt.qos = TRUE;
957			break;
958
959		case 'Y':
960			SET_STR_OPT(opt.qos_policy_file, optarg);
961			printf(" QoS policy file \'%s\'\n", optarg);
962			break;
963
964		case 128:
965			opt.congestion_control = TRUE;
966			break;
967
968		case 129:
969			opt.cc_key = strtoull(optarg, NULL, 0);
970			printf(" CC Key 0x%" PRIx64 "\n", opt.cc_key);
971			break;
972
973		case 'y':
974			opt.exit_on_fatal = FALSE;
975			printf(" Staying on fatal initialization errors\n");
976			break;
977
978		case 'v':
979			opt.log_flags = (opt.log_flags << 1) | 1;
980			printf(" Verbose option -v (log flags = 0x%X)\n",
981			       opt.log_flags);
982			break;
983
984		case 'V':
985			opt.log_flags = 0xFF;
986			opt.force_log_flush = TRUE;
987			printf(" Big V selected\n");
988			break;
989
990		case 'p':
991			temp = strtoul(optarg, NULL, 0);
992			if (temp > 15) {
993				fprintf(stderr,
994					"ERROR: priority must be between 0 and 15\n");
995				return -1;
996			}
997			opt.sm_priority = (uint8_t) temp;
998			printf(" Priority = %d\n", temp);
999			break;
1000
1001		case 'k':
1002			sm_key = cl_hton64(strtoull(optarg, NULL, 16));
1003			printf(" SM Key <0x%" PRIx64 ">\n", cl_hton64(sm_key));
1004			opt.sm_key = sm_key;
1005			break;
1006
1007		case 'R':
1008			SET_STR_OPT(opt.routing_engine_names, optarg);
1009			printf(" Activate \'%s\' routing engine(s)\n", optarg);
1010			break;
1011
1012		case 'z':
1013			opt.connect_roots = TRUE;
1014			printf(" Connect roots option is on\n");
1015			break;
1016
1017		case 'A':
1018			opt.use_ucast_cache = TRUE;
1019			printf(" Unicast routing cache option is on\n");
1020			break;
1021
1022		case 'M':
1023			SET_STR_OPT(opt.lid_matrix_dump_file, optarg);
1024			printf(" Lid matrix dump file is \'%s\'\n", optarg);
1025			break;
1026
1027		case 'U':
1028			SET_STR_OPT(opt.lfts_file, optarg);
1029			printf(" LFTs file is \'%s\'\n", optarg);
1030			break;
1031
1032		case 'S':
1033			SET_STR_OPT(opt.sa_db_file, optarg);
1034			printf(" SA DB file is \'%s\'\n", optarg);
1035			break;
1036
1037		case 'a':
1038			SET_STR_OPT(opt.root_guid_file, optarg);
1039			printf(" Root Guid File: %s\n", opt.root_guid_file);
1040			break;
1041
1042		case 'u':
1043			SET_STR_OPT(opt.cn_guid_file, optarg);
1044			printf(" Compute Node Guid File: %s\n",
1045			       opt.cn_guid_file);
1046			break;
1047
1048		case 'G':
1049			SET_STR_OPT(opt.io_guid_file, optarg);
1050			printf(" I/O Node Guid File: %s\n", opt.io_guid_file);
1051			break;
1052		case 11:
1053			opt.port_shifting = TRUE;
1054			printf(" Port Shifting is on\n");
1055			break;
1056		case 14:
1057			opt.scatter_ports = strtol(optarg, NULL, 0);
1058			printf(" Scatter Ports is on\n");
1059			break;
1060		case 'H':
1061			opt.max_reverse_hops = atoi(optarg);
1062			printf(" Max Reverse Hops: %d\n", opt.max_reverse_hops);
1063			break;
1064		case 'm':
1065			SET_STR_OPT(opt.ids_guid_file, optarg);
1066			printf(" IDs Guid File: %s\n", opt.ids_guid_file);
1067			break;
1068
1069		case 'X':
1070			SET_STR_OPT(opt.guid_routing_order_file, optarg);
1071			printf(" GUID Routing Order File: %s\n",
1072			       opt.guid_routing_order_file);
1073			break;
1074
1075		case 'x':
1076			opt.honor_guid2lid_file = TRUE;
1077			printf(" Honor guid2lid file, if possible\n");
1078			break;
1079
1080		case 'B':
1081			opt.daemon = TRUE;
1082			printf(" Daemon mode\n");
1083			break;
1084
1085		case 'I':
1086			opt.sm_inactive = TRUE;
1087			printf(" SM started in inactive state\n");
1088			break;
1089
1090#ifdef ENABLE_OSM_PERF_MGR
1091		case 1:
1092			opt.perfmgr = TRUE;
1093			break;
1094		case 2:
1095			opt.perfmgr_sweep_time_s = atoi(optarg);
1096			break;
1097#endif				/* ENABLE_OSM_PERF_MGR */
1098
1099		case 3:
1100			SET_STR_OPT(opt.prefix_routes_file, optarg);
1101			break;
1102		case 4:
1103			opt.consolidate_ipv6_snm_req = TRUE;
1104			break;
1105		case 5:
1106			opt.do_mesh_analysis = TRUE;
1107			break;
1108		case 6:
1109			temp = strtoul(optarg, NULL, 0);
1110			if (temp >= IB_MAX_NUM_VLS) {
1111				fprintf(stderr,
1112					"ERROR: starting lash vl must be between 0 and 15\n");
1113				return -1;
1114			}
1115			opt.lash_start_vl = (uint8_t) temp;
1116			printf(" LASH starting VL = %d\n", opt.lash_start_vl);
1117			break;
1118		case 7:
1119			temp = strtoul(optarg, NULL, 0);
1120			if (temp > 15) {
1121				fprintf(stderr,
1122					"ERROR: SM's SL must be between 0 and 15\n");
1123				return -1;
1124			}
1125			opt.sm_sl = (uint8_t) temp;
1126			printf(" SMSL = %d\n", opt.sm_sl);
1127			break;
1128		case 8:
1129			opt.transaction_retries = strtoul(optarg, NULL, 0);
1130			printf(" Transaction retries = %u\n",
1131			       opt.transaction_retries);
1132			break;
1133		case 9:
1134			SET_STR_OPT(opt.log_prefix, optarg);
1135			printf("Log prefix = %s\n", opt.log_prefix);
1136			break;
1137		case 10:
1138			SET_STR_OPT(opt.torus_conf_file, optarg);
1139			printf("Torus-2QoS config file = %s\n", opt.torus_conf_file);
1140			break;
1141		case 13:
1142			opt.guid_routing_order_no_scatter = TRUE;
1143			break;
1144		case 'h':
1145		case '?':
1146		case ':':
1147			show_usage();
1148			break;
1149
1150		case -1:
1151			break;	/* done with option */
1152		default:	/* something wrong */
1153			abort();
1154		}
1155	} while (next_option != -1);
1156
1157	if (opt.log_file != NULL)
1158		printf(" Log File: %s\n", opt.log_file);
1159	/* Done with options description */
1160	printf("-------------------------------------------------\n");
1161
1162	if (conf_template) {
1163		status = osm_subn_write_conf_file(conf_template, &opt);
1164		if (status)
1165			printf("\nosm_subn_write_conf_file failed!\n");
1166		exit(status);
1167	}
1168
1169	osm_subn_verify_config(&opt);
1170
1171	if (vendor_debug)
1172		osm_vendor_set_debug(osm.p_vendor, vendor_debug);
1173
1174	block_signals();
1175
1176	if (opt.daemon) {
1177		if (INVALID_GUID == opt.guid) {
1178			fprintf(stderr,
1179				"ERROR: Invalid GUID specified; exiting because of daemon mode\n");
1180			return -1;
1181		}
1182		daemonize(&osm);
1183	}
1184
1185	complib_init();
1186
1187	status = osm_opensm_init(&osm, &opt);
1188	if (status != IB_SUCCESS) {
1189		const char *err_str = ib_get_err_str(status);
1190		if (err_str == NULL)
1191			err_str = "Unknown Error Type";
1192		printf("\nError from osm_opensm_init: %s.\n", err_str);
1193		/* We will just exit, and not go to Exit, since we don't
1194		   want the destroy to be called. */
1195		complib_exit();
1196		return status;
1197	}
1198
1199	/*
1200	   If the user didn't specify a GUID on the command line,
1201	   then get a port GUID value with which to bind.
1202	 */
1203	if (opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID))
1204		opt.guid = get_port_guid(&osm, opt.guid);
1205
1206	if (opt.guid == 0)
1207		goto Exit2;
1208
1209	status = osm_opensm_init_finish(&osm, &opt);
1210	if (status != IB_SUCCESS) {
1211		const char *err_str = ib_get_err_str(status);
1212		if (err_str == NULL)
1213			err_str = "Unknown Error Type";
1214		printf("\nError from osm_opensm_init_finish: %s.\n", err_str);
1215		goto Exit2;
1216	}
1217
1218	status = osm_opensm_bind(&osm, opt.guid);
1219	if (status != IB_SUCCESS) {
1220		printf("\nError from osm_opensm_bind (0x%X)\n", status);
1221		printf
1222		    ("Perhaps another instance of OpenSM is already running\n");
1223		goto Exit;
1224	}
1225
1226	setup_signals();
1227
1228	osm_opensm_sweep(&osm);
1229
1230	if (run_once_flag == TRUE) {
1231		while (!osm_exit_flag) {
1232			status =
1233			    osm_opensm_wait_for_subnet_up(&osm,
1234							  osm.subn.opt.
1235							  sweep_interval *
1236							  1000000, TRUE);
1237			if (!status)
1238				osm_exit_flag = 1;
1239		}
1240	} else {
1241		/*
1242		 *         Sit here until signaled to exit
1243		 */
1244		osm_manager_loop(&opt, &osm);
1245	}
1246
1247	if (osm.mad_pool.mads_out) {
1248		fprintf(stdout,
1249			"There are still %u MADs out. Forcing the exit of the OpenSM application...\n",
1250			osm.mad_pool.mads_out);
1251#ifdef HAVE_LIBPTHREAD
1252		pthread_cond_signal(&osm.stats.cond);
1253#else
1254		cl_event_signal(&osm.stats.event);
1255#endif
1256	}
1257
1258Exit:
1259	osm_opensm_destroy(&osm);
1260Exit2:
1261	osm_opensm_destroy_finish(&osm);
1262	complib_exit();
1263	remove_pidfile();
1264
1265	exit(0);
1266}
1267