1/* 2 * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved. 3 * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved. 4 * 5 * This software is available to you under a choice of one of two 6 * licenses. You may choose to be licensed under the terms of the GNU 7 * General Public License (GPL) Version 2, available from the file 8 * COPYING in the main directory of this source tree, or the 9 * OpenIB.org BSD license below: 10 * 11 * Redistribution and use in source and binary forms, with or 12 * without modification, are permitted provided that the following 13 * conditions are met: 14 * 15 * - Redistributions of source code must retain the above 16 * copyright notice, this list of conditions and the following 17 * disclaimer. 18 * 19 * - Redistributions in binary form must reproduce the above 20 * copyright notice, this list of conditions and the following 21 * disclaimer in the documentation and/or other materials 22 * provided with the distribution. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 * SOFTWARE. 32 * 33 */ 34 35/* 36 * Abstract: 37 * Command line interface for osmtest. 38 * 39 */ 40 41#include <stdio.h> 42#include <stdlib.h> 43#include <getopt.h> 44#include <complib/cl_debug.h> 45#include "osmtest.h" 46 47/******************************************************************** 48 D E F I N E G L O B A L V A R I A B L E S 49*********************************************************************/ 50 51/* 52 This is the global osmtest object. 53 One osmtest object is required per subnet. 54 Future versions could support multiple subents by 55 instantiating more than one osmtest object. 56*/ 57#define GUID_ARRAY_SIZE 64 58#define OSMT_DEFAULT_RETRY_COUNT 3 59#define OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC 1000 60#define OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC 10 61#define INVALID_GUID (0xFFFFFFFFFFFFFFFFULL) 62 63/********************************************************************** 64 **********************************************************************/ 65boolean_t osmt_is_debug(void) 66{ 67#if defined( _DEBUG_ ) 68 return TRUE; 69#else 70 return FALSE; 71#endif /* defined( _DEBUG_ ) */ 72} 73 74/********************************************************************** 75 **********************************************************************/ 76void show_usage(void); 77 78void show_usage() 79{ 80 printf 81 ("\n------- osmtest - Usage and options ----------------------\n"); 82 printf("Usage: osmtest [options]\n"); 83 printf("Options:\n"); 84 printf("-f <c|a|v|s|e|f|m|q|t>\n" 85 "--flow <c|a|v|s|e|f|m|q|t>\n" 86 " This option directs osmtest to run a specific flow:\n" 87 " FLOW DESCRIPTION\n" 88 " c = create an inventory file with all nodes, ports and paths\n" 89 " a = run all validation tests (expecting an input inventory)\n" 90 " v = only validate the given inventory file\n" 91 " s = run service registration, deregistration, and lease test\n" 92 " e = run event forwarding test\n" 93 " f = flood the SA with queries according to the stress mode\n" 94 " m = multicast flow\n" 95 " q = QoS info: dump VLArb and SLtoVL tables\n" 96 " t = run trap 64/65 flow (this flow requires running of external tool)\n" 97 " (default is all flows except QoS)\n\n"); 98 99 printf("-w <trap_wait_time>\n" 100 "--wait <trap_wait_time>\n" 101 " This option specifies the wait time for trap 64/65 in seconds\n" 102 " It is used only when running -f t - the trap 64/65 flow\n" 103 " (default to 10 sec)\n\n"); 104 printf("-d <number>\n" 105 "--debug <number>\n" 106 " This option specifies a debug option\n" 107 " These options are not normally needed\n" 108 " The number following -d selects the debug\n" 109 " option to enable as follows:\n" 110 " OPT Description\n" 111 " --- -----------------\n" 112 " -d0 - Unused.\n" 113 " -d1 - Do not scan/compare path records.\n" 114 " -d2 - Force log flushing after each log message.\n" 115 " Without -d, no debug options are enabled\n\n"); 116 printf("-m <LID in hex>\n" 117 "--max_lid <LID in hex>\n" 118 " This option specifies the maximal LID number to be searched\n" 119 " for during inventory file build (default to 100)\n\n"); 120 printf("-g <GUID in hex>\n" 121 "--guid <GUID in hex>\n" 122 " This option specifies the local port GUID value\n" 123 " with which osmtest should bind. osmtest may be\n" 124 " bound to 1 port at a time\n\n"); 125 printf("-p \n" 126 "--port\n" 127 " This option displays a menu of possible local port GUID values\n" 128 " with which osmtest could bind\n\n"); 129 printf("-h\n" 130 "--help\n" " Display this usage info then exit\n\n"); 131 printf("-i <filename>\n" 132 "--inventory <filename>\n" 133 " This option specifies the name of the inventory file\n" 134 " Normally, osmtest expects to find an inventory file,\n" 135 " which osmtest uses to validate real-time information\n" 136 " received from the SA during testing\n" 137 " If -i is not specified, osmtest defaults to the file\n" 138 " 'osmtest.dat'\n" 139 " See -c option for related information\n\n"); 140 printf("-s\n" 141 "--stress\n" 142 " This option runs the specified stress test instead\n" 143 " of the normal test suite\n" 144 " Stress test options are as follows:\n" 145 " OPT Description\n" 146 " --- -----------------\n" 147 " -s1 - Single-MAD response SA queries\n" 148 " -s2 - Multi-MAD (RMPP) response SA queries\n" 149 " -s3 - Multi-MAD (RMPP) Path Record SA queries\n" 150 " Without -s, stress testing is not performed\n\n"); 151 printf("-M\n" 152 "--Multicast_Mode\n" 153 " This option specify length of Multicast test:\n" 154 " OPT Description\n" 155 " --- -----------------\n" 156 " -M1 - Short Multicast Flow (default) - single mode\n" 157 " -M2 - Short Multicast Flow - multiple mode\n" 158 " -M3 - Long Multicast Flow - single mode\n" 159 " -M4 - Long Multicast Flow - multiple mode\n" 160 " Single mode - Osmtest is tested alone, with no other\n" 161 " apps that interact with OpenSM MC\n" 162 " Multiple mode - Could be run with other apps using MC with\n" 163 " OpenSM." 164 " Without -M, default flow testing is performed\n\n"); 165 166 printf("-t <milliseconds>\n" 167 " This option specifies the time in milliseconds\n" 168 " used for transaction timeouts\n" 169 " Specifying -t 0 disables timeouts\n" 170 " Without -t, osmtest defaults to a timeout value of\n" 171 " 1 second\n\n"); 172 printf("-l\n" 173 "--log_file\n" 174 " This option defines the log to be the given file\n" 175 " By default the log goes to stdout\n\n"); 176 printf("-v\n" 177 " This option increases the log verbosity level\n" 178 " The -v option may be specified multiple times\n" 179 " to further increase the verbosity level\n" 180 " See the -vf option for more information about.\n" 181 " log verbosity\n\n"); 182 printf("-V\n" 183 " This option sets the maximum verbosity level and\n" 184 " forces log flushing\n" 185 " The -V is equivalent to '-vf 0xFF -d 2'\n" 186 " See the -vf option for more information about.\n" 187 " log verbosity\n\n"); 188 printf("-vf <flags>\n" 189 " This option sets the log verbosity level\n" 190 " A flags field must follow the -vf option\n" 191 " A bit set/clear in the flags enables/disables a\n" 192 " specific log level as follows:\n" 193 " BIT LOG LEVEL ENABLED\n" 194 " ---- -----------------\n" 195 " 0x01 - ERROR (error messages)\n" 196 " 0x02 - INFO (basic messages, low volume)\n" 197 " 0x04 - VERBOSE (interesting stuff, moderate volume)\n" 198 " 0x08 - DEBUG (diagnostic, high volume)\n" 199 " 0x10 - FUNCS (function entry/exit, very high volume)\n" 200 " 0x20 - FRAMES (dumps all SMP and GMP frames)\n" 201 " 0x40 - currently unused\n" 202 " 0x80 - currently unused\n" 203 " Without -vf, osmtest defaults to ERROR + INFO (0x3)\n" 204 " Specifying -vf 0 disables all messages\n" 205 " Specifying -vf 0xFF enables all messages (see -V)\n" 206 " High verbosity levels may require increasing\n" 207 " the transaction timeout with the -t option\n\n"); 208} 209 210/********************************************************************** 211 **********************************************************************/ 212static void print_all_guids(IN osmtest_t * p_osmt); 213static void print_all_guids(IN osmtest_t * p_osmt) 214{ 215 ib_api_status_t status; 216 uint32_t num_ports = GUID_ARRAY_SIZE; 217 ib_port_attr_t attr_array[GUID_ARRAY_SIZE]; 218 int i; 219 220 /* 221 Call the transport layer for a list of local port 222 GUID values. 223 */ 224 status = 225 osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array, 226 &num_ports); 227 if (status != IB_SUCCESS) { 228 printf("\nError from osm_vendor_get_all_port_attr (%x)\n", 229 status); 230 return; 231 } 232 233 printf("\nListing GUIDs:\n"); 234 for (i = 0; i < num_ports; i++) 235 printf("Port %i: 0x%" PRIx64 "\n", i, 236 cl_hton64(attr_array[i].port_guid)); 237} 238 239/********************************************************************** 240 **********************************************************************/ 241ib_net64_t get_port_guid(IN osmtest_t * p_osmt, uint64_t port_guid) 242{ 243 ib_api_status_t status; 244 uint32_t num_ports = GUID_ARRAY_SIZE; 245 ib_port_attr_t attr_array[GUID_ARRAY_SIZE]; 246 int i; 247 248 /* 249 Call the transport layer for a list of local port 250 GUID values. 251 */ 252/* "local ports" is(?) phys, shouldn't this exclude port 0 then ? */ 253 status = 254 osm_vendor_get_all_port_attr(p_osmt->p_vendor, attr_array, 255 &num_ports); 256 if (status != IB_SUCCESS) { 257 printf("\nError from osm_vendor_get_all_port_attr (%x)\n", 258 status); 259 return (0); 260 } 261 262 if (num_ports == 1) { 263 printf("using default guid 0x%" PRIx64 "\n", 264 cl_hton64(attr_array[0].port_guid)); 265 return (attr_array[0].port_guid); 266 } 267 268 for (i = 0; i < num_ports; i++) { 269 if (attr_array[i].port_guid == port_guid || 270 (!port_guid && attr_array[i].link_state > IB_LINK_DOWN)) 271 return attr_array[i].port_guid; 272 } 273 274 return 0; 275} 276 277/********************************************************************** 278 **********************************************************************/ 279int main(int argc, char *argv[]) 280{ 281 static osmtest_t osm_test; 282 osmtest_opt_t opt = { 0 }; 283 ib_net64_t guid = 0; 284 uint16_t max_lid = 100; 285 ib_api_status_t status; 286 uint32_t log_flags = OSM_LOG_ERROR | OSM_LOG_INFO; 287 int32_t vendor_debug = 0; 288 char flow_name[64]; 289 uint32_t next_option; 290 const char *const short_option = "f:l:m:M:d:g:s:t:i:pcvVh"; 291 292 /* 293 * In the array below, the 2nd parameter specified the number 294 * of arguments as follows: 295 * 0: no arguments 296 * 1: argument 297 * 2: optional 298 */ 299 const struct option long_option[] = { 300 {"create", 0, NULL, 'c'}, 301 {"debug", 1, NULL, 'd'}, 302 {"flow", 1, NULL, 'f'}, 303 {"wait", 1, NULL, 'w'}, 304 {"inventory", 1, NULL, 'i'}, 305 {"max_lid", 1, NULL, 'm'}, 306 {"guid", 2, NULL, 'g'}, 307 {"port", 0, NULL, 'p'}, 308 {"help", 0, NULL, 'h'}, 309 {"stress", 1, NULL, 's'}, 310 {"Multicast_Mode", 1, NULL, 'M'}, 311 {"timeout", 1, NULL, 't'}, 312 {"verbose", 0, NULL, 'v'}, 313 {"log_file", 1, NULL, 'l'}, 314 {"vf", 1, NULL, 'x'}, 315 {"V", 0, NULL, 'V'}, 316 317 {NULL, 0, NULL, 0} /* Required at end of array */ 318 }; 319 320 /* Make sure that the opensm, complib and osmtest were compiled using 321 same modes (debug/free) */ 322 if (osm_is_debug() != cl_is_debug() || osm_is_debug() != osmt_is_debug() 323 || osmt_is_debug() != cl_is_debug()) { 324 fprintf(stderr, 325 "-E- OpenSM, Complib and OsmTest were compiled using different modes\n"); 326 fprintf(stderr, 327 "-E- OpenSM debug:%d Complib debug:%d OsmTest debug:%d \n", 328 osm_is_debug(), cl_is_debug(), osmt_is_debug()); 329 exit(1); 330 } 331 332 opt.transaction_timeout = OSMT_DEFAULT_TRANS_TIMEOUT_MILLISEC; 333 opt.wait_time = OSMT_DEFAULT_TRAP_WAIT_TIMEOUT_SEC; 334 opt.retry_count = OSMT_DEFAULT_RETRY_COUNT; 335 opt.force_log_flush = FALSE; 336 opt.stress = 0; 337 opt.log_file = NULL; 338 opt.create = FALSE; 339 opt.mmode = 1; 340 opt.ignore_path_records = FALSE; /* Do path Records too */ 341 opt.flow = OSMT_FLOW_ALL; /* run all validation tests */ 342 strcpy(flow_name, "All Validations"); 343 strcpy(opt.file_name, "osmtest.dat"); 344 345 printf("\nCommand Line Arguments\n"); 346 do { 347 next_option = getopt_long_only(argc, argv, short_option, 348 long_option, NULL); 349 switch (next_option) { 350 case 'c': 351 /* 352 * Create the inventory file. 353 */ 354 opt.create = TRUE; 355 printf("\tCreating inventory file\n"); 356 break; 357 358 case 'i': 359 /* 360 * Specifies inventory file name. 361 */ 362 if (strlen(optarg) > OSMTEST_FILE_PATH_MAX) 363 printf 364 ("\nError: path name too long (ignored)\n"); 365 else 366 strcpy(opt.file_name, optarg); 367 368 printf("\tFile = %s\n", opt.file_name); 369 break; 370 371 case 'f': 372 /* 373 * Specifies Flow . 374 */ 375 if (strlen(optarg) > OSMTEST_FILE_PATH_MAX) 376 printf 377 ("\nError: path name too long (ignored)\n"); 378 else 379 strcpy(flow_name, optarg); 380 381 if (!strcmp("c", optarg)) { 382 strcpy(flow_name, "Create Inventory"); 383 opt.flow = OSMT_FLOW_CREATE_INVENTORY; 384 } else if (!strcmp("v", optarg)) { 385 strcpy(flow_name, "Validate Inventory"); 386 opt.flow = OSMT_FLOW_VALIDATE_INVENTORY; 387 } else if (!strcmp("s", optarg)) { 388 strcpy(flow_name, "Services Registration"); 389 opt.flow = OSMT_FLOW_SERVICE_REGISTRATION; 390 } else if (!strcmp("e", optarg)) { 391 strcpy(flow_name, "Event Forwarding"); 392 opt.flow = OSMT_FLOW_EVENT_FORWARDING; 393 } else if (!strcmp("f", optarg)) { 394 strcpy(flow_name, "Stress SA"); 395 opt.flow = OSMT_FLOW_STRESS_SA; 396 } else if (!strcmp("m", optarg)) { 397 strcpy(flow_name, "Multicast"); 398 opt.flow = OSMT_FLOW_MULTICAST; 399 } else if (!strcmp("q", optarg)) { 400 strcpy(flow_name, "QoS: VLArb and SLtoVL"); 401 opt.flow = OSMT_FLOW_QOS; 402 } else if (!strcmp("t", optarg)) { 403 strcpy(flow_name, "Trap 64/65"); 404 opt.flow = OSMT_FLOW_TRAP; 405 } else if (!strcmp("a", optarg)) { 406 strcpy(flow_name, "All Validations"); 407 opt.flow = OSMT_FLOW_ALL; 408 } else { 409 printf("\nError: unknown flow %s\n", flow_name); 410 exit(2); 411 } 412 break; 413 414 case 'w': 415 /* 416 * Specifies trap 64/65 wait time 417 */ 418 CL_ASSERT(strtol(optarg, NULL, 0) < 0x100); 419 opt.wait_time = (uint8_t) strtol(optarg, NULL, 0); 420 printf("\tTrap 64/65 wait time = %d\n", opt.wait_time); 421 break; 422 423 case 'm': 424 /* 425 * Specifies the max LID to search for during exploration. 426 */ 427 max_lid = atoi(optarg); 428 printf("\tMAX-LID %u\n", max_lid); 429 break; 430 431 case 'g': 432 /* 433 * Specifies port guid with which to bind. 434 */ 435 guid = cl_hton64(strtoull(optarg, NULL, 16)); 436 printf(" Guid <0x%" PRIx64 ">\n", cl_hton64(guid)); 437 break; 438 439 case 'p': 440 /* 441 * Display current port guids 442 */ 443 guid = INVALID_GUID; 444 break; 445 446 case 't': 447 /* 448 * Specifies transaction timeout. 449 */ 450 opt.transaction_timeout = strtol(optarg, NULL, 0); 451 printf("\tTransaction timeout = %d\n", 452 opt.transaction_timeout); 453 break; 454 455 case 'l': 456 opt.log_file = optarg; 457 printf("\tLog File:%s\n", opt.log_file); 458 break; 459 460 case 'v': 461 /* 462 * Increases log verbosity. 463 */ 464 log_flags = (log_flags << 1) | 1; 465 printf("\tVerbose option -v (log flags = 0x%X)\n", 466 log_flags); 467 break; 468 469 case 'V': 470 /* 471 * Specifies maximum log verbosity. 472 */ 473 log_flags = 0xFFFFFFFF; 474 opt.force_log_flush = TRUE; 475 printf("\tEnabling maximum log verbosity\n"); 476 break; 477 478 case 's': 479 /* 480 * Perform stress test. 481 */ 482 opt.stress = strtol(optarg, NULL, 0); 483 printf("\tStress test enabled: "); 484 switch (opt.stress) { 485 case 1: 486 printf("Small SA queries\n"); 487 break; 488 case 2: 489 printf("Large SA queries\n"); 490 break; 491 case 3: 492 printf("Large Path Record SA queries\n"); 493 break; 494 default: 495 printf("Unknown value %u (ignored)\n", 496 opt.stress); 497 opt.stress = 0; 498 break; 499 } 500 break; 501 502 case 'M': 503 /* 504 * Perform multicast test. 505 */ 506 opt.mmode = strtol(optarg, NULL, 0); 507 printf("\tMulticast test enabled: "); 508 switch (opt.mmode) { 509 case 1: 510 printf 511 ("Short MC Flow - single mode (default)\n"); 512 break; 513 case 2: 514 printf("Short MC Flow - multiple mode\n"); 515 break; 516 case 3: 517 printf("Long MC Flow - single mode\n"); 518 break; 519 case 4: 520 printf("Long MC Flow - multiple mode\n"); 521 break; 522 default: 523 printf("Unknown value %u (ignored)\n", 524 opt.stress); 525 opt.mmode = 0; 526 break; 527 } 528 break; 529 530 case 'd': 531 /* 532 * Debug Options 533 */ 534 printf("\tDebug Option: "); 535 switch (strtol(optarg, NULL, 0)) { 536 case 1: 537 printf("Ignore Path Records\n"); 538 opt.ignore_path_records = TRUE; 539 break; 540 case 2: 541 printf("Force Log Flush\n"); 542 opt.force_log_flush = TRUE; 543 break; 544 case 3: 545 /* Used to be memory tracking */ 546 default: 547 printf("Unknown value %ld (ignored)\n", 548 strtol(optarg, NULL, 0)); 549 break; 550 } 551 break; 552 553 case 'h': 554 show_usage(); 555 return 0; 556 557 case 'x': 558 log_flags = strtol(optarg, NULL, 0); 559 printf 560 ("\t\t\t\tVerbose option -vf (log flags = 0x%X)\n", 561 log_flags); 562 break; 563 564 case -1: 565 printf("Done with args\n"); 566 break; 567 568 default: /* something wrong */ 569 abort(); 570 } 571 572 } 573 while (next_option != -1); 574 575 printf("\tFlow = %s\n", flow_name); 576 577 if (vendor_debug) 578 osm_vendor_set_debug(osm_test.p_vendor, vendor_debug); 579 580 complib_init(); 581 582 status = osmtest_init(&osm_test, &opt, (osm_log_level_t) log_flags); 583 if (status != IB_SUCCESS) { 584 printf("\nError from osmtest_init: %s\n", 585 ib_get_err_str(status)); 586 goto Exit; 587 } 588 if (cl_hton64(guid) == cl_hton64(INVALID_GUID)) { 589 print_all_guids(&osm_test); 590 complib_exit(); 591 return (status); 592 } 593 594 /* 595 If the user didn't specify a GUID on the command line, 596 then get a port GUID value with which to bind. 597 */ 598 if (guid == 0 && !(guid = get_port_guid(&osm_test, guid))) { 599 printf("\nError: port guid 0x%" PRIx64 " not found\n", guid); 600 goto Exit; 601 } 602 603 /* 604 * Guid may be zero going into this function if the user 605 * hasn't specified a binding port on the command line. 606 */ 607 status = osmtest_bind(&osm_test, max_lid, guid); 608 if (status != IB_SUCCESS) 609 exit(status); 610 611 status = osmtest_run(&osm_test); 612 if (status != IB_SUCCESS) { 613 printf("OSMTEST: TEST \"%s\" FAIL\n", flow_name); 614 } else { 615 printf("OSMTEST: TEST \"%s\" PASS\n", flow_name); 616 } 617 osmtest_destroy(&osm_test); 618 619 complib_exit(); 620 621Exit: 622 return (status); 623} 624