a5b46512c5df04ef71855ed927ce4a29ad200e8d
[mirror/winof/.git] / ulp / opensm / user / opensm / main.c
1 /*
2  * Copyright (c) 2004, 2005 Voltaire, Inc. All rights reserved.
3  * Copyright (c) 2002-2005 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 the OpenIB.org BSD license
7  * below:
8  *
9  *     Redistribution and use in source and binary forms, with or
10  *     without modification, are permitted provided that the following
11  *     conditions are met:
12  *
13  *      - Redistributions of source code must retain the above
14  *        copyright notice, this list of conditions and the following
15  *        disclaimer.
16  *
17  *      - Redistributions in binary form must reproduce the above
18  *        copyright notice, this list of conditions and the following
19  *        disclaimer in the documentation and/or other materials
20  *        provided with the distribution.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
26  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
28  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29  * SOFTWARE.
30  *
31  * $Id: main.c 3445 2005-09-15 08:35:44Z yael $
32  */
33
34
35 /*
36  * Abstract:
37  *    Command line interface for opensm.
38  *
39  * Environment:
40  *    Linux User Mode
41  *
42  * $Revision: 1.23 $
43  */
44 #pragma warning(disable : 4996)
45
46 #if HAVE_CONFIG_H
47 #  include <config.h>
48 #endif /* HAVE_CONFIG_H */
49
50 #include "stdio.h"
51 #include <stdlib.h>
52 #include <complib/cl_types.h>
53 #include <complib/cl_debug.h>
54 #include <opensm/osm_opensm.h>
55 #include <vendor/osm_vendor_api.h>
56 #include <opensm/osm_ucast_updn.h>
57
58 /********************************************************************
59        D E F I N E    G L O B A L    V A R I A B L E S
60 *********************************************************************/
61 /*
62   This is the global opensm object.
63   One opensm object is required per subnet.
64   Future versions could support multiple subents by
65   instantiating more than one opensm object.
66 */
67 osm_opensm_t osm;
68 volatile int osm_exit_flag = 0;
69
70 #define GUID_ARRAY_SIZE 64
71 #define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL)
72
73 /**********************************************************************
74  **********************************************************************/
75 void show_usage(void);
76
77 void
78 show_usage(void)
79 {
80   printf( "\n------- OpenSM - Usage and options ----------------------\n" );
81   printf( "Usage:   opensm [options]\n");
82   printf( "Options:\n" );
83   printf( "-c\n"
84           "--cache-options\n"
85           "          Cache the given command line options into the file\n"
86           "          /var/cache/osm/opensm.opts for use next invocation\n"
87           "          The cache directory can be changed by the environment\n"
88           "          variable OSM_CACHE_DIR\n\n");
89   printf( "-g <GUID in hex>\n"
90           "--guid <GUID in hex>\n"
91           "          This option specifies the local port GUID value\n"
92           "          with which OpenSM should bind.  OpenSM may be\n"
93           "          bound to 1 port at a time.\n"
94           "          If GUID given is 0, OpenSM displays a list\n"
95           "          of possible port GUIDs and waits for user input.\n"
96           "          Without -g, OpenSM trys to use the default port.\n\n");
97   printf( "-l <LMC>\n"
98           "--lmc <LMC>\n"
99           "          This option specifies the subnet's LMC value.\n"
100           "          The number of LIDs assigned to each port is 2^LMC.\n"
101           "          The LMC value must be in the range 0-7.\n"
102           "          LMC values > 0 allow multiple paths between ports.\n"
103           "          LMC values > 0 should only be used if the subnet\n"
104           "          topology actually provides multiple paths between\n"
105           "          ports, i.e. multiple interconnects between switches.\n"
106           "          Without -l, OpenSM defaults to LMC = 0, which allows\n"
107           "          one path between any two ports.\n\n" );
108   printf( "-p <PRIORITY>\n"
109           "--priority <PRIORITY>\n"
110           "          This option specifies the SM's PRIORITY.\n"
111           "          This will effect the handover cases, where master\n"
112           "          is chosen by priority and GUID.\n" );
113   printf( "-r\n"
114           "--reassign_lids\n"
115           "          This option causes OpenSM to reassign LIDs to all\n"
116           "          end nodes. Specifying -r on a running subnet\n"
117           "          may disrupt subnet traffic.\n"
118           "          Without -r, OpenSM attempts to preserve existing\n"
119           "          LID assignments resolving multiple use of same LID.\n\n");
120   printf( "-u\n"
121           "--updn\n"
122           "          This option activate UPDN algorithm instead of Min Hop\n"
123           "          algorithm (default).\n");
124   printf ("-a\n"
125           "--add_guid_file <path to file>\n"
126           "          Set the root nodes for the Up/Down routing algorithm\n"
127           "          to the guids provided in the given file (one at a line)\n"
128           "\n");
129   printf( "-o\n"
130           "--once\n"
131           "          This option causes OpenSM to configure the subnet\n"
132           "          once, then exit.  Ports remain in the ACTIVE state.\n" );
133   printf( "-s <interval>\n"
134           "--sweep <interval>\n"
135           "          This option specifies the number of seconds between\n"
136           "          subnet sweeps.  Specifying -s 0 disables sweeping.\n"
137           "          Without -s, OpenSM defaults to a sweep interval of\n"
138           "          10 seconds.\n\n" );
139   printf( "-t <milliseconds>\n"
140           "--timeout <milliseconds>\n"
141           "          This option specifies the time in milliseconds\n"
142           "          used for transaction timeouts.\n"
143           "          Specifying -t 0 disables timeouts.\n"
144           "          Without -t, OpenSM defaults to a timeout value of\n"
145           "          100 milliseconds.\n\n" );
146   printf( "-maxsmps <number>\n"
147           "          This option specifies the number of VL15 SMP MADs\n"
148           "          allowed on the wire at any one time.\n"
149           "          Specifying -maxsmps 0 allows unlimited outstanding\n"
150           "          SMPs.\n"
151           "          Without -maxsmps, OpenSM defaults to a maximum of\n"
152           "          one outstanding SMP.\n\n" );
153   printf( "-i <equalize-ignore-guids-file>\n"
154           "-ignore-guids <equalize-ignore-guids-file>\n"
155           "          This option provides means to define a set of ports\n"
156           "          (by guids) that will be ignored by the link load \n"
157           "          equalization algorithm.\n\n" );
158   printf( "-f\n"
159           "--log_file\n"
160           "          This option defines the log to be the given file.\n"
161           "          By default the log goes to /var/log/osm.log.\n"
162           "          For the log to go to standard output use -f stdout.\n\n");
163   printf( "-v\n"
164           "--verbose\n"
165           "          This option increases the log verbosity level.\n"
166           "          The -v option may be specified multiple times\n"
167           "          to further increase the verbosity level.\n"
168           "          See the -vf option for more information about.\n"
169           "          log verbosity.\n\n" );
170   printf( "-V\n"
171           "          This option sets the maximum verbosity level and\n"
172           "          forces log flushing.\n"
173           "          The -V is equivalent to '-vf 0xFF -d 2'.\n"
174           "          See the -vf option for more information about.\n"
175           "          log verbosity.\n\n" );
176   printf( "-D <flags>\n"
177           "          This option sets the log verbosity level.\n"
178           "          A flags field must follow the -D option.\n"
179           "          A bit set/clear in the flags enables/disables a\n"
180           "          specific log level as follows:\n"
181           "          BIT    LOG LEVEL ENABLED\n"
182           "          ----   -----------------\n"
183           "          0x01 - ERROR (error messages)\n"
184           "          0x02 - INFO (basic messages, low volume)\n"
185           "          0x04 - VERBOSE (interesting stuff, moderate volume)\n"
186           "          0x08 - DEBUG (diagnostic, high volume)\n"
187           "          0x10 - FUNCS (function entry/exit, very high volume)\n"
188           "          0x20 - FRAMES (dumps all SMP and GMP frames)\n"
189           "          0x40 - ROUTING (dump FDB routing information)\n"
190           "          0x80 - currently unused.\n"
191           "          Without -D, OpenSM defaults to ERROR + INFO (0x3).\n"
192           "          Specifying -D 0 disables all messages.\n"
193           "          Specifying -D 0xFF enables all messages (see -V).\n"
194           "          High verbosity levels may require increasing\n"
195           "          the transaction timeout with the -t option.\n\n" );
196   printf( "-d <number>\n"
197           "--debug <number>\n"
198           "          This option specifies a debug option.\n"
199           "          These options are not normally needed.\n"
200           "          The number following -d selects the debug\n"
201           "          option to enable as follows:\n"
202           "          OPT   Description\n"
203           "          ---    -----------------\n"
204           "          -d0  - Ignore other SM nodes.\n"
205           "          -d1  - Force single threaded dispatching.\n"
206           "          -d2  - Force log flushing after each log message.\n"
207           "          -d3  - Disable multicast support.\n"
208           "          -d4  - Put OpenSM in memory tracking mode.\n"
209           "          -d10.. Put OpenSM in testability mode.\n"
210           "          Without -d, no debug options are enabled.\n\n" );
211   printf( "-h\n"
212           "--help\n"
213           "          Display this usage info then exit.\n\n" );
214   printf( "-?\n"
215           "          Display this usage info then exit.\n\n" );
216   fflush( stdout );
217   osm_exit_flag = 1;
218 }
219
220 /**********************************************************************
221  **********************************************************************/
222 void show_menu(void);
223
224 void
225 show_menu(void)
226 {
227   printf("\n------- Interactive Menu -------\n");
228   printf("X - Exit.\n\n");
229 }
230
231 /**********************************************************************
232  **********************************************************************/
233 ib_net64_t
234 get_port_guid(
235   IN osm_opensm_t *p_osm, uint64_t port_guid )
236 {
237   uint32_t i;
238   uint32_t choice = 0;
239   char junk[128];
240   boolean_t done_flag = FALSE;
241   ib_api_status_t status;
242   uint32_t num_ports = GUID_ARRAY_SIZE;
243   ib_port_attr_t attr_array[GUID_ARRAY_SIZE];
244   
245   /*
246     Call the transport layer for a list of local port
247     GUID values.
248   */
249   status = osm_vendor_get_all_port_attr( p_osm->p_vendor, attr_array, &num_ports );
250   if( status != IB_SUCCESS )
251   {
252     printf( "\nError from osm_opensm_init (%x)\n", status);
253     return( 0 );
254   }
255
256   /* if num_ports is 0 - return 0 */
257   if( num_ports == 0 )
258   {
259     printf( "\nNo local ports detected!\n" );
260     return( 0 );
261   }
262   /* If num_ports is 1, then there is only one possible port to use. Use it. */
263   if ( num_ports == 1 )
264   {
265     printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
266     return( attr_array[0].port_guid );
267   }
268
269 #if defined ( OSM_VENDOR_INTF_OPENIB )
270   /* If port_guid is 0, and this is gen2 - use the default port whose info is in attr_array[0] */
271   if ( port_guid == 0 )
272   {
273     printf("Using default guid 0x%" PRIx64 "\n", cl_hton64(attr_array[0].port_guid));
274     return( attr_array[0].port_guid );
275   }
276 #endif /* OSM_VENDOR_INTF_OPENIB */
277
278   /* More than one possible port - list all ports and let the user to choose. */
279   while( done_flag == FALSE )
280   {
281     printf( "\nChoose a local port number with which to bind:\n\n" );
282     /* If this is gen2 code - then port 0 has details of the default port used. 
283        no need to print it.
284        If this is not gen2 code - need to print details of all ports. */
285 #if defined ( OSM_VENDOR_INTF_OPENIB )
286     for( i = 1; i < num_ports; i++ )
287     {
288       printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
289              i, cl_ntoh64( attr_array[i].port_guid ),
290              attr_array[i].lid,
291              ib_get_port_state_str( attr_array[i].link_state ) );
292     }
293     printf( "\nEnter choice (1-%u): ", i-1 );
294 # else
295     for( i = 0; i < num_ports; i++ )
296     {
297       /*
298         Print the index + 1 since by convention, port numbers
299         start with 1 on host channel adapters.
300       */
301
302       printf("\t%u: GUID = 0x%8" PRIx64 ", lid = 0x%04X, state = %s\n",
303              i+1, cl_ntoh64( attr_array[i].port_guid ),
304              attr_array[i].lid,
305              ib_get_port_state_str( attr_array[i].link_state ) );
306     }
307     printf( "\nEnter choice (1-%u): ", i );
308 #endif /* OSM_VENDOR_INTF_OPENIB */
309
310     fflush( stdout );
311     if (scanf( "%u", &choice ))
312     {
313       /* If gen2 code - choice can be between 1 to num_ports-1
314          if not gen2 code - choice can be between 1 to num_ports */
315 #if defined ( OSM_VENDOR_INTF_OPENIB )
316       if( choice >= num_ports )
317 # else
318       if( choice > num_ports || choice < 1 )
319 #endif /* OSM_VENDOR_INTF_OPENIB */
320       {
321         printf("\nError: Lame choice!\n");
322         fflush( stdin );
323       }
324       else
325       {
326         done_flag = TRUE;
327       }
328     }
329     else
330     {
331       /* get rid of the junk in the selection line */
332       scanf( "%s", junk );
333       printf("\nError: Lame choice!\n"); 
334       fflush( stdin );
335     }
336   }
337 #if defined ( OSM_VENDOR_INTF_OPENIB )
338   printf("Choice guid=0x%8" PRIx64 "\n", cl_ntoh64( attr_array[choice].port_guid ));       
339   return( attr_array[choice].port_guid );
340 # else
341   return( attr_array[choice - 1].port_guid );
342 #endif /* OSM_VENDOR_INTF_OPENIB */
343 }
344
345 /**********************************************************************
346  **********************************************************************/
347 #define OSM_MAX_IGNORE_GUID_LINES_LEN 128
348 int
349 parse_ignore_guids_file(IN char *guids_file_name,
350                         IN osm_opensm_t *p_osm)
351 {
352   FILE *fh;
353   char line[OSM_MAX_IGNORE_GUID_LINES_LEN];
354   char *p_c, *p_ec;
355   uint32_t line_num = 0;
356   uint64_t port_guid;
357   ib_api_status_t status = IB_SUCCESS;
358   unsigned int  port_num;
359   OSM_LOG_ENTER( &p_osm->log, parse_ignore_guids_file );
360
361   fh = fopen( guids_file_name, "r" );
362   if( fh == NULL )
363   {
364     osm_log( &p_osm->log, OSM_LOG_ERROR,
365              "parse_ignore_guids_file: ERR 0601: "
366              "Unable to open ignore guids file (%s).\n" );
367     status = IB_ERROR;
368     goto Exit;
369   }
370
371   /*
372    * Parse the file and add to the ignore guids map.
373    */
374   while( fgets( line, OSM_MAX_IGNORE_GUID_LINES_LEN, fh ) != NULL )
375   {
376     line_num++;
377     p_c = line;
378     while ( (*p_c == ' ') && (*p_c != '\0')) p_c++ ;
379     port_guid = cl_hton64( strtoull( p_c, &p_ec, 16 ) );
380     if (p_ec == p_c)
381     {
382       osm_log( &p_osm->log, OSM_LOG_ERROR,
383                "parse_ignore_guids_file: ERR 0602: "
384                "Error in line (%u): %s" ,
385                line_num, line
386                );
387       status = IB_ERROR;
388       goto Exit;
389     }
390
391     while ( (*p_ec == ' ') && (*p_ec != '\0')) p_ec++ ;
392     if (! sscanf(p_ec, "%d", &port_num))
393     {
394       osm_log( &p_osm->log, OSM_LOG_ERROR,
395                "parse_ignore_guids_file: ERR 0603: "
396                "Error in line (%u): %s" ,
397                line_num, p_ec
398                );
399       status = IB_ERROR;
400       goto Exit;
401     }
402     /* Make sure the port_num isn't greater than 256 */
403     if (port_num > 256)
404     {
405       osm_log( &p_osm->log, OSM_LOG_ERROR,
406                "parse_ignore_guids_file: ERR XXX: "
407                "Error in line (%u): %s. "
408                "port number is greater than 256 (%d) \n",
409                line_num, p_ec, port_num
410                );
411       status = IB_ERROR;
412       goto Exit;
413     }
414     /* ok insert it */
415     osm_port_pro_set_ignored_port(&p_osm->subn, port_guid, (uint8_t)port_num);
416     osm_log( &p_osm->log, OSM_LOG_DEBUG,
417              "parse_ignore_guids_file: "
418              "Inserted Port: 0x%" PRIx64 " into ignored guids list\n" ,
419              port_guid
420              );
421
422   }
423
424   fclose( fh );
425
426  Exit:
427   OSM_LOG_EXIT( &p_osm->log );
428   return ( status );
429
430 }
431
432 /**********************************************************************
433  **********************************************************************/
434 int __cdecl
435 main(
436   int                   argc,
437   char*                 argv[] )
438 {
439   osm_subn_opt_t        opt;
440   ib_net64_t            guid = 0;
441   ib_api_status_t       status;
442   uint32_t              log_flags = OSM_LOG_DEFAULT_LEVEL;
443   int long              temp;
444   uint32_t              dbg_lvl;
445   boolean_t             run_once_flag = FALSE;
446   boolean_t             mem_track = FALSE;
447   uint32_t              next_option;
448   uint32_t                  exitTimeout;
449   boolean_t             cache_options = FALSE;
450   char                 *ignore_guids_file_name = NULL;
451   uint32_t              val;
452   const char * const    short_option = "i:f:d:g:l:s:t:vVhorc";
453
454   /*
455     In the array below, the 2nd parameter specified the number
456     of arguments as follows:
457     0: no arguments
458     1: argument
459     2: optional
460   */
461   const struct option long_option[] =
462     {
463       {  "debug",         1, NULL, 'd'},
464       {  "guid",          1, NULL, 'g'},
465       {  "ignore_guids",  1, NULL, 'i'},
466       {  "lmc",           1, NULL, 'l'},
467       {  "sweep",         1, NULL, 's'},
468       {  "timeout",       1, NULL, 't'},
469       {  "verbose",       0, NULL, 'v'},
470       {  "D",             1, NULL, 'D'},
471       {  "log_file",      1, NULL, 'f'},
472       {  "maxsmps",       1, NULL, 'n'},
473       {  "V",             0, NULL, 'V'},
474       {  "help",          0, NULL, 'h'},
475       {  "once",          0, NULL, 'o'},
476       {  "reassign_lids", 0, NULL, 'r'},
477       {  "priority",      1, NULL, 'p'},
478       {  "updn",          0, NULL, 'u'},
479       {  "add_guid_file", 1, NULL, 'a'},
480       {  "cache-options", 0, NULL, 'c'},
481       {  NULL,            0, NULL,  0 }  /* Required at the end of the array */
482     };
483
484   printf("-------------------------------------------------\n");
485   printf("%s\n", OSM_VERSION);
486
487   osm_subn_set_default_opt(&opt);
488   osm_subn_parse_conf_file(&opt);
489
490   printf("Command Line Arguments:\n");
491   do
492   {
493     next_option = getopt_long_only(argc, argv, short_option,
494                                    long_option, NULL);
495     switch(next_option)
496     {
497     case 'o':
498       /*
499         Run once option.
500       */
501       run_once_flag = TRUE;
502       printf(" Run Once\n");
503       break;
504
505     case 'r':
506       /*
507         Reassign LIDs subnet option.
508       */
509       opt.reassign_lids = TRUE;
510       printf(" Reassign LIDs\n");
511       break;
512
513     case 'i':
514       /*
515         Specifies ignore guids file.
516       */
517       ignore_guids_file_name = optarg;
518       printf(" Ignore Guids File = %s\n", ignore_guids_file_name);
519       break;
520
521     case 'g':
522       /*
523         Specifies port guid with which to bind.
524       */
525       guid = cl_hton64( strtoull( optarg, NULL, 16 ));
526       if (! guid)
527       {
528         /* If guid is 0 - need to display the guid list */
529         guid = INVALID_GUID;
530       }
531       else
532         printf(" Guid <0x%"PRIx64">\n", cl_hton64( guid ));
533       break;
534
535     case 's':
536       val = strtol(optarg, NULL, 0);
537       /* Check that the number is not too large */
538       if ( ((uint32_t)(val * 1000000)) / 1000000 != val )
539         fprintf(stderr, "ERROR: sweep interval given is too large. Ignoring it.\n");
540       else
541       {
542         opt.sweep_interval = val;
543         printf(" sweep interval = %d\n", opt.sweep_interval);
544       }
545       break;
546
547     case 't':
548       opt.transaction_timeout = strtol(optarg, NULL, 0);
549       printf(" Transaction timeout = %d\n", opt.transaction_timeout);
550
551       break;
552
553     case 'n':
554       opt.max_wire_smps = strtol(optarg, NULL, 0);
555       if( opt.max_wire_smps <= 0 )
556         opt.max_wire_smps = 0x7FFFFFFF;
557       printf(" Max wire smp's = %d\n", opt.max_wire_smps);
558       break;
559
560     case 'd':
561       dbg_lvl = strtol(optarg, NULL, 0);
562       printf(" d level = 0x%x\n", dbg_lvl);
563       if (dbg_lvl == 0)
564       {
565         printf(" Debug mode: Ignore Other SMs\n");
566         opt.ignore_other_sm = TRUE;
567       }
568       else if(dbg_lvl == 1)
569       {
570         printf(" Debug mode: Force Signale Thread\n");
571         opt.single_thread = TRUE;
572       }
573       else if(dbg_lvl == 2)
574       {
575         printf(" Debug mode: Force Log Flush\n");
576         opt.force_log_flush = TRUE;
577       }
578       else if(dbg_lvl == 3)
579       {
580         printf(" Debug mode: Disable multicast support\n");
581         opt.disable_multicast = TRUE;
582       }
583       else if(dbg_lvl == 4)
584       {
585         mem_track = TRUE;
586       }
587       else if(dbg_lvl >= 10)
588       {
589         /* Please look at subnet.h for list of testability modes. */
590         opt.testability_mode = dbg_lvl - 9;
591       }
592       else
593         printf(   " OpenSM: Unknown debug option %d ignored\n",
594                   dbg_lvl );
595       break;
596
597     case 'l':
598       temp = strtol(optarg, NULL, 0);
599       if( temp > 7 )
600       {
601         fprintf(stderr, "ERROR: LMC must be 7 or less.");
602         return( -1 );
603       }
604       opt.lmc = (uint8_t)temp;
605       printf(" LMC = %d\n", temp);
606       break;
607
608     case 'D':
609       log_flags = strtol(optarg, NULL, 0);
610       printf(" verbose option -D = 0x%x\n", log_flags);
611       break;
612
613     case 'f':
614       if (!strcmp(optarg, "stdout"))
615         /* output should be to standard output */
616         opt.log_file = NULL;
617       else
618         opt.log_file = optarg;
619       break;
620
621     case 'v':
622       log_flags = (log_flags <<1 )|1;
623       printf(" Verbose option -v (log flags = 0x%X)\n", log_flags );
624       break;
625
626     case 'V':
627       log_flags = 0xFFFFFFFF;
628       opt.force_log_flush = TRUE;
629       printf(" Big V selected\n");
630       break;
631
632     case 'p':
633       temp = strtol(optarg, NULL, 0);
634       if (0 > temp || 15 < temp) {
635         fprintf(stderr, "ERROR: priority must be between 0 and 15\n");
636         return (-1);
637       }
638       opt.sm_priority = (uint8_t)temp;
639       printf(" Priority = %d\n", temp);
640       break;
641
642     case 'u':
643       opt.updn_activate = TRUE;
644       printf(" Activate UPDN algorithm\n");
645       break;
646
647     case 'a':
648       /*
649         Specifies port guids file
650       */
651       opt.updn_guid_file = optarg;
652       printf (" UPDN Guid File: %s\n", opt.updn_guid_file );
653       break;
654
655     case 'c':
656       cache_options = TRUE;
657       printf (" Caching command line options\n");
658       break;
659
660     case 'h':
661     case '?':
662     case ':':
663       show_usage();
664       break;
665
666     case -1:
667       break; /* done with option */
668     default: /* something wrong */
669       abort();
670     }
671   }
672   while(next_option != -1);
673
674   if (osm_exit_flag) {
675     return( 0 );
676   }
677   if (opt.log_file != NULL )
678     printf(" Log File: %s\n", opt.log_file );
679   /* Done with options description */
680   printf("-------------------------------------------------\n");
681
682   if (mem_track) __cl_mem_track(TRUE);
683
684   opt.log_flags = (uint8_t)log_flags;
685
686   if ( cache_options == TRUE )
687     osm_subn_write_conf_file( &opt );
688
689   status = osm_opensm_init( &osm, &opt );
690   if( status != IB_SUCCESS )
691   {
692     const char *err_str = ib_get_err_str( status );
693     if (err_str == NULL)
694     {
695       err_str = "Unknown Error Type";
696     }
697     printf( "\nError from osm_opensm_init: %s.\n",
698             err_str);
699     /* We will just exit, and not go to Exit, since we don't
700        want the destroy to be called. */
701     return( status );
702   }
703
704   /*
705     If the user didn't specify a GUID on the command line,
706     then get a port GUID value with which to bind.
707   */
708   if( guid == 0 || cl_hton64(guid) == cl_hton64(INVALID_GUID))
709     guid = get_port_guid( &osm, guid );
710
711   if ( guid == 0 )
712   {
713     printf( "Error: Could not get port guid \n" );
714     status = IB_ERROR;
715     goto Exit;
716   }
717
718   status = osm_opensm_bind( &osm, guid );
719   if( status != IB_SUCCESS )
720   {
721     printf( "\nError from osm_opensm_bind (0x%X)\n", status );
722     goto Exit;
723   }
724
725   /*
726    * Define some port guids to ignore during path equalization
727    */
728   if (ignore_guids_file_name != NULL)
729   {
730     status = parse_ignore_guids_file(ignore_guids_file_name, &osm);
731     if( status != IB_SUCCESS )
732     {
733       printf( "\nError from parse_ignore_guids_file (0x%X)\n", status );
734       goto Exit;
735     }
736   }
737
738   osm_opensm_sweep( &osm );
739   /* since osm_opensm_init get opt as RO we'll set the opt value with UI pfn here */
740   /* Now do the registration */
741   if (opt.updn_activate)
742     if (osm_updn_reg_calc_min_hop_table(osm.p_updn_ucast_routing, &(osm.subn.opt))) {
743       status = IB_ERROR;
744       goto Exit;
745     }
746
747   if( run_once_flag == TRUE )
748   {
749     status = osm_opensm_wait_for_subnet_up(
750       &osm, EVENT_NO_TIMEOUT, TRUE );
751     osm_exit_flag = 1;
752   }
753   else
754   {
755     /*
756       Sit here forever
757       In the future, some sort of console interactivity could
758       be implemented in this loop.
759     */
760     while( !osm_exit_flag )
761       cl_thread_suspend( 10000 );
762   }
763
764   /* wait for all transactions to end */
765   CL_ASSERT( ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0) < 0x100000000ULL ); 
766   exitTimeout = 
767      (uint32_t) ((opt.polling_retry_number + 1) * opt.transaction_timeout / 1000.0);
768
769   if (exitTimeout < 3) exitTimeout = 3;
770
771   /*
772     printf( "\n------- OpenSM Exiting (in %u seconds) -------\n",
773     exitTimeout);
774     sleep(exitTimeout); 
775   */
776
777   if ((osm.mad_pool.mads_out))
778     fprintf(stdout, 
779             "There are still %u mads out. Forcing the exit of the OpenSM application...\n",
780             osm.mad_pool.mads_out);
781
782  Exit:
783   osm_opensm_destroy( &osm );
784
785   if (mem_track) cl_mem_display();
786
787   exit( 0 );
788 }