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 62volatile unsigned int osm_exit_flag = 0; 63 64static volatile unsigned int osm_hup_flag = 0; 65static volatile unsigned int osm_usr1_flag = 0; 66 67#define GUID_ARRAY_SIZE 64 68#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL) 69 70static 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 77static void mark_hup_flag(int signum) 78{ 79 osm_hup_flag = 1; 80} 81 82static void mark_usr1_flag(int signum) 83{ 84 osm_usr1_flag = 1; 85} 86 87static sigset_t saved_sigset; 88 89static 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 103static 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 125static 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 **********************************************************************/ 355static 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 441static 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 **********************************************************************/ 479int 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 **********************************************************************/ 515int 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 1022Exit: 1023 osm_opensm_destroy(&osm); 1024 complib_exit(); 1025 1026 exit(0); 1027} 1028