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