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.
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:
15 * Redistribution and use in source and binary forms, with or
16 * without modification, are permitted provided that the following
19 * - Redistributions of source code must retain the above
20 * copyright notice, this list of conditions and the following
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.
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
41 * Command line interface for opensm.
46 #endif /* HAVE_CONFIG_H */
53 #include <sys/types.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>
67 volatile unsigned int osm_exit_flag = 0;
69 static volatile unsigned int osm_hup_flag = 0;
70 static volatile unsigned int osm_usr1_flag = 0;
73 #define MAX_LOCAL_IBPORTS 64
74 #define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
76 static void mark_exit_flag(int signum)
79 printf("OpenSM: Got signal %d - exiting...\n", signum);
83 static void mark_hup_flag(int signum)
88 static void mark_usr1_flag(int signum)
93 static sigset_t saved_sigset;
95 static void block_signals()
100 sigaddset(&set, SIGINT);
101 sigaddset(&set, SIGTERM);
102 sigaddset(&set, SIGHUP);
103 #ifndef HAVE_OLD_LINUX_THREADS
104 sigaddset(&set, SIGUSR1);
106 pthread_sigmask(SIG_SETMASK, &set, &saved_sigset);
109 static void setup_signals()
111 struct sigaction act;
113 sigemptyset(&act.sa_mask);
114 act.sa_handler = mark_exit_flag;
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);
125 pthread_sigmask(SIG_SETMASK, &saved_sigset, NULL);
128 static void show_usage(void)
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"
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"
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"
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
283 #ifdef ENABLE_OSM_CONSOLE_SOCKET
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);
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"
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
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");
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");
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"
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");
429 static ib_net64_t get_port_guid(IN osm_opensm_t * p_osm, uint64_t port_guid)
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;
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;
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,
446 if (status != IB_SUCCESS) {
447 printf("\nError from osm_vendor_get_all_port_attr (%x)\n",
452 /* if num_ports is 0 - return 0 */
453 if (num_ports == 0) {
454 printf("\nNo local ports detected!\n");
457 /* If num_ports is 1, then there is only one possible port to use.
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;
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)
471 printf("Using default GUID 0x%" PRIx64 "\n",
472 cl_hton64(attr_array[i].port_guid));
473 return attr_array[i].port_guid;
476 if (p_osm->subn.opt.daemon)
479 /* More than one possible port - list all ports and let the user
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),
489 ib_get_port_state_str(attr_array[i].link_state));
490 printf("\n\t0: Exit\n");
491 printf("\nEnter choice (0-%u): ", i);
493 if (scanf("%u", &choice) <= 0) {
495 if (scanf("%s", junk) <= 0)
496 printf("\nError: Cannot scan!\n");
497 } else if (choice == 0)
499 else if (choice <= num_ports)
501 printf("\nError: Lame choice! Please try again.\n");
504 printf("Choice guid=0x%" PRIx64 "\n",
505 cl_ntoh64(attr_array[choice].port_guid));
506 return attr_array[choice].port_guid;
509 static void remove_pidfile(void)
515 static int daemonize(osm_opensm_t * osm)
521 fd = open("/dev/null", O_WRONLY);
527 if ((pid = fork()) < 0) {
535 if ((pid = fork()) < 0) {
543 f = fopen(pidfile, "w");
545 fprintf(f, "%d\n", getpid());
564 int osm_manager_loop(osm_subn_opt_t * p_opt, osm_opensm_t * p_osm)
566 int console_init_flag = 0;
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;
574 Sit here forever - dwell or do console i/o & cmds
576 while (!osm_exit_flag) {
577 if (console_init_flag) {
578 if (osm_console(p_osm))
579 console_init_flag = 0;
581 cl_thread_suspend(10000);
585 osm_log_reopen_file(&(p_osm->log));
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);
594 if (is_console_enabled(p_opt))
595 osm_console_exit(&p_osm->console, &p_osm->log);
599 #define SET_STR_OPT(opt, val) do { \
600 opt = val ? strdup(val) : NULL ; \
603 int main(int argc, char *argv[])
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;
613 char *conf_template = NULL;
614 const char *config_file = NULL;
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:";
620 In the array below, the 2nd parameter specifies the number
621 of arguments as follows:
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'},
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'},
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'},
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},
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 */
698 /* force stdout to be line-buffered */
699 setvbuf(stdout, NULL, _IOLBF, BUFSIZ);
701 /* Make sure that the opensm and complib were compiled using
702 same modes (debug/free) */
703 if (osm_is_debug() != cl_is_debug()) {
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());
711 printf("-------------------------------------------------\n");
712 printf("%s\n", OSM_VERSION);
715 next_option = getopt_long_only(argc, argv, short_option,
717 switch (next_option) {
719 config_file = optarg;
720 printf("Config file is `%s`:\n", config_file);
725 } while (next_option != -1);
727 optind = 0; /* reset command line */
730 config_file = OSM_DEFAULT_CONFIG_FILE;
732 osm_subn_set_default_opt(&opt);
734 if (osm_subn_parse_conf_file(config_file, &opt) < 0)
735 printf("\nFail to parse config file \'%s\'\n", config_file);
737 printf("Command Line Arguments:\n");
739 next_option = getopt_long_only(argc, argv, short_option,
741 switch (next_option) {
742 case 12: /* --version - already printed above */
748 conf_template = optarg;
749 printf(" Creating config file template \'%s\'.\n",
756 run_once_flag = TRUE;
757 printf(" Run Once\n");
762 Reassign LIDs subnet option.
764 opt.reassign_lids = TRUE;
765 printf(" Reassign LIDs\n");
770 Specifies ignore guids file.
772 SET_STR_OPT(opt.port_prof_ignore_file, optarg);
773 printf(" Ignore Guids File = %s\n",
774 opt.port_prof_ignore_file);
778 SET_STR_OPT(opt.hop_weights_file, optarg);
779 printf(" Hop Weights File = %s\n",
780 opt.hop_weights_file);
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);
791 Specifies port guid with which to bind.
793 opt.guid = cl_hton64(strtoull(optarg, NULL, 16));
795 /* If guid is 0 - need to display the
797 opt.guid = INVALID_GUID;
799 printf(" Guid <0x%" PRIx64 ">\n",
800 cl_hton64(opt.guid));
804 val = strtol(optarg, NULL, 0);
805 /* Check that the number is not too large */
806 if (((uint32_t) (val * 1000000)) / 1000000 != val)
808 "ERROR: sweep interval given is too large. Ignoring it.\n");
810 opt.sweep_interval = val;
811 printf(" sweep interval = %d\n",
817 val = strtoul(optarg, NULL, 0);
818 opt.transaction_timeout = strtoul(optarg, NULL, 0);
820 fprintf(stderr, "ERROR: timeout value 0 is invalid. Ignoring it.\n");
822 opt.transaction_timeout = val;
823 printf(" Transaction timeout = %u\n",
824 opt.transaction_timeout);
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);
838 * OpenSM interactive console
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
845 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
846 || strcmp(optarg, OSM_LOOPBACK_CONSOLE) == 0
849 SET_STR_OPT(opt.console, optarg);
851 printf("-console %s option not understood\n",
855 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
857 opt.console_port = strtol(optarg, NULL, 0);
862 dbg_lvl = strtol(optarg, NULL, 0);
863 printf(" d level = 0x%x\n", dbg_lvl);
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) {
875 (" Debug mode: Disable multicast support\n");
876 opt.disable_multicast = TRUE;
879 * NOTE: Debug level 4 used to be used for memory
880 * tracking but this is now deprecated
882 else if (dbg_lvl == 5)
885 printf(" OpenSM: Unknown debug option %d"
886 " ignored\n", dbg_lvl);
890 temp = strtoul(optarg, NULL, 0);
893 "ERROR: LMC must be 7 or less.\n");
896 opt.lmc = (uint8_t) temp;
897 printf(" LMC = %d\n", temp);
901 opt.log_flags = strtol(optarg, NULL, 0);
902 printf(" verbose option -D = 0x%x\n", opt.log_flags);
906 SET_STR_OPT(opt.log_file, optarg);
910 opt.log_max_size = strtoul(optarg, NULL, 0);
911 printf(" Log file max size is %u MBytes\n",
916 opt.accum_log_file = FALSE;
917 printf(" Creating new log file\n");
925 SET_STR_OPT(opt.partition_config_file, optarg);
929 opt.no_partition_enforcement = TRUE;
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;
945 opt.part_enforce_enum = OSM_PARTITION_ENFORCE_TYPE_OFF;
947 printf("-part_enforce %s option not understood\n",
952 opt.allow_both_pkeys = TRUE;
960 SET_STR_OPT(opt.qos_policy_file, optarg);
961 printf(" QoS policy file \'%s\'\n", optarg);
965 opt.congestion_control = TRUE;
969 opt.cc_key = strtoull(optarg, NULL, 0);
970 printf(" CC Key 0x%" PRIx64 "\n", opt.cc_key);
974 opt.exit_on_fatal = FALSE;
975 printf(" Staying on fatal initialization errors\n");
979 opt.log_flags = (opt.log_flags << 1) | 1;
980 printf(" Verbose option -v (log flags = 0x%X)\n",
985 opt.log_flags = 0xFF;
986 opt.force_log_flush = TRUE;
987 printf(" Big V selected\n");
991 temp = strtoul(optarg, NULL, 0);
994 "ERROR: priority must be between 0 and 15\n");
997 opt.sm_priority = (uint8_t) temp;
998 printf(" Priority = %d\n", temp);
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;
1008 SET_STR_OPT(opt.routing_engine_names, optarg);
1009 printf(" Activate \'%s\' routing engine(s)\n", optarg);
1013 opt.connect_roots = TRUE;
1014 printf(" Connect roots option is on\n");
1018 opt.use_ucast_cache = TRUE;
1019 printf(" Unicast routing cache option is on\n");
1023 SET_STR_OPT(opt.lid_matrix_dump_file, optarg);
1024 printf(" Lid matrix dump file is \'%s\'\n", optarg);
1028 SET_STR_OPT(opt.lfts_file, optarg);
1029 printf(" LFTs file is \'%s\'\n", optarg);
1033 SET_STR_OPT(opt.sa_db_file, optarg);
1034 printf(" SA DB file is \'%s\'\n", optarg);
1038 SET_STR_OPT(opt.root_guid_file, optarg);
1039 printf(" Root Guid File: %s\n", opt.root_guid_file);
1043 SET_STR_OPT(opt.cn_guid_file, optarg);
1044 printf(" Compute Node Guid File: %s\n",
1049 SET_STR_OPT(opt.io_guid_file, optarg);
1050 printf(" I/O Node Guid File: %s\n", opt.io_guid_file);
1053 opt.port_shifting = TRUE;
1054 printf(" Port Shifting is on\n");
1057 opt.scatter_ports = strtol(optarg, NULL, 0);
1058 printf(" Scatter Ports is on\n");
1061 opt.max_reverse_hops = atoi(optarg);
1062 printf(" Max Reverse Hops: %d\n", opt.max_reverse_hops);
1065 SET_STR_OPT(opt.ids_guid_file, optarg);
1066 printf(" IDs Guid File: %s\n", opt.ids_guid_file);
1070 SET_STR_OPT(opt.guid_routing_order_file, optarg);
1071 printf(" GUID Routing Order File: %s\n",
1072 opt.guid_routing_order_file);
1076 opt.honor_guid2lid_file = TRUE;
1077 printf(" Honor guid2lid file, if possible\n");
1082 printf(" Daemon mode\n");
1086 opt.sm_inactive = TRUE;
1087 printf(" SM started in inactive state\n");
1090 #ifdef ENABLE_OSM_PERF_MGR
1095 opt.perfmgr_sweep_time_s = atoi(optarg);
1097 #endif /* ENABLE_OSM_PERF_MGR */
1100 SET_STR_OPT(opt.prefix_routes_file, optarg);
1103 opt.consolidate_ipv6_snm_req = TRUE;
1106 opt.do_mesh_analysis = TRUE;
1109 temp = strtoul(optarg, NULL, 0);
1110 if (temp >= IB_MAX_NUM_VLS) {
1112 "ERROR: starting lash vl must be between 0 and 15\n");
1115 opt.lash_start_vl = (uint8_t) temp;
1116 printf(" LASH starting VL = %d\n", opt.lash_start_vl);
1119 temp = strtoul(optarg, NULL, 0);
1122 "ERROR: SM's SL must be between 0 and 15\n");
1125 opt.sm_sl = (uint8_t) temp;
1126 printf(" SMSL = %d\n", opt.sm_sl);
1129 opt.transaction_retries = strtoul(optarg, NULL, 0);
1130 printf(" Transaction retries = %u\n",
1131 opt.transaction_retries);
1134 SET_STR_OPT(opt.log_prefix, optarg);
1135 printf("Log prefix = %s\n", opt.log_prefix);
1138 SET_STR_OPT(opt.torus_conf_file, optarg);
1139 printf("Torus-2QoS config file = %s\n", opt.torus_conf_file);
1142 opt.guid_routing_order_no_scatter = TRUE;
1151 break; /* done with option */
1152 default: /* something wrong */
1155 } while (next_option != -1);
1157 if (opt.log_file != NULL)
1158 printf(" Log File: %s\n", opt.log_file);
1159 /* Done with options description */
1160 printf("-------------------------------------------------\n");
1162 if (conf_template) {
1163 status = osm_subn_write_conf_file(conf_template, &opt);
1165 printf("\nosm_subn_write_conf_file failed!\n");
1169 osm_subn_verify_config(&opt);
1172 osm_vendor_set_debug(osm.p_vendor, vendor_debug);
1177 if (INVALID_GUID == opt.guid) {
1179 "ERROR: Invalid GUID specified; exiting because of daemon mode\n");
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. */
1200 If the user didn't specify a GUID on the command line,
1201 then get a port GUID value with which to bind.
1203 if (opt.guid == 0 || cl_hton64(opt.guid) == CL_HTON64(INVALID_GUID))
1204 opt.guid = get_port_guid(&osm, opt.guid);
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);
1218 status = osm_opensm_bind(&osm, opt.guid);
1219 if (status != IB_SUCCESS) {
1220 printf("\nError from osm_opensm_bind (0x%X)\n", status);
1222 ("Perhaps another instance of OpenSM is already running\n");
1228 osm_opensm_sweep(&osm);
1230 if (run_once_flag == TRUE) {
1231 while (!osm_exit_flag) {
1233 osm_opensm_wait_for_subnet_up(&osm,
1242 * Sit here until signaled to exit
1244 osm_manager_loop(&opt, &osm);
1247 if (osm.mad_pool.mads_out) {
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);
1254 cl_event_signal(&osm.stats.event);
1259 osm_opensm_destroy(&osm);
1261 osm_opensm_destroy_finish(&osm);