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.
305 If the second argument is not specified, and there is no comma,
306 then the value of the second argument will be the same as the value
307 of the first. If there is a comma, then the value of the second
308 argument will be the value of the second argument ;-) */
309 void
break_args(char * s,char * arg1,char * arg2)310 break_args(char *s, char *arg1, char *arg2)
311
312 {
313 char *ns;
314 ns = strchr(s,',');
315 if (ns) {
316 /* there was a comma arg2 should be the second arg*/
317 *ns++ = '\0';
318 while ((*arg2++ = *ns++) != '\0');
319 }
320 else {
321 /* there was not a comma, we can use ns as a temp s */
322 /* and arg2 should be the same value as arg1 */
323 ns = s;
324 while ((*arg2++ = *ns++) != '\0');
325 };
326 while ((*arg1++ = *s++) != '\0');
327 }
328
329 /* break_args_explicit_sep
330
331 this routine is somewhat like break_args in that it will separate a
332 pair of values using the given separator. however, if there is no
333 separator this version will not ass-u-me that arg2 should be the
334 same as arg1. raj 20101129 */
335
336 void
break_args_explicit_sep(char * s,int sep,char * arg1,char * arg2)337 break_args_explicit_sep(char *s, int sep, char *arg1, char *arg2)
338
339 {
340 char *ns;
341 ns = strchr(s,sep);
342 if (ns) {
343 /* there was a separator arg2 should be the second arg*/
344 *ns++ = '\0';
345 while ((*arg2++ = *ns++) != '\0');
346 }
347 else {
348 /* there was no separator, so we should make sure that arg2 is \0
349 lest something become confused. raj 2005-02-04 */
350 *arg2 = '\0';
351 };
352 while ((*arg1++ = *s++) != '\0');
353
354 }
355
356 /* break_args_explicit - now just a wrapper around a call to
357 break_args_explicit_sep passing-in a ',' as the separator. raj
358 20101129 */
359
360 void
break_args_explicit(char * s,char * arg1,char * arg2)361 break_args_explicit(char *s, char *arg1, char *arg2)
362
363 {
364 break_args_explicit_sep(s, ',', arg1, arg2);
365 }
366
367
368 /* given a string with possible values for setting an address family,
369 convert that into one of the AF_mumble values - AF_INET, AF_INET6,
370 AF_UNSPEC as apropriate. the family_string is compared in a
371 case-insensitive manner */
372
373 int
parse_address_family(char family_string[])374 parse_address_family(char family_string[])
375 {
376
377 char temp[10]; /* gotta love magic constants :) */
378
379 strncpy(temp,family_string,10);
380
381 if (debug) {
382 fprintf(where,
383 "Attempting to parse address family from %s derived from %s\n",
384 temp,
385 family_string);
386 }
387 #if defined(AF_INET6)
388 if (strstr(temp,"6")) {
389 return(AF_INET6);
390 }
391 #endif
392 if (strstr(temp,"inet") ||
393 strstr(temp,"4")) {
394 return(AF_INET);
395 }
396 #if defined(AF_RDS)
397 if (strstr(temp,"af_rds") ||
398 strstr(temp,"32")) {
399 return(AF_RDS);
400 }
401 #endif
402 if (strstr(temp,"unspec") ||
403 strstr(temp,"0")) {
404 return(AF_UNSPEC);
405 }
406 fprintf(where,
407 "WARNING! %s not recognized as an address family, using AF_UNPSEC\n"
408 "Are you sure netperf was configured for that address family?\n",
409 family_string);
410 fflush(where);
411 return(AF_UNSPEC);
412 }
413
414 int
parse_socket_type(char socket_string[])415 parse_socket_type(char socket_string[]) {
416
417 char temp[10];
418
419 strncpy(temp,socket_string,10);
420
421 if (debug) {
422 fprintf(where,
423 "Attempting to parse socket type from %s derived from %s\n",
424 temp,
425 socket_string);
426 }
427
428 #ifdef SOCK_STREAM
429 if (strstr(temp,"stream"))
430 return SOCK_STREAM;
431 #endif
432 #ifdef SOCK_DGRAM
433 if (strstr(temp,"dgram"))
434 return SOCK_DGRAM;
435 #endif
436 return NST_UNKN;
437
438 }
439
440 int
parse_direction(char direction_string[])441 parse_direction(char direction_string[])
442 {
443 char arg1[BUFSIZ],arg2[BUFSIZ];
444 int left, right;
445
446 if (NULL == direction_string) {
447 return 0;
448 }
449
450 if (direction_string[0] == '\0') {
451 return 0;
452 }
453
454 /* allow someone to "or" break_args_explicit will split at the first
455 '|' in the string so we know that arg1 has no '|' in it and arg2
456 might */
457 break_args_explicit_sep(direction_string,'|',arg1,arg2);
458
459 /* at this point only arg2 could contain a '|' so recurse on that */
460 right = parse_direction(arg2);
461
462 /* now we parse the "left side" or arg1 */
463 if (arg1[0] == '\0') {
464 left = 0;
465 }
466 else if ((strcasecmp(arg1,"xmit") == 0) ||
467 (strcasecmp(arg1,"send") == 0) ||
468 (strcasecmp(arg1,"stream") == 0) ||
469 (strcasecmp(arg1,"transmit") == 0)) {
470 left = NETPERF_XMIT;
471 }
472 else if ((strcasecmp(arg1,"recv") == 0) ||
473 (strcasecmp(arg1,"receive") == 0) ||
474 (strcasecmp(arg1,"maerts") == 0)) {
475 /* yes, another magic number... */
476 left = NETPERF_RECV;
477 }
478 else if (strcasecmp(arg1,"rr") == 0) {
479 left = NETPERF_XMIT|NETPERF_RECV;
480 }
481 else {
482 /* we now "ass-u-me" it is a number that can be parsed by strtol()
483 */
484 left = strtol(arg1,NULL,0);
485 }
486
487 return (left | right);
488
489 }
490
491 int
parse_protocol(char protocol_string[])492 parse_protocol(char protocol_string[])
493 {
494 char temp[10];
495
496 strncpy(temp,protocol_string,10);
497
498 if (debug) {
499 fprintf(where,
500 "Attempting to parse protocol from %s derived from %s\n",
501 temp,
502 protocol_string);
503 }
504
505 /* we ass-u-me that everyone has IPPROTO_TCP elsewhere so might as
506 well here, and avoid issues with windows using an enum. Kudos to
507 Jonathan Cook. */
508 if (!strcasecmp(temp,"tcp")){
509 socket_type = SOCK_STREAM;
510 return IPPROTO_TCP;
511 }
512
513 if (!strcasecmp(temp,"udp")) {
514 socket_type = SOCK_DGRAM;
515 return IPPROTO_UDP;
516 }
517
518 /* we keep the rest of the #idefs though because these may not be as
519 universal as TCP and UDP... */
520 #ifdef IPPROTO_SCTP
521 if (!strcasecmp(temp,"sctp")) {
522 /* it can be more than one socket type */
523 return IPPROTO_SCTP;
524 }
525 #endif
526 #ifdef IPPROTO_SDP
527 if (!strcasecmp(temp,"sdp")) {
528 socket_type = SOCK_STREAM;
529 return IPPROTO_SDP;
530 }
531 #endif
532 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
533 if (!strcasecmp(temp,"dccp")) {
534 socket_type = SOCK_DCCP;
535 return IPPROTO_DCCP;
536 }
537 #endif
538 #ifdef IPPROTO_UDPLITE
539 if (!strcasecmp(temp,"udplite")) {
540 socket_type = SOCK_DGRAM;
541 return IPPROTO_UDPLITE;
542 }
543 #endif
544 return IPPROTO_IP;
545 }
546
547
548 void
print_netserver_usage()549 print_netserver_usage()
550 {
551 fprintf(stderr, "%s", netserver_usage);
552 }
553
554
555 void
print_netperf_usage()556 print_netperf_usage()
557 {
558 fprintf(stderr, "%s%s", netperf_usage1, netperf_usage2);
559 }
560
561 /* convert the specified string to upper case if we know how */
562 static void
convert_to_upper(char * source)563 convert_to_upper(char *source)
564 {
565 #if defined(HAVE_TOUPPER)
566 int i,length;
567
568 length = strlen(source);
569
570 for (i=0; i < length; i++) {
571 source[i] = toupper(source[i]);
572 }
573 #endif
574 return;
575
576 }
577
578 void
scan_cmd_line(int argc,char * argv[])579 scan_cmd_line(int argc, char *argv[])
580 {
581 extern int optind; /* index of first unused arg */
582 extern char *optarg; /* pointer to option string */
583
584 int cmnd_len;
585 char *p;
586
587 int c;
588
589 char arg1[BUFSIZ], /* argument holders */
590 arg2[BUFSIZ];
591
592 program = (char *)malloc(strlen(argv[0]) + 1);
593 if (program == NULL) {
594 printf("malloc() to store program name failed!\n");
595 exit(-1);
596 }
597 strcpy(program, argv[0]);
598
599 /* brute force, but effective */
600 command_line = NULL;
601 cmnd_len = 0;
602 for (c = 0; c < argc; c++) {
603 cmnd_len += strlen(argv[c]);
604 }
605 cmnd_len += argc; /* forget thee not the spaces */
606 command_line = malloc(cmnd_len+1);
607
608 if (command_line == NULL) {
609 printf("malloc(%d) failed!\n",cmnd_len);
610 exit(-1);
611 }
612 p = command_line;
613 for (c = 0; c < argc; c++) {
614 memcpy(p,argv[c],strlen(argv[c]));
615 p += strlen(argv[c]);
616 *p = ' ';
617 p += 1;
618 }
619 *--p = 0;
620
621 /* Go through all the command line arguments and break them out. For
622 those options that take two parms, specifying only the first will
623 set both to that value. Specifying only the second will leave the
624 first untouched. To change only the first, use the form first,
625 (see the routine break_args.. */
626
627 while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
628 switch (c) {
629 case '?':
630 case 'h':
631 print_netperf_usage();
632 exit(1);
633 case 'a':
634 /* set local alignments */
635 break_args(optarg,arg1,arg2);
636 if (arg1[0]) {
637 local_send_align = convert(arg1);
638 }
639 if (arg2[0])
640 local_recv_align = convert(arg2);
641 break;
642 case 'A':
643 /* set remote alignments */
644 break_args(optarg,arg1,arg2);
645 if (arg1[0]) {
646 remote_send_align = convert(arg1);
647 }
648 if (arg2[0])
649 remote_recv_align = convert(arg2);
650 break;
651 case 'c':
652 /* measure local cpu usage please. the user may have specified
653 the cpu rate as an optional parm */
654 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
655 /* there was an optional parm */
656 local_cpu_rate = (float)atof(argv[optind]);
657 optind++;
658 }
659 local_cpu_usage++;
660 break;
661 case 'C':
662 /* measure remote cpu usage please */
663 if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
664 /* there was an optional parm */
665 remote_cpu_rate = (float)atof(argv[optind]);
666 optind++;
667 }
668 remote_cpu_usage++;
669 break;
670 case 'd':
671 debug++;
672 break;
673 case 'D':
674 #if (defined WANT_DEMO)
675 demo_mode = 1; /* 1 == use units; 2 == always timestamp */
676 break_args_explicit(optarg,arg1,arg2);
677 if (arg1[0]) {
678 demo_interval = atof(arg1) * 1000000.0;
679 if (demo_interval < 0.0) {
680 demo_interval = demo_interval * -1.0;
681 demo_mode = 2;
682 }
683 }
684 if (arg2[0]) {
685 demo_units = convert(arg2);
686 }
687 #else
688 printf("Sorry, Demo Mode not configured into this netperf.\n"
689 "Please consider reconfiguring netperf with\n"
690 "--enable-demo=yes and recompiling\n");
691 #endif
692 break;
693 case 'f':
694 /* set the thruput formatting */
695 libfmt = *optarg;
696 break;
697 case 'F':
698 /* set the fill_file variables for pre-filling buffers. check
699 the remote fill file name length against our limit as we will
700 not hear from the remote on errors opening the fill
701 file. Props to Jonathan Cook for the remote name check */
702 break_args_explicit(optarg,arg1,arg2);
703 if (arg1[0]) {
704 strncpy(local_fill_file,arg1,sizeof(local_fill_file));
705 local_fill_file[sizeof(local_fill_file) - 1] = '\0';
706 }
707 if (arg2[0]) {
708 if (strlen(arg2)>(sizeof(remote_fill_file) - 1)){
709 fprintf(stderr,
710 "Remote fill file name must be less than %d characters\n",
711 (int) sizeof(remote_fill_file));
712 fflush(stderr);
713 exit(-1);
714 }
715
716 strncpy(remote_fill_file,arg2,sizeof(remote_fill_file));
717 remote_fill_file[sizeof(remote_fill_file) - 1] = '\0';
718 }
719 break;
720 case 'i':
721 /* set the iterations min and max for confidence intervals */
722 break_args(optarg,arg1,arg2);
723 if (arg1[0]) {
724 iteration_max = convert(arg1);
725 }
726 if (arg2[0] ) {
727 iteration_min = convert(arg2);
728 }
729 /* if the iteration_max is < iteration_min make iteration_max
730 equal iteration_min */
731 if (iteration_max < iteration_min) iteration_max = iteration_min;
732 /* limit minimum to 3 iterations */
733 if (iteration_max < 3) iteration_max = 3;
734 if (iteration_min < 3) iteration_min = 3;
735 /* limit maximum to 30 iterations */
736 if (iteration_max > 30) iteration_max = 30;
737 if (iteration_min > 30) iteration_min = 30;
738 if (confidence_level == 0) confidence_level = 99;
739 if (interval == 0.0) interval = 0.05; /* five percent */
740 break;
741 case 'I':
742 /* set the confidence level (95 or 99) and width */
743 break_args(optarg,arg1,arg2);
744 if (arg1[0]) {
745 confidence_level = convert(arg1);
746 }
747 if((confidence_level != 95) && (confidence_level != 99)){
748 printf("Only 95%% and 99%% confidence level is supported\n");
749 exit(-1);
750 }
751 if (arg2[0] ) {
752 /* it doesn't make much sense to use convert() here so just
753 use strtod() instead. raj 2007-10-24 */
754 interval = strtod(arg2,NULL)/100.0;
755 }
756 /* make sure that iteration_min and iteration_max are at least
757 at a reasonable default value. if a -i option has previously
758 been parsed, these will no longer be 1, so we can check
759 against 1 */
760 if (iteration_min == 1) iteration_min = 3;
761 if (iteration_max == 1) iteration_max = 10;
762 /* make sure that the interval is set if it isn't at its default
763 value */
764 if (interval == 0.0) interval = 0.05; /* five percent */
765 break;
766 case 'j':
767 keep_histogram = 1;
768 keep_statistics = 1;
769 break;
770 case 'k':
771 /* local dirty and clean counts */
772 #ifdef DIRTY
773 break_args(optarg,arg1,arg2);
774 if (arg1[0]) {
775 loc_dirty_count = convert(arg1);
776 }
777 if (arg2[0] ) {
778 loc_clean_count = convert(arg2);
779 }
780 #else
781 printf("I don't know how to get dirty.\n");
782 #endif /* DIRTY */
783 break;
784 case 'K':
785 /* remote dirty and clean counts */
786 #ifdef DIRTY
787 break_args(optarg,arg1,arg2);
788 if (arg1[0]) {
789 rem_dirty_count = convert(arg1);
790 }
791 if (arg2[0] ) {
792 rem_clean_count = convert(arg2);
793 }
794 #else
795 printf("I don't know how to get dirty.\n");
796 #endif /* DIRTY */
797 break;
798 case 'n':
799 shell_num_cpus = atoi(optarg);
800 break;
801 case 'N':
802 no_control = 1;
803 break;
804 case 'o':
805 /* set the local offsets */
806 break_args(optarg,arg1,arg2);
807 if (arg1[0])
808 local_send_offset = convert(arg1);
809 if (arg2[0])
810 local_recv_offset = convert(arg2);
811 break;
812 case 'O':
813 /* set the remote offsets */
814 break_args(optarg,arg1,arg2);
815 if (arg1[0])
816 remote_send_offset = convert(arg1);
817 if (arg2[0])
818 remote_recv_offset = convert(arg2);
819 break;
820 case 'P':
821 /* to print or not to print, that is */
822 /* the header question */
823 print_headers = convert(optarg);
824 break;
825 case 'r':
826 /* the user wishes that we declare confidence when hit on the
827 result even if not yet reached on CPU utilization. only
828 meaningful if cpu util is enabled */
829 result_confidence_only = 1;
830 break;
831 case 'S':
832 /* the user wishes us to set SO_KEEPALIVE */
833 want_keepalive = 1;
834 break;
835 case 's':
836 /* the user wishes us to sleep/pause some length of time before
837 actually starting the test */
838 wait_time_secs = convert(optarg);
839 break;
840 case 't':
841 /* set the test name and shift it to upper case so we don't have
842 to worry about compares on things like substrings */
843 strncpy(test_name,optarg,sizeof(test_name)-1);
844 convert_to_upper(test_name);
845 break;
846 case 'T':
847 /* We want to set the processor on which netserver or netperf
848 will run */
849 break_args(optarg,arg1,arg2);
850 if (arg1[0]) {
851 local_proc_affinity = convert(arg1);
852 bind_to_specific_processor(local_proc_affinity,0);
853 }
854 if (arg2[0]) {
855 remote_proc_affinity = convert(arg2);
856 }
857 cpu_binding_requested = 1;
858 break;
859 case 'W':
860 /* set the "width" of the user space data buffer ring. This will
861 be the number of send_size buffers malloc'd in the tests */
862 break_args(optarg,arg1,arg2);
863 if (arg1[0])
864 send_width = convert(arg1);
865 if (arg2[0])
866 recv_width = convert(arg2);
867 break;
868 case 'y':
869 break_args(optarg, arg1, arg2);
870 #if defined(SO_PRIORITY)
871 if (arg1[0])
872 local_socket_prio = convert(arg1);
873 #else
874 if (debug) {
875 fprintf(where,
876 "Setting SO_PRIORITY is not supported on this platform, request to set SO_PRIORITY locally ignored.\n");
877 fflush(where);
878 }
879 local_socket_prio = -3;
880 #endif
881 if (arg2[0])
882 remote_socket_prio = convert(arg2);
883 break;
884 case 'Y':
885 break_args(optarg, arg1, arg2);
886 #if defined(IP_TOS) || defined(IPV6_TCLASS)
887 if (arg1[0])
888 local_socket_tos = parse_ipqos(arg1);
889 #else
890 if (debug) {
891 fprintf(where,
892 "Setting IP type-of-service is not supported on this platform, request to set it locally ignored.\n");
893 fflush(where);
894 }
895 local_socket_tos = -1;
896 #endif
897 if (arg2[0]) {
898 remote_socket_tos = parse_ipqos(arg2);
899 if (debug) {
900 fprintf(where,
901 "Setting remote_socket_tos to 0x%x\n",
902 remote_socket_tos);
903 fflush(where);
904 }
905 }
906 break;
907 case 'Z':
908 /* only copy as much of the passphrase as could fit in the
909 test-specific portion of a control message. Windows does not
910 seem to have a strndup() so just malloc and strncpy it. we
911 weren't checking the strndup() return so won't bother with
912 checking malloc(). we will though make certain we only
913 allocated it once in the event that someone puts -Z on the
914 command line more than once */
915 if (passphrase == NULL)
916 passphrase = malloc(sizeof(netperf_request.content.test_specific_data));
917 strncpy(passphrase,
918 optarg,
919 sizeof(netperf_request.content.test_specific_data));
920 passphrase[sizeof(netperf_request.content.test_specific_data) - 1] = '\0';
921 break;
922 case 'l':
923 /* determine test end conditions */
924 /* assume a timed test */
925 test_time = convert(optarg);
926 test_bytes = test_trans = 0;
927 if (test_time < 0) {
928 test_bytes = -1 * test_time;
929 test_trans = test_bytes;
930 test_time = 0;
931 }
932 break;
933 case 'v':
934 /* say how much to say */
935 verbosity = convert(optarg);
936 break;
937 case 'p':
938 /* specify an alternate port number we use break_args_explicit
939 here to maintain backwards compatibility with previous
940 generations of netperf where having a single value did not
941 set both remote _and_ local port number. raj 2005-02-04 */
942 break_args_explicit(optarg,arg1,arg2);
943 if (arg1[0])
944 strncpy(test_port,arg1,PORTBUFSIZE);
945 if (arg2[0])
946 strncpy(local_test_port,arg2,PORTBUFSIZE);
947 break;
948 case 'H':
949 /* save-off the host identifying information, use
950 break_args_explicit since passing just one value should not
951 set both */
952 break_args_explicit(optarg,arg1,arg2);
953 if (arg1[0])
954 strncpy(host_name,arg1,sizeof(host_name));
955 if (arg2[0])
956 address_family = parse_address_family(arg2);
957 break;
958 case 'L':
959 /* save-off the local control socket addressing information. use
960 break_args_explicit since passing just one value should not
961 set both */
962 break_args_explicit(optarg,arg1,arg2);
963 if (arg1[0])
964 strncpy(local_host_name,arg1,sizeof(local_host_name));
965 if (arg2[0])
966 local_address_family = parse_address_family(arg2);
967 break;
968 case 'w':
969 /* We want to send requests at a certain wate. Remember that
970 there are 1000000 usecs in a second, and that the packet rate
971 is expressed in packets per millisecond. shuffle the #ifdef
972 around a bit to deal with both netperf and netserver possibly
973 doing intervals with omni tests */
974 break_args_explicit(optarg,arg1,arg2);
975 if (arg1[0]) {
976 #ifdef WANT_INTERVALS
977 interval_usecs = convert_timespec(arg1);
978 interval_wate = interval_usecs / 1000;
979 #else
980 fprintf(where,
981 "Packet rate control is not compiled in.\n");
982 #endif
983 }
984 if (arg2[0]) {
985 /* we pass usecs to the remote and let it deal to cover both
986 intervals and spin methods. if he wasn't intervals enabled
987 he will return a suitable value back to us */
988 remote_interval_usecs = convert_timespec(arg2);
989 }
990 break;
991 case 'b':
992 /* we want to have a burst so many packets per */
993 /* interval. */
994 break_args_explicit(optarg,arg1,arg2);
995 if (arg1[0]) {
996 #ifdef WANT_INTERVALS
997 interval_burst = convert(arg1);
998 /* set a default in case the user does not include the -w
999 option */
1000 if (interval_usecs == 0) {
1001 interval_wate = 1;
1002 interval_usecs = 1000;
1003 }
1004 #else
1005 fprintf(where,
1006 "Packet burst size is not compiled in. \n");
1007 #endif /* WANT_INTERVALS */
1008 }
1009 /* there is no ifdef here because we are sending this value to
1010 the remote, which may or may not have been compiled for
1011 intervals and we don't have a way of knowing on this side
1012 until we try */
1013 if (arg2[0]) {
1014 remote_interval_burst = convert(arg2);
1015 if (remote_interval_usecs == 0) {
1016 remote_interval_usecs = 1000;
1017 }
1018 }
1019 break;
1020 case 'B':
1021 result_brand = malloc(strlen(optarg)+1);
1022 if (NULL != result_brand) {
1023 strcpy(result_brand,optarg);
1024 }
1025 else {
1026 fprintf(where,
1027 "Unable to malloc space for result brand\n");
1028 }
1029 break;
1030 case '4':
1031 address_family = AF_INET;
1032 local_address_family = AF_INET;
1033 break;
1034 case '6':
1035 #if defined(AF_INET6)
1036 address_family = AF_INET6;
1037 local_address_family = AF_INET6;
1038 #else
1039 printf("This netperf was not compiled on an IPv6 capable system!\n");
1040 exit(-1);
1041 #endif
1042 break;
1043 case 'V':
1044 printf("Netperf version %s\n",NETPERF_VERSION);
1045 exit(0);
1046 break;
1047 };
1048 }
1049 /* ok, what should our default hostname and local binding info be?
1050 */
1051
1052 if ('\0' == host_name[0]) {
1053 /* host_name was not set */
1054 switch (address_family) {
1055 case AF_INET:
1056 #if defined(AF_RDS)
1057 case AF_RDS:
1058 #endif
1059 strcpy(host_name,"localhost");
1060 break;
1061 case AF_UNSPEC:
1062 /* what to do here? case it off the local_address_family I
1063 suppose */
1064 switch (local_address_family) {
1065 case AF_INET:
1066 case AF_UNSPEC:
1067 #if defined(AF_RDS)
1068 case AF_RDS:
1069 #endif
1070 strcpy(host_name,"localhost");
1071 break;
1072 #if defined(AF_INET6)
1073 case AF_INET6:
1074 strcpy(host_name,"::1");
1075 break;
1076 #endif
1077 default:
1078 printf("Netperf does not understand %d as an address family\n",
1079 address_family);
1080 exit(-1);
1081 }
1082 break;
1083 #if defined(AF_INET6)
1084 case AF_INET6:
1085 strcpy(host_name,"::1");
1086 break;
1087 #endif
1088 default:
1089 printf("Netperf does not understand %d as an address family\n",
1090 address_family);
1091 exit(-1);
1092 }
1093 } else {
1094 /* resolve the hostname and pull the address family from the
1095 addrinfo */
1096 struct addrinfo *ai;
1097
1098 ai = resolve_host(host_name, NULL, address_family);
1099 if (!ai) {
1100 printf("Netperf could not resolve %s as a host name\n", host_name);
1101 exit(-1);
1102 }
1103 address_family = ai->ai_family;
1104 freeaddrinfo(ai);
1105 }
1106
1107
1108 /* now, having established the name to which the control will
1109 connect, from what should it come? */
1110 if ('\0' == local_host_name[0]) {
1111 switch (local_address_family) {
1112 case AF_INET:
1113 #if defined(AF_RDS)
1114 case AF_RDS:
1115 #endif
1116 strcpy(local_host_name,"0.0.0.0");
1117 break;
1118 case AF_UNSPEC:
1119 switch (address_family) {
1120 case AF_INET:
1121 case AF_UNSPEC:
1122 #if defined(AF_RDS)
1123 case AF_RDS:
1124 #endif
1125 strcpy(local_host_name,"0.0.0.0");
1126 break;
1127 #if defined(AF_INET6)
1128 case AF_INET6:
1129 strcpy(local_host_name,"::0");
1130 break;
1131 #endif
1132 default:
1133 printf("Netperf does not understand %d as an address family\n",
1134 address_family);
1135 exit(-1);
1136 }
1137 break;
1138 #if defined(AF_INET6)
1139 case AF_INET6:
1140 strcpy(local_host_name,"::0");
1141 break;
1142 #endif
1143 default:
1144 printf("Netperf does not understand %d as an address family\n",
1145 address_family);
1146 exit(-1);
1147 }
1148 }
1149
1150 /* so, if we aren't even going to establish a control connection we
1151 should set certain "remote" settings to reflect this, regardless
1152 of what else may have been set on the command line */
1153 if (no_control) {
1154 remote_socket_prio = -1;
1155 remote_socket_tos = -1;
1156 remote_recv_align = -1;
1157 remote_send_align = -1;
1158 remote_send_offset = -1;
1159 remote_recv_offset = -1;
1160 remote_cpu_rate = (float)-1.0;
1161 remote_cpu_usage = 0;
1162 }
1163
1164 /* parsing test-specific options used to be conditional on there
1165 being a "--" in the option stream. however, some of the tests
1166 have other initialization happening in their "scan" routines so
1167 we want to call them regardless. raj 2005-02-08 */
1168 /* while the parsing of the command line will upshift the test name,
1169 since we don't know that there will always be a way to do so? we
1170 will retain for now the strcasecmp calls rather than switch to
1171 strcmp. raj 20101220 */
1172 if (
1173 #ifndef WANT_MIGRATION
1174 (strcasecmp(test_name,"TCP_STREAM") == 0) ||
1175 (strcasecmp(test_name,"TCP_MAERTS") == 0) ||
1176 (strcasecmp(test_name,"TCP_RR") == 0) ||
1177 (strcasecmp(test_name,"TCP_CRR") == 0) ||
1178 (strcasecmp(test_name,"UDP_STREAM") == 0) ||
1179 (strcasecmp(test_name,"UDP_RR") == 0) ||
1180 #endif
1181 #ifdef HAVE_ICSC_EXS
1182 (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
1183 #endif /* HAVE_ICSC_EXS */
1184 #ifdef HAVE_SENDFILE
1185 (strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
1186 #endif /* HAVE_SENDFILE */
1187 (strcasecmp(test_name,"TCP_CC") == 0) ||
1188 (strcasecmp(test_name,"TCP_MSS") == 0) ||
1189 #ifdef DO_1644
1190 (strcasecmp(test_name,"TCP_TRR") == 0) ||
1191 #endif /* DO_1644 */
1192 #ifdef DO_NBRR
1193 (strcasecmp(test_name,"TCP_TRR") == 0) ||
1194 #endif /* DO_NBRR */
1195 (0))
1196 {
1197 scan_sockets_args(argc, argv);
1198 }
1199
1200 #ifdef WANT_DLPI
1201 else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
1202 (strcasecmp(test_name,"DLCL_RR") == 0) ||
1203 (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
1204 (strcasecmp(test_name,"DLCL_STREAM") == 0))
1205 {
1206 scan_dlpi_args(argc, argv);
1207 }
1208 #endif /* WANT_DLPI */
1209
1210 #ifdef WANT_UNIX
1211 else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
1212 (strcasecmp(test_name,"DG_RR") == 0) ||
1213 (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
1214 (strcasecmp(test_name,"DG_STREAM") == 0))
1215 {
1216 scan_unix_args(argc, argv);
1217 }
1218 #endif /* WANT_UNIX */
1219
1220 #ifdef WANT_XTI
1221 else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
1222 (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
1223 (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
1224 (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
1225 {
1226 scan_xti_args(argc, argv);
1227 }
1228 #endif /* WANT_XTI */
1229
1230 #ifdef WANT_SCTP
1231 else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
1232 (strcasecmp(test_name,"SCTP_RR") == 0) ||
1233 (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
1234 (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
1235 {
1236 scan_sctp_args(argc, argv);
1237 }
1238 #endif
1239
1240 #ifdef WANT_SDP
1241 else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
1242 (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
1243 (strcasecmp(test_name,"SDP_RR") == 0))
1244 {
1245 scan_sdp_args(argc, argv);
1246 }
1247 #endif
1248
1249 #ifdef WANT_OMNI
1250 else if ((strcasecmp(test_name,"OMNI") == 0) ||
1251 #ifdef WANT_MIGRATION
1252 (strcasecmp(test_name,"TCP_STREAM") == 0) ||
1253 (strcasecmp(test_name,"TCP_MAERTS") == 0) ||
1254 (strcasecmp(test_name,"TCP_RR") == 0) ||
1255 (strcasecmp(test_name,"TCP_CRR") == 0) ||
1256 (strcasecmp(test_name,"UDP_STREAM") == 0) ||
1257 (strcasecmp(test_name,"UDP_RR") == 0) ||
1258 #endif
1259 (strcasecmp(test_name,"UUID") == 0)) {
1260 scan_omni_args(argc, argv);
1261 }
1262 #endif
1263
1264 /* what is our default value for the output units? if the test
1265 name contains "RR" or "rr" or "Rr" or "rR" then the default is
1266 'x' for transactions. otherwise it is 'm' for megabits (10^6)
1267 however... if this is an "omni" test then we want to defer
1268 this decision to scan_omni_args */
1269
1270 if (strcasecmp(test_name,"omni")) {
1271 if ('?' == libfmt) {
1272 /* we use a series of strstr's here because not everyone has
1273 strcasestr and I don't feel like up or downshifting text */
1274 if ((strstr(test_name,"RR")) ||
1275 (strstr(test_name,"rr")) ||
1276 (strstr(test_name,"Rr")) ||
1277 (strstr(test_name,"rR"))) {
1278 libfmt = 'x';
1279 }
1280 else {
1281 libfmt = 'm';
1282 }
1283 }
1284 else if ('x' == libfmt) {
1285 /* now, a format of 'x' makes no sense for anything other than
1286 an RR test. if someone has been silly enough to try to set
1287 that, we will reset it silently to default - namely 'm' */
1288 if ((strstr(test_name,"RR") == NULL) &&
1289 (strstr(test_name,"rr") == NULL) &&
1290 (strstr(test_name,"Rr") == NULL) &&
1291 (strstr(test_name,"rR") == NULL)) {
1292 libfmt = 'm';
1293 }
1294 }
1295 }
1296 }
1297
1298
1299 void
dump_globals()1300 dump_globals()
1301 {
1302 printf("Program name: %s\n", program);
1303 printf("Local send alignment: %d\n",local_send_align);
1304 printf("Local recv alignment: %d\n",local_recv_align);
1305 printf("Remote send alignment: %d\n",remote_send_align);
1306 printf("Remote recv alignment: %d\n",remote_recv_align);
1307 printf("Local socket priority: %d\n", local_socket_prio);
1308 printf("Remote socket priority: %d\n", remote_socket_prio);
1309 printf("Local socket TOS: %s\n", iptos2str(local_socket_tos));
1310 printf("Remote socket TOS: %s\n", iptos2str(remote_socket_tos));
1311 printf("Report local CPU %d\n",local_cpu_usage);
1312 printf("Report remote CPU %d\n",remote_cpu_usage);
1313 printf("Verbosity: %d\n",verbosity);
1314 printf("Debug: %d\n",debug);
1315 printf("Port: %s\n",test_port);
1316 printf("Test name: %s\n",test_name);
1317 printf("Test bytes: %d Test time: %d Test trans: %d\n",
1318 test_bytes,
1319 test_time,
1320 test_trans);
1321 printf("Host name: %s\n",host_name);
1322 printf("\n");
1323 }
1324