]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/opensm/opensm/main.c
MFV r357608: Limit memory usage in xz(1) instead of in tuklib.
[FreeBSD/FreeBSD.git] / contrib / ofed / opensm / opensm / main.c
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
67 volatile unsigned int osm_exit_flag = 0;
68
69 static volatile unsigned int osm_hup_flag = 0;
70 static volatile unsigned int osm_usr1_flag = 0;
71 static char *pidfile;
72
73 #define MAX_LOCAL_IBPORTS 64
74 #define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
75
76 static 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
83 static void mark_hup_flag(int signum)
84 {
85         osm_hup_flag = 1;
86 }
87
88 static void mark_usr1_flag(int signum)
89 {
90         osm_usr1_flag = 1;
91 }
92
93 static sigset_t saved_sigset;
94
95 static 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
109 static 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
128 static 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
429 static 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
509 static void remove_pidfile(void)
510 {
511         if (pidfile)
512                 unlink(pidfile);
513 }
514
515 static 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
564 int 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
603 int 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
1258 Exit:
1259         osm_opensm_destroy(&osm);
1260 Exit2:
1261         osm_opensm_destroy_finish(&osm);
1262         complib_exit();
1263         remove_pidfile();
1264
1265         exit(0);
1266 }