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