1 #include "netperf_version.h" 2 3 char netsh_id[]="\ 4 @(#)netsh.c (c) Copyright 1993-2012 Hewlett-Packard Company. Version 2.6.0"; 5 6 7 /****************************************************************/ 8 /* */ 9 /* Global include files */ 10 /* */ 11 /****************************************************************/ 12 13 #ifdef HAVE_CONFIG_H 14 #include "config.h" 15 #endif 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <ctype.h> 20 #include <sys/types.h> 21 #include <fcntl.h> 22 23 #ifndef WIN32 24 #include <unistd.h> 25 #include <errno.h> 26 #include <signal.h> 27 #include <sys/time.h> 28 #include <sys/socket.h> 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 #include <netdb.h> 32 #else 33 #include <time.h> 34 #include <winsock2.h> 35 #include "missing\stdint.h" 36 /* while it is unlikely that anyone running Windows 2000 or NT 4 is 37 going to be trying to compile this, if they are they will want to 38 define DONT_IPV6 in the sources file */ 39 #ifndef DONT_IPV6 40 #include <ws2tcpip.h> 41 #endif 42 #define netperf_socklen_t socklen_t 43 extern int getopt(int , char **, char *) ; 44 #endif 45 46 47 #ifndef STRINGS 48 #include <string.h> 49 #else /* STRINGS */ 50 #include <strings.h> 51 #endif /* STRINGS */ 52 53 /**********************************************************************/ 54 /* */ 55 /* Local Include Files */ 56 /* */ 57 /**********************************************************************/ 58 59 #define NETSH 60 #include "netsh.h" 61 #include "netlib.h" 62 #include "nettest_bsd.h" 63 64 #ifdef WANT_UNIX 65 #include "nettest_unix.h" 66 #endif /* WANT_UNIX */ 67 68 #ifdef WANT_XTI 69 #include "nettest_xti.h" 70 #endif /* WANT_XTI */ 71 72 #ifdef WANT_DLPI 73 #include "nettest_dlpi.h" 74 #endif /* WANT_DLPI */ 75 76 #ifdef WANT_SCTP 77 #include "nettest_sctp.h" 78 #endif 79 80 /************************************************************************/ 81 /* */ 82 /* Global constants and macros */ 83 /* */ 84 /************************************************************************/ 85 86 /* Some of the args take optional parameters. Since we are using 87 getopt to parse the command line, we will tell getopt that they do 88 not take parms, and then look for them ourselves */ 89 90 #define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdD:f:F:H:hi:I:jk:K:l:L:n:NO:o:P:p:rSs:t:T:v:VW:w:y:Y:Z:46" 91 92 /************************************************************************/ 93 /* */ 94 /* Global variables */ 95 /* */ 96 /************************************************************************/ 97 98 /* some names and such */ 99 char *program; /* program invocation name */ 100 char *command_line; /* a copy of the entire command line */ 101 102 /* stuff to say where this test is going */ 103 char 104 host_name[HOSTNAMESIZE] = "", /* remote host name or ip addr */ 105 local_host_name[HOSTNAMESIZE] = "", /* local hostname or ip */ 106 test_name[BUFSIZ] = "TCP_STREAM", /* which test to run */ 107 test_port[PORTBUFSIZE] = "12865", /* where is the test waiting */ 108 local_test_port[PORTBUFSIZE] = "0"; /* from whence we should start */ 109 110 int 111 address_family = AF_UNSPEC, /* which address family remote */ 112 local_address_family = AF_UNSPEC; /* which address family local */ 113 114 /* the source of data for filling the buffers */ 115 char local_fill_file[BUFSIZ] = ""; 116 char remote_fill_file[32] = ""; /* size limited for control message */ 117 118 /* output controlling variables */ 119 int 120 debug = 0, /* debugging level */ 121 print_headers = 1, /* do/don't display headers */ 122 verbosity = 1, /* verbosity level */ 123 keep_histogram = 0, 124 keep_statistics = 0; 125 126 /* When specified with -B, this will be displayed at the end of the line 127 for output that does not include the test header. mostly this is 128 to help identify a specific netperf result when concurrent netperfs 129 are run. raj 2006-02-01 */ 130 char *result_brand = NULL; 131 132 /* cpu variables */ 133 int 134 local_cpu_usage = 0, /* you guessed it */ 135 remote_cpu_usage = 0; /* still right ! */ 136 137 float 138 local_cpu_rate = 0.0F, 139 remote_cpu_rate = 0.0F; 140 141 int 142 shell_num_cpus=1; 143 144 /* the end-test conditions for the tests - either transactions, bytes, 145 or time. different vars used for clarity - space is cheap ;-) */ 146 147 int 148 test_time = 10, /* test ends by time */ 149 test_len_ticks, /* how many times will the timer go off before the 150 test is over? */ 151 test_bytes = 0, /* test ends on byte count */ 152 test_trans = 0; /* test ends on tran count */ 153 154 /* the alignment conditions for the tests */ 155 int 156 local_recv_align = 8, /* alignment for local receives */ 157 local_send_align = 8, /* alignment for local sends */ 158 local_send_offset = 0, 159 local_recv_offset = 0, 160 remote_recv_align = 8, /* alignment for remote receives */ 161 remote_send_align = 8, /* alignment for remote sends */ 162 remote_send_offset = 0, 163 remote_recv_offset = 0, 164 remote_send_width = 0, 165 remote_recv_width = 0; 166 167 /* hoist above the if for omni */ 168 int 169 interval_usecs = 0, 170 interval_wate = 0, 171 interval_burst = 0, 172 remote_interval_usecs = 0, 173 remote_interval_burst = 0; 174 175 /* wait time between control/data connection establishment and start 176 of data traffic */ 177 int wait_time_secs = 0; 178 179 180 #ifdef DIRTY 181 int loc_dirty_count = 0, 182 loc_clean_count = 0, 183 rem_dirty_count = 0, 184 rem_clean_count = 0; 185 #else 186 int loc_dirty_count = -1, 187 loc_clean_count = -1, 188 rem_dirty_count = -1, 189 rem_clean_count = -1; 190 #endif /* DIRTY */ 191 192 /* some of the vairables for confidence intervals... */ 193 194 int confidence_level = 0; 195 int iteration_min = 1; 196 int iteration_max = 1; 197 int result_confidence_only = 0; 198 double interval = 0.0; 199 200 /* stuff to control the "width" of the buffer rings for sending and 201 receiving data */ 202 int send_width; 203 int recv_width; 204 205 /* address family */ 206 int af = AF_INET; 207 208 /* socket priority via SO_PRIORITY */ 209 int local_socket_prio = -1; 210 int remote_socket_prio = -1; 211 212 /* and IP_TOS */ 213 int local_socket_tos = -1; 214 int remote_socket_tos = -1; 215 216 /* did someone request processor affinity? */ 217 int cpu_binding_requested = 0; 218 219 /* are we not establishing a control connection? */ 220 int no_control = 0; 221 222 /* what is the passphrase? */ 223 char *passphrase = NULL; 224 225 char netserver_usage[] = "\n\ 226 Usage: netserver [options] \n\ 227 \n\ 228 Options:\n\ 229 -h Display this text\n\ 230 -D Do not daemonize\n\ 231 -d Increase debugging output\n\ 232 -f Do not spawn chilren for each test, run serially\n\ 233 -L name,family Use name to pick listen address and family for family\n\ 234 -N No debugging output, even if netperf asks\n\ 235 -p portnum Listen for connect requests on portnum.\n\ 236 -4 Do IPv4\n\ 237 -6 Do IPv6\n\ 238 -v verbosity Specify the verbosity level\n\ 239 -V Display version information and exit\n\ 240 -Z passphrase Expect passphrase as the first thing received\n\ 241 \n"; 242 243 /* netperf_usage done as two concatenated strings to make the MS 244 compiler happy when compiling for x86_32. fix from Spencer 245 Frink. */ 246 247 char netperf_usage1[] = "\n\ 248 Usage: netperf [global options] -- [test options] \n\ 249 \n\ 250 Global options:\n\ 251 -a send,recv Set the local send,recv buffer alignment\n\ 252 -A send,recv Set the remote send,recv buffer alignment\n\ 253 -B brandstr Specify a string to be emitted with brief output\n\ 254 -c [cpu_rate] Report local CPU usage\n\ 255 -C [cpu_rate] Report remote CPU usage\n\ 256 -d Increase debugging output\n\ 257 -D time,[units] * Display interim results at least every time interval\n\ 258 using units as the initial guess for units per second\n\ 259 A negative value for time will make heavy use of the\n\ 260 system's timestamping functionality\n\ 261 -f G|M|K|g|m|k Set the output units\n\ 262 -F lfill[,rfill]* Pre-fill buffers with data from specified file\n\ 263 -h Display this text\n\ 264 -H name|ip,fam * Specify the target machine and/or local ip and family\n\ 265 -i max,min Specify the max and min number of iterations (15,1)\n\ 266 -I lvl[,intvl] Specify confidence level (95 or 99) (99) \n\ 267 and confidence interval in percentage (10)\n\ 268 -j Keep additional timing statistics\n\ 269 -l testlen Specify test duration (>0 secs) (<0 bytes|trans)\n\ 270 -L name|ip,fam * Specify the local ip|name and address family\n\ 271 -o send,recv Set the local send,recv buffer offsets\n\ 272 -O send,recv Set the remote send,recv buffer offset\n\ 273 -n numcpu Set the number of processors for CPU util\n\ 274 -N Establish no control connection, do 'send' side only\n\ 275 -p port,lport* Specify netserver port number and/or local port\n\ 276 -P 0|1 Don't/Do display test headers\n\ 277 -r Allow confidence to be hit on result only\n\ 278 -s seconds Wait seconds between test setup and test start\n\ 279 -S Set SO_KEEPALIVE on the data connection\n\ 280 -t testname Specify test to perform\n\ 281 -T lcpu,rcpu Request netperf/netserver be bound to local/remote cpu\n\ 282 -v verbosity Specify the verbosity level\n\ 283 -W send,recv Set the number of send,recv buffers\n\ 284 -v level Set the verbosity level (default 1, min 0)\n\ 285 -V Display the netperf version and exit\n\ 286 -y local,remote Set the socket priority\n\ 287 -Y local,remote Set the IP_TOS. Use hexadecimal.\n\ 288 -Z passphrase Set and pass to netserver a passphrase\n"; 289 290 char netperf_usage2[] = "\n\ 291 For those options taking two parms, at least one must be specified;\n\ 292 specifying one value without a comma will set both parms to that\n\ 293 value, specifying a value with a leading comma will set just the second\n\ 294 parm, a value with a trailing comma will set just the first. To set\n\ 295 each parm to unique values, specify both and separate them with a\n\ 296 comma.\n\ 297 \n" 298 "* For these options taking two parms, specifying one value with no comma\n\ 299 will only set the first parms and will leave the second at the default\n\ 300 value. To set the second value it must be preceded with a comma or be a\n\ 301 comma-separated pair. This is to retain previous netperf behaviour.\n"; 302 303 304 /* This routine will return the two arguments to the calling routine. 306 If the second argument is not specified, and there is no comma, 307 then the value of the second argument will be the same as the value 308 of the first. If there is a comma, then the value of the second 309 argument will be the value of the second argument ;-) */ 310 void 311 break_args(char *s, char *arg1, char *arg2) 312 313 { 314 char *ns; 315 ns = strchr(s,','); 316 if (ns) { 317 /* there was a comma arg2 should be the second arg*/ 318 *ns++ = '\0'; 319 while ((*arg2++ = *ns++) != '\0'); 320 } 321 else { 322 /* there was not a comma, we can use ns as a temp s */ 323 /* and arg2 should be the same value as arg1 */ 324 ns = s; 325 while ((*arg2++ = *ns++) != '\0'); 326 }; 327 while ((*arg1++ = *s++) != '\0'); 328 } 329 330 /* break_args_explicit_sep 331 332 this routine is somewhat like break_args in that it will separate a 333 pair of values using the given separator. however, if there is no 334 separator this version will not ass-u-me that arg2 should be the 335 same as arg1. raj 20101129 */ 336 337 void 338 break_args_explicit_sep(char *s, int sep, char *arg1, char *arg2) 339 340 { 341 char *ns; 342 ns = strchr(s,sep); 343 if (ns) { 344 /* there was a separator arg2 should be the second arg*/ 345 *ns++ = '\0'; 346 while ((*arg2++ = *ns++) != '\0'); 347 } 348 else { 349 /* there was no separator, so we should make sure that arg2 is \0 350 lest something become confused. raj 2005-02-04 */ 351 *arg2 = '\0'; 352 }; 353 while ((*arg1++ = *s++) != '\0'); 354 355 } 356 357 /* break_args_explicit - now just a wrapper around a call to 358 break_args_explicit_sep passing-in a ',' as the separator. raj 359 20101129 */ 360 361 void 362 break_args_explicit(char *s, char *arg1, char *arg2) 363 364 { 365 break_args_explicit_sep(s, ',', arg1, arg2); 366 } 367 368 369 /* given a string with possible values for setting an address family, 370 convert that into one of the AF_mumble values - AF_INET, AF_INET6, 371 AF_UNSPEC as apropriate. the family_string is compared in a 372 case-insensitive manner */ 373 374 int 375 parse_address_family(char family_string[]) 376 { 377 378 char temp[10]; /* gotta love magic constants :) */ 379 380 strncpy(temp,family_string,10); 381 382 if (debug) { 383 fprintf(where, 384 "Attempting to parse address family from %s derived from %s\n", 385 temp, 386 family_string); 387 } 388 #if defined(AF_INET6) 389 if (strstr(temp,"6")) { 390 return(AF_INET6); 391 } 392 #endif 393 if (strstr(temp,"inet") || 394 strstr(temp,"4")) { 395 return(AF_INET); 396 } 397 #if defined(AF_RDS) 398 if (strstr(temp,"af_rds") || 399 strstr(temp,"32")) { 400 return(AF_RDS); 401 } 402 #endif 403 if (strstr(temp,"unspec") || 404 strstr(temp,"0")) { 405 return(AF_UNSPEC); 406 } 407 fprintf(where, 408 "WARNING! %s not recognized as an address family, using AF_UNPSEC\n" 409 "Are you sure netperf was configured for that address family?\n", 410 family_string); 411 fflush(where); 412 return(AF_UNSPEC); 413 } 414 415 int 416 parse_socket_type(char socket_string[]) { 417 418 char temp[10]; 419 420 strncpy(temp,socket_string,10); 421 422 if (debug) { 423 fprintf(where, 424 "Attempting to parse socket type from %s derived from %s\n", 425 temp, 426 socket_string); 427 } 428 429 #ifdef SOCK_STREAM 430 if (strstr(temp,"stream")) 431 return SOCK_STREAM; 432 #endif 433 #ifdef SOCK_DGRAM 434 if (strstr(temp,"dgram")) 435 return SOCK_DGRAM; 436 #endif 437 return NST_UNKN; 438 439 } 440 441 int 442 parse_direction(char direction_string[]) 443 { 444 char arg1[BUFSIZ],arg2[BUFSIZ]; 445 int left, right; 446 447 if (NULL == direction_string) { 448 return 0; 449 } 450 451 if (direction_string[0] == '\0') { 452 return 0; 453 } 454 455 /* allow someone to "or" break_args_explicit will split at the first 456 '|' in the string so we know that arg1 has no '|' in it and arg2 457 might */ 458 break_args_explicit_sep(direction_string,'|',arg1,arg2); 459 460 /* at this point only arg2 could contain a '|' so recurse on that */ 461 right = parse_direction(arg2); 462 463 /* now we parse the "left side" or arg1 */ 464 if (arg1[0] == '\0') { 465 left = 0; 466 } 467 else if ((strcasecmp(arg1,"xmit") == 0) || 468 (strcasecmp(arg1,"send") == 0) || 469 (strcasecmp(arg1,"stream") == 0) || 470 (strcasecmp(arg1,"transmit") == 0)) { 471 left = NETPERF_XMIT; 472 } 473 else if ((strcasecmp(arg1,"recv") == 0) || 474 (strcasecmp(arg1,"receive") == 0) || 475 (strcasecmp(arg1,"maerts") == 0)) { 476 /* yes, another magic number... */ 477 left = NETPERF_RECV; 478 } 479 else if (strcasecmp(arg1,"rr") == 0) { 480 left = NETPERF_XMIT|NETPERF_RECV; 481 } 482 else { 483 /* we now "ass-u-me" it is a number that can be parsed by strtol() 484 */ 485 left = strtol(arg1,NULL,0); 486 } 487 488 return (left | right); 489 490 } 491 492 int 493 parse_protocol(char protocol_string[]) 494 { 495 char temp[10]; 496 497 strncpy(temp,protocol_string,10); 498 499 if (debug) { 500 fprintf(where, 501 "Attempting to parse protocol from %s derived from %s\n", 502 temp, 503 protocol_string); 504 } 505 506 /* we ass-u-me that everyone has IPPROTO_TCP elsewhere so might as 507 well here, and avoid issues with windows using an enum. Kudos to 508 Jonathan Cook. */ 509 if (!strcasecmp(temp,"tcp")){ 510 socket_type = SOCK_STREAM; 511 return IPPROTO_TCP; 512 } 513 514 if (!strcasecmp(temp,"udp")) { 515 socket_type = SOCK_DGRAM; 516 return IPPROTO_UDP; 517 } 518 519 /* we keep the rest of the #idefs though because these may not be as 520 universal as TCP and UDP... */ 521 #ifdef IPPROTO_SCTP 522 if (!strcasecmp(temp,"sctp")) { 523 /* it can be more than one socket type */ 524 return IPPROTO_SCTP; 525 } 526 #endif 527 #ifdef IPPROTO_SDP 528 if (!strcasecmp(temp,"sdp")) { 529 socket_type = SOCK_STREAM; 530 return IPPROTO_SDP; 531 } 532 #endif 533 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP) 534 if (!strcasecmp(temp,"dccp")) { 535 socket_type = SOCK_DCCP; 536 return IPPROTO_DCCP; 537 } 538 #endif 539 #ifdef IPPROTO_UDPLITE 540 if (!strcasecmp(temp,"udplite")) { 541 socket_type = SOCK_DGRAM; 542 return IPPROTO_UDPLITE; 543 } 544 #endif 545 return IPPROTO_IP; 546 } 547 548 549 void 551 print_netserver_usage() 552 { 553 fprintf(stderr, "%s", netserver_usage); 554 } 555 556 557 void 559 print_netperf_usage() 560 { 561 fprintf(stderr, "%s%s", netperf_usage1, netperf_usage2); 562 } 563 564 /* convert the specified string to upper case if we know how */ 565 static void 566 convert_to_upper(char *source) 567 { 568 #if defined(HAVE_TOUPPER) 569 int i,length; 570 571 length = strlen(source); 572 573 for (i=0; i < length; i++) { 574 source[i] = toupper(source[i]); 575 } 576 #endif 577 return; 578 579 } 580 581 void 582 scan_cmd_line(int argc, char *argv[]) 583 { 584 extern int optind; /* index of first unused arg */ 585 extern char *optarg; /* pointer to option string */ 586 587 int cmnd_len; 588 char *p; 589 590 int c; 591 592 char arg1[BUFSIZ], /* argument holders */ 593 arg2[BUFSIZ]; 594 595 program = (char *)malloc(strlen(argv[0]) + 1); 596 if (program == NULL) { 597 printf("malloc() to store program name failed!\n"); 598 exit(-1); 599 } 600 strcpy(program, argv[0]); 601 602 /* brute force, but effective */ 603 command_line = NULL; 604 cmnd_len = 0; 605 for (c = 0; c < argc; c++) { 606 cmnd_len += strlen(argv[c]); 607 } 608 cmnd_len += argc; /* forget thee not the spaces */ 609 command_line = malloc(cmnd_len+1); 610 611 if (command_line == NULL) { 612 printf("malloc(%d) failed!\n",cmnd_len); 613 exit(-1); 614 } 615 p = command_line; 616 for (c = 0; c < argc; c++) { 617 memcpy(p,argv[c],strlen(argv[c])); 618 p += strlen(argv[c]); 619 *p = ' '; 620 p += 1; 621 } 622 *--p = 0; 623 624 /* Go through all the command line arguments and break them out. For 625 those options that take two parms, specifying only the first will 626 set both to that value. Specifying only the second will leave the 627 first untouched. To change only the first, use the form first, 628 (see the routine break_args.. */ 629 630 while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) { 631 switch (c) { 632 case '?': 633 case 'h': 634 print_netperf_usage(); 635 exit(1); 636 case 'a': 637 /* set local alignments */ 638 break_args(optarg,arg1,arg2); 639 if (arg1[0]) { 640 local_send_align = convert(arg1); 641 } 642 if (arg2[0]) 643 local_recv_align = convert(arg2); 644 break; 645 case 'A': 646 /* set remote alignments */ 647 break_args(optarg,arg1,arg2); 648 if (arg1[0]) { 649 remote_send_align = convert(arg1); 650 } 651 if (arg2[0]) 652 remote_recv_align = convert(arg2); 653 break; 654 case 'c': 655 /* measure local cpu usage please. the user may have specified 656 the cpu rate as an optional parm */ 657 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){ 658 /* there was an optional parm */ 659 local_cpu_rate = (float)atof(argv[optind]); 660 optind++; 661 } 662 local_cpu_usage++; 663 break; 664 case 'C': 665 /* measure remote cpu usage please */ 666 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){ 667 /* there was an optional parm */ 668 remote_cpu_rate = (float)atof(argv[optind]); 669 optind++; 670 } 671 remote_cpu_usage++; 672 break; 673 case 'd': 674 debug++; 675 break; 676 case 'D': 677 #if (defined WANT_DEMO) 678 demo_mode = 1; /* 1 == use units; 2 == always timestamp */ 679 break_args_explicit(optarg,arg1,arg2); 680 if (arg1[0]) { 681 demo_interval = atof(arg1) * 1000000.0; 682 if (demo_interval < 0.0) { 683 demo_interval = demo_interval * -1.0; 684 demo_mode = 2; 685 } 686 } 687 if (arg2[0]) { 688 demo_units = convert(arg2); 689 } 690 #else 691 printf("Sorry, Demo Mode not configured into this netperf.\n" 692 "Please consider reconfiguring netperf with\n" 693 "--enable-demo=yes and recompiling\n"); 694 #endif 695 break; 696 case 'f': 697 /* set the thruput formatting */ 698 libfmt = *optarg; 699 break; 700 case 'F': 701 /* set the fill_file variables for pre-filling buffers. check 702 the remote fill file name length against our limit as we will 703 not hear from the remote on errors opening the fill 704 file. Props to Jonathan Cook for the remote name check */ 705 break_args_explicit(optarg,arg1,arg2); 706 if (arg1[0]) { 707 strncpy(local_fill_file,arg1,sizeof(local_fill_file)); 708 local_fill_file[sizeof(local_fill_file) - 1] = '\0'; 709 } 710 if (arg2[0]) { 711 if (strlen(arg2)>(sizeof(remote_fill_file) - 1)){ 712 fprintf(stderr, 713 "Remote fill file name must be less than %d characters\n", 714 (int) sizeof(remote_fill_file)); 715 fflush(stderr); 716 exit(-1); 717 } 718 719 strncpy(remote_fill_file,arg2,sizeof(remote_fill_file)); 720 remote_fill_file[sizeof(remote_fill_file) - 1] = '\0'; 721 } 722 break; 723 case 'i': 724 /* set the iterations min and max for confidence intervals */ 725 break_args(optarg,arg1,arg2); 726 if (arg1[0]) { 727 iteration_max = convert(arg1); 728 } 729 if (arg2[0] ) { 730 iteration_min = convert(arg2); 731 } 732 /* if the iteration_max is < iteration_min make iteration_max 733 equal iteration_min */ 734 if (iteration_max < iteration_min) iteration_max = iteration_min; 735 /* limit minimum to 3 iterations */ 736 if (iteration_max < 3) iteration_max = 3; 737 if (iteration_min < 3) iteration_min = 3; 738 /* limit maximum to 30 iterations */ 739 if (iteration_max > 30) iteration_max = 30; 740 if (iteration_min > 30) iteration_min = 30; 741 if (confidence_level == 0) confidence_level = 99; 742 if (interval == 0.0) interval = 0.05; /* five percent */ 743 break; 744 case 'I': 745 /* set the confidence level (95 or 99) and width */ 746 break_args(optarg,arg1,arg2); 747 if (arg1[0]) { 748 confidence_level = convert(arg1); 749 } 750 if((confidence_level != 95) && (confidence_level != 99)){ 751 printf("Only 95%% and 99%% confidence level is supported\n"); 752 exit(-1); 753 } 754 if (arg2[0] ) { 755 /* it doesn't make much sense to use convert() here so just 756 use strtod() instead. raj 2007-10-24 */ 757 interval = strtod(arg2,NULL)/100.0; 758 } 759 /* make sure that iteration_min and iteration_max are at least 760 at a reasonable default value. if a -i option has previously 761 been parsed, these will no longer be 1, so we can check 762 against 1 */ 763 if (iteration_min == 1) iteration_min = 3; 764 if (iteration_max == 1) iteration_max = 10; 765 /* make sure that the interval is set if it isn't at its default 766 value */ 767 if (interval == 0.0) interval = 0.05; /* five percent */ 768 break; 769 case 'j': 770 keep_histogram = 1; 771 keep_statistics = 1; 772 break; 773 case 'k': 774 /* local dirty and clean counts */ 775 #ifdef DIRTY 776 break_args(optarg,arg1,arg2); 777 if (arg1[0]) { 778 loc_dirty_count = convert(arg1); 779 } 780 if (arg2[0] ) { 781 loc_clean_count = convert(arg2); 782 } 783 #else 784 printf("I don't know how to get dirty.\n"); 785 #endif /* DIRTY */ 786 break; 787 case 'K': 788 /* remote dirty and clean counts */ 789 #ifdef DIRTY 790 break_args(optarg,arg1,arg2); 791 if (arg1[0]) { 792 rem_dirty_count = convert(arg1); 793 } 794 if (arg2[0] ) { 795 rem_clean_count = convert(arg2); 796 } 797 #else 798 printf("I don't know how to get dirty.\n"); 799 #endif /* DIRTY */ 800 break; 801 case 'n': 802 shell_num_cpus = atoi(optarg); 803 break; 804 case 'N': 805 no_control = 1; 806 break; 807 case 'o': 808 /* set the local offsets */ 809 break_args(optarg,arg1,arg2); 810 if (arg1[0]) 811 local_send_offset = convert(arg1); 812 if (arg2[0]) 813 local_recv_offset = convert(arg2); 814 break; 815 case 'O': 816 /* set the remote offsets */ 817 break_args(optarg,arg1,arg2); 818 if (arg1[0]) 819 remote_send_offset = convert(arg1); 820 if (arg2[0]) 821 remote_recv_offset = convert(arg2); 822 break; 823 case 'P': 824 /* to print or not to print, that is */ 825 /* the header question */ 826 print_headers = convert(optarg); 827 break; 828 case 'r': 829 /* the user wishes that we declare confidence when hit on the 830 result even if not yet reached on CPU utilization. only 831 meaningful if cpu util is enabled */ 832 result_confidence_only = 1; 833 break; 834 case 'S': 835 /* the user wishes us to set SO_KEEPALIVE */ 836 want_keepalive = 1; 837 break; 838 case 's': 839 /* the user wishes us to sleep/pause some length of time before 840 actually starting the test */ 841 wait_time_secs = convert(optarg); 842 break; 843 case 't': 844 /* set the test name and shift it to upper case so we don't have 845 to worry about compares on things like substrings */ 846 strncpy(test_name,optarg,sizeof(test_name)-1); 847 convert_to_upper(test_name); 848 break; 849 case 'T': 850 /* We want to set the processor on which netserver or netperf 851 will run */ 852 break_args(optarg,arg1,arg2); 853 if (arg1[0]) { 854 local_proc_affinity = convert(arg1); 855 bind_to_specific_processor(local_proc_affinity,0); 856 } 857 if (arg2[0]) { 858 remote_proc_affinity = convert(arg2); 859 } 860 cpu_binding_requested = 1; 861 break; 862 case 'W': 863 /* set the "width" of the user space data buffer ring. This will 864 be the number of send_size buffers malloc'd in the tests */ 865 break_args(optarg,arg1,arg2); 866 if (arg1[0]) 867 send_width = convert(arg1); 868 if (arg2[0]) 869 recv_width = convert(arg2); 870 break; 871 case 'y': 872 break_args(optarg, arg1, arg2); 873 #if defined(SO_PRIORITY) 874 if (arg1[0]) 875 local_socket_prio = convert(arg1); 876 #else 877 if (debug) { 878 fprintf(where, 879 "Setting SO_PRIORITY is not supported on this platform, request to set SO_PRIORITY locally ignored.\n"); 880 fflush(where); 881 } 882 local_socket_prio = -3; 883 #endif 884 if (arg2[0]) 885 remote_socket_prio = convert(arg2); 886 break; 887 case 'Y': 888 break_args(optarg, arg1, arg2); 889 #if defined(IP_TOS) || defined(IPV6_TCLASS) 890 if (arg1[0]) 891 local_socket_tos = parse_ipqos(arg1); 892 #else 893 if (debug) { 894 fprintf(where, 895 "Setting IP type-of-service is not supported on this platform, request to set it locally ignored.\n"); 896 fflush(where); 897 } 898 local_socket_tos = -1; 899 #endif 900 if (arg2[0]) { 901 remote_socket_tos = parse_ipqos(arg2); 902 if (debug) { 903 fprintf(where, 904 "Setting remote_socket_tos to 0x%x\n", 905 remote_socket_tos); 906 fflush(where); 907 } 908 } 909 break; 910 case 'Z': 911 /* only copy as much of the passphrase as could fit in the 912 test-specific portion of a control message. Windows does not 913 seem to have a strndup() so just malloc and strncpy it. we 914 weren't checking the strndup() return so won't bother with 915 checking malloc(). we will though make certain we only 916 allocated it once in the event that someone puts -Z on the 917 command line more than once */ 918 if (passphrase == NULL) 919 passphrase = malloc(sizeof(netperf_request.content.test_specific_data)); 920 strncpy(passphrase, 921 optarg, 922 sizeof(netperf_request.content.test_specific_data)); 923 passphrase[sizeof(netperf_request.content.test_specific_data) - 1] = '\0'; 924 break; 925 case 'l': 926 /* determine test end conditions */ 927 /* assume a timed test */ 928 test_time = convert(optarg); 929 test_bytes = test_trans = 0; 930 if (test_time < 0) { 931 test_bytes = -1 * test_time; 932 test_trans = test_bytes; 933 test_time = 0; 934 } 935 break; 936 case 'v': 937 /* say how much to say */ 938 verbosity = convert(optarg); 939 break; 940 case 'p': 941 /* specify an alternate port number we use break_args_explicit 942 here to maintain backwards compatibility with previous 943 generations of netperf where having a single value did not 944 set both remote _and_ local port number. raj 2005-02-04 */ 945 break_args_explicit(optarg,arg1,arg2); 946 if (arg1[0]) 947 strncpy(test_port,arg1,PORTBUFSIZE); 948 if (arg2[0]) 949 strncpy(local_test_port,arg2,PORTBUFSIZE); 950 break; 951 case 'H': 952 /* save-off the host identifying information, use 953 break_args_explicit since passing just one value should not 954 set both */ 955 break_args_explicit(optarg,arg1,arg2); 956 if (arg1[0]) 957 strncpy(host_name,arg1,sizeof(host_name)); 958 if (arg2[0]) 959 address_family = parse_address_family(arg2); 960 break; 961 case 'L': 962 /* save-off the local control socket addressing information. use 963 break_args_explicit since passing just one value should not 964 set both */ 965 break_args_explicit(optarg,arg1,arg2); 966 if (arg1[0]) 967 strncpy(local_host_name,arg1,sizeof(local_host_name)); 968 if (arg2[0]) 969 local_address_family = parse_address_family(arg2); 970 break; 971 case 'w': 972 /* We want to send requests at a certain wate. Remember that 973 there are 1000000 usecs in a second, and that the packet rate 974 is expressed in packets per millisecond. shuffle the #ifdef 975 around a bit to deal with both netperf and netserver possibly 976 doing intervals with omni tests */ 977 break_args_explicit(optarg,arg1,arg2); 978 if (arg1[0]) { 979 #ifdef WANT_INTERVALS 980 interval_usecs = convert_timespec(arg1); 981 interval_wate = interval_usecs / 1000; 982 #else 983 fprintf(where, 984 "Packet rate control is not compiled in.\n"); 985 #endif 986 } 987 if (arg2[0]) { 988 /* we pass usecs to the remote and let it deal to cover both 989 intervals and spin methods. if he wasn't intervals enabled 990 he will return a suitable value back to us */ 991 remote_interval_usecs = convert_timespec(arg2); 992 } 993 break; 994 case 'b': 995 /* we want to have a burst so many packets per */ 996 /* interval. */ 997 break_args_explicit(optarg,arg1,arg2); 998 if (arg1[0]) { 999 #ifdef WANT_INTERVALS 1000 interval_burst = convert(arg1); 1001 /* set a default in case the user does not include the -w 1002 option */ 1003 if (interval_usecs == 0) { 1004 interval_wate = 1; 1005 interval_usecs = 1000; 1006 } 1007 #else 1008 fprintf(where, 1009 "Packet burst size is not compiled in. \n"); 1010 #endif /* WANT_INTERVALS */ 1011 } 1012 /* there is no ifdef here because we are sending this value to 1013 the remote, which may or may not have been compiled for 1014 intervals and we don't have a way of knowing on this side 1015 until we try */ 1016 if (arg2[0]) { 1017 remote_interval_burst = convert(arg2); 1018 if (remote_interval_usecs == 0) { 1019 remote_interval_usecs = 1000; 1020 } 1021 } 1022 break; 1023 case 'B': 1024 result_brand = malloc(strlen(optarg)+1); 1025 if (NULL != result_brand) { 1026 strcpy(result_brand,optarg); 1027 } 1028 else { 1029 fprintf(where, 1030 "Unable to malloc space for result brand\n"); 1031 } 1032 break; 1033 case '4': 1034 address_family = AF_INET; 1035 local_address_family = AF_INET; 1036 break; 1037 case '6': 1038 #if defined(AF_INET6) 1039 address_family = AF_INET6; 1040 local_address_family = AF_INET6; 1041 #else 1042 printf("This netperf was not compiled on an IPv6 capable system!\n"); 1043 exit(-1); 1044 #endif 1045 break; 1046 case 'V': 1047 printf("Netperf version %s\n",NETPERF_VERSION); 1048 exit(0); 1049 break; 1050 }; 1051 } 1052 /* ok, what should our default hostname and local binding info be? 1053 */ 1054 1055 if ('\0' == host_name[0]) { 1056 /* host_name was not set */ 1057 switch (address_family) { 1058 case AF_INET: 1059 #if defined(AF_RDS) 1060 case AF_RDS: 1061 #endif 1062 strcpy(host_name,"localhost"); 1063 break; 1064 case AF_UNSPEC: 1065 /* what to do here? case it off the local_address_family I 1066 suppose */ 1067 switch (local_address_family) { 1068 case AF_INET: 1069 case AF_UNSPEC: 1070 #if defined(AF_RDS) 1071 case AF_RDS: 1072 #endif 1073 strcpy(host_name,"localhost"); 1074 break; 1075 #if defined(AF_INET6) 1076 case AF_INET6: 1077 strcpy(host_name,"::1"); 1078 break; 1079 #endif 1080 default: 1081 printf("Netperf does not understand %d as an address family\n", 1082 address_family); 1083 exit(-1); 1084 } 1085 break; 1086 #if defined(AF_INET6) 1087 case AF_INET6: 1088 strcpy(host_name,"::1"); 1089 break; 1090 #endif 1091 default: 1092 printf("Netperf does not understand %d as an address family\n", 1093 address_family); 1094 exit(-1); 1095 } 1096 } else { 1097 /* resolve the hostname and pull the address family from the 1098 addrinfo */ 1099 struct addrinfo *ai; 1100 1101 ai = resolve_host(host_name, NULL, address_family); 1102 if (!ai) { 1103 printf("Netperf could not resolve %s as a host name\n", host_name); 1104 exit(-1); 1105 } 1106 address_family = ai->ai_family; 1107 freeaddrinfo(ai); 1108 } 1109 1110 1111 /* now, having established the name to which the control will 1112 connect, from what should it come? */ 1113 if ('\0' == local_host_name[0]) { 1114 switch (local_address_family) { 1115 case AF_INET: 1116 #if defined(AF_RDS) 1117 case AF_RDS: 1118 #endif 1119 strcpy(local_host_name,"0.0.0.0"); 1120 break; 1121 case AF_UNSPEC: 1122 switch (address_family) { 1123 case AF_INET: 1124 case AF_UNSPEC: 1125 #if defined(AF_RDS) 1126 case AF_RDS: 1127 #endif 1128 strcpy(local_host_name,"0.0.0.0"); 1129 break; 1130 #if defined(AF_INET6) 1131 case AF_INET6: 1132 strcpy(local_host_name,"::0"); 1133 break; 1134 #endif 1135 default: 1136 printf("Netperf does not understand %d as an address family\n", 1137 address_family); 1138 exit(-1); 1139 } 1140 break; 1141 #if defined(AF_INET6) 1142 case AF_INET6: 1143 strcpy(local_host_name,"::0"); 1144 break; 1145 #endif 1146 default: 1147 printf("Netperf does not understand %d as an address family\n", 1148 address_family); 1149 exit(-1); 1150 } 1151 } 1152 1153 /* so, if we aren't even going to establish a control connection we 1154 should set certain "remote" settings to reflect this, regardless 1155 of what else may have been set on the command line */ 1156 if (no_control) { 1157 remote_socket_prio = -1; 1158 remote_socket_tos = -1; 1159 remote_recv_align = -1; 1160 remote_send_align = -1; 1161 remote_send_offset = -1; 1162 remote_recv_offset = -1; 1163 remote_cpu_rate = (float)-1.0; 1164 remote_cpu_usage = 0; 1165 } 1166 1167 /* parsing test-specific options used to be conditional on there 1168 being a "--" in the option stream. however, some of the tests 1169 have other initialization happening in their "scan" routines so 1170 we want to call them regardless. raj 2005-02-08 */ 1171 /* while the parsing of the command line will upshift the test name, 1172 since we don't know that there will always be a way to do so? we 1173 will retain for now the strcasecmp calls rather than switch to 1174 strcmp. raj 20101220 */ 1175 if ( 1176 #ifndef WANT_MIGRATION 1177 (strcasecmp(test_name,"TCP_STREAM") == 0) || 1178 (strcasecmp(test_name,"TCP_MAERTS") == 0) || 1179 (strcasecmp(test_name,"TCP_RR") == 0) || 1180 (strcasecmp(test_name,"TCP_CRR") == 0) || 1181 (strcasecmp(test_name,"UDP_STREAM") == 0) || 1182 (strcasecmp(test_name,"UDP_RR") == 0) || 1183 #endif 1184 #ifdef HAVE_ICSC_EXS 1185 (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) || 1186 #endif /* HAVE_ICSC_EXS */ 1187 #ifdef HAVE_SENDFILE 1188 (strcasecmp(test_name,"TCP_SENDFILE") == 0) || 1189 #endif /* HAVE_SENDFILE */ 1190 (strcasecmp(test_name,"TCP_CC") == 0) || 1191 (strcasecmp(test_name,"TCP_MSS") == 0) || 1192 #ifdef DO_1644 1193 (strcasecmp(test_name,"TCP_TRR") == 0) || 1194 #endif /* DO_1644 */ 1195 #ifdef DO_NBRR 1196 (strcasecmp(test_name,"TCP_TRR") == 0) || 1197 #endif /* DO_NBRR */ 1198 (0)) 1199 { 1200 scan_sockets_args(argc, argv); 1201 } 1202 1203 #ifdef WANT_DLPI 1204 else if ((strcasecmp(test_name,"DLCO_RR") == 0) || 1205 (strcasecmp(test_name,"DLCL_RR") == 0) || 1206 (strcasecmp(test_name,"DLCO_STREAM") == 0) || 1207 (strcasecmp(test_name,"DLCL_STREAM") == 0)) 1208 { 1209 scan_dlpi_args(argc, argv); 1210 } 1211 #endif /* WANT_DLPI */ 1212 1213 #ifdef WANT_UNIX 1214 else if ((strcasecmp(test_name,"STREAM_RR") == 0) || 1215 (strcasecmp(test_name,"DG_RR") == 0) || 1216 (strcasecmp(test_name,"STREAM_STREAM") == 0) || 1217 (strcasecmp(test_name,"DG_STREAM") == 0)) 1218 { 1219 scan_unix_args(argc, argv); 1220 } 1221 #endif /* WANT_UNIX */ 1222 1223 #ifdef WANT_XTI 1224 else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) || 1225 (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) || 1226 (strcasecmp(test_name,"XTI_UDP_RR") == 0) || 1227 (strcasecmp(test_name,"XTI_UDP_STREAM") == 0)) 1228 { 1229 scan_xti_args(argc, argv); 1230 } 1231 #endif /* WANT_XTI */ 1232 1233 #ifdef WANT_SCTP 1234 else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) || 1235 (strcasecmp(test_name,"SCTP_RR") == 0) || 1236 (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) || 1237 (strcasecmp(test_name,"SCTP_RR_MANY") == 0)) 1238 { 1239 scan_sctp_args(argc, argv); 1240 } 1241 #endif 1242 1243 #ifdef WANT_SDP 1244 else if((strcasecmp(test_name,"SDP_STREAM") == 0) || 1245 (strcasecmp(test_name,"SDP_MAERTS") == 0) || 1246 (strcasecmp(test_name,"SDP_RR") == 0)) 1247 { 1248 scan_sdp_args(argc, argv); 1249 } 1250 #endif 1251 1252 #ifdef WANT_OMNI 1253 else if ((strcasecmp(test_name,"OMNI") == 0) || 1254 #ifdef WANT_MIGRATION 1255 (strcasecmp(test_name,"TCP_STREAM") == 0) || 1256 (strcasecmp(test_name,"TCP_MAERTS") == 0) || 1257 (strcasecmp(test_name,"TCP_RR") == 0) || 1258 (strcasecmp(test_name,"TCP_CRR") == 0) || 1259 (strcasecmp(test_name,"UDP_STREAM") == 0) || 1260 (strcasecmp(test_name,"UDP_RR") == 0) || 1261 #endif 1262 (strcasecmp(test_name,"UUID") == 0)) { 1263 scan_omni_args(argc, argv); 1264 } 1265 #endif 1266 1267 /* what is our default value for the output units? if the test 1268 name contains "RR" or "rr" or "Rr" or "rR" then the default is 1269 'x' for transactions. otherwise it is 'm' for megabits (10^6) 1270 however... if this is an "omni" test then we want to defer 1271 this decision to scan_omni_args */ 1272 1273 if (strcasecmp(test_name,"omni")) { 1274 if ('?' == libfmt) { 1275 /* we use a series of strstr's here because not everyone has 1276 strcasestr and I don't feel like up or downshifting text */ 1277 if ((strstr(test_name,"RR")) || 1278 (strstr(test_name,"rr")) || 1279 (strstr(test_name,"Rr")) || 1280 (strstr(test_name,"rR"))) { 1281 libfmt = 'x'; 1282 } 1283 else { 1284 libfmt = 'm'; 1285 } 1286 } 1287 else if ('x' == libfmt) { 1288 /* now, a format of 'x' makes no sense for anything other than 1289 an RR test. if someone has been silly enough to try to set 1290 that, we will reset it silently to default - namely 'm' */ 1291 if ((strstr(test_name,"RR") == NULL) && 1292 (strstr(test_name,"rr") == NULL) && 1293 (strstr(test_name,"Rr") == NULL) && 1294 (strstr(test_name,"rR") == NULL)) { 1295 libfmt = 'm'; 1296 } 1297 } 1298 } 1299 } 1300 1301 1302 void 1304 dump_globals() 1305 { 1306 printf("Program name: %s\n", program); 1307 printf("Local send alignment: %d\n",local_send_align); 1308 printf("Local recv alignment: %d\n",local_recv_align); 1309 printf("Remote send alignment: %d\n",remote_send_align); 1310 printf("Remote recv alignment: %d\n",remote_recv_align); 1311 printf("Local socket priority: %d\n", local_socket_prio); 1312 printf("Remote socket priority: %d\n", remote_socket_prio); 1313 printf("Local socket TOS: %s\n", iptos2str(local_socket_tos)); 1314 printf("Remote socket TOS: %s\n", iptos2str(remote_socket_tos)); 1315 printf("Report local CPU %d\n",local_cpu_usage); 1316 printf("Report remote CPU %d\n",remote_cpu_usage); 1317 printf("Verbosity: %d\n",verbosity); 1318 printf("Debug: %d\n",debug); 1319 printf("Port: %s\n",test_port); 1320 printf("Test name: %s\n",test_name); 1321 printf("Test bytes: %d Test time: %d Test trans: %d\n", 1322 test_bytes, 1323 test_time, 1324 test_trans); 1325 printf("Host name: %s\n",host_name); 1326 printf("\n"); 1327 } 1328