1#include "netperf_version.h"
2
3char	netsh_id[]="\
4@(#)netsh.c (c) Copyright 1993-2007 Hewlett-Packard Company. Version 2.4.3pre";
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 <sys/types.h>
18#ifndef WIN32
19#include <unistd.h>
20#ifndef __VMS
21#include <sys/ipc.h>
22#endif /* __VMS */
23#endif /* WIN32 */
24#include <fcntl.h>
25#ifndef WIN32
26#include <errno.h>
27#include <signal.h>
28#endif  /* !WIN32 */
29#include <stdio.h>
30#include <stdlib.h>
31#include <ctype.h>
32 /* the following four includes should not be needed ?*/
33#ifndef WIN32
34#include <sys/time.h>
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <netdb.h>
38#else
39#include <time.h>
40#include <winsock2.h>
41#define netperf_socklen_t socklen_t
42#endif
43
44#ifndef STRINGS
45#include <string.h>
46#else /* STRINGS */
47#include <strings.h>
48#endif /* STRINGS */
49
50#ifdef WIN32
51extern	int	getopt(int , char **, char *) ;
52#else
53double atof(const char *);
54#endif /* WIN32 */
55
56/**********************************************************************/
57/*                                                                    */
58/*          Local Include Files                                       */
59/*                                                                    */
60/**********************************************************************/
61
62#define  NETSH
63#include "netsh.h"
64#include "netlib.h"
65#include "nettest_bsd.h"
66
67#ifdef WANT_UNIX
68#include "nettest_unix.h"
69#ifndef WIN32
70#include "sys/socket.h"
71#endif  /* !WIN32 */
72#endif /* WANT_UNIX */
73
74#ifdef WANT_XTI
75#include "nettest_xti.h"
76#endif /* WANT_XTI */
77
78#ifdef WANT_DLPI
79#include "nettest_dlpi.h"
80#endif /* WANT_DLPI */
81
82#ifdef WANT_SCTP
83#include "nettest_sctp.h"
84#endif
85
86
87/************************************************************************/
88/*									*/
89/*	Global constants  and macros					*/
90/*									*/
91/************************************************************************/
92
93 /* Some of the args take optional parameters. Since we are using */
94 /* getopt to parse the command line, we will tell getopt that they do */
95 /* not take parms, and then look for them ourselves */
96#define GLOBAL_CMD_LINE_ARGS "A:a:b:B:CcdDf:F:H:hi:I:k:K:l:L:n:NO:o:P:p:rt:T:v:VW:w:46"
97
98/************************************************************************/
99/*									*/
100/*	Extern variables 						*/
101/*									*/
102/************************************************************************/
103
104/*
105extern int errno;
106extern char *sys_errlist[ ];
107extern int sys_nerr;
108*/
109
110/************************************************************************/
111/*									*/
112/*	Global variables 						*/
113/*									*/
114/************************************************************************/
115
116/* some names and such                                                  */
117char	*program;		/* program invocation name		*/
118char	username[BUFSIZ];	/* login name of user			*/
119char	cmd_file[BUFSIZ];	/* name of the commands file		*/
120
121/* stuff to say where this test is going                                */
122char	host_name[HOSTNAMESIZE];	/* remote host name or ip addr  */
123char    local_host_name[HOSTNAMESIZE];  /* local hostname or ip */
124char    test_name[BUFSIZ];		/* which test to run 		*/
125char	test_port[PORTBUFSIZE];		/* where is the test waiting    */
126char    local_test_port[PORTBUFSIZE];   /* from whence we should start */
127int     address_family;                 /* which address family remote */
128int     local_address_family;           /* which address family local */
129
130/* the source of data for filling the buffers */
131char    fill_file[BUFSIZ];
132
133/* output controlling variables                                         */
134int
135  debug,			/* debugging level */
136  print_headers,		/* do/don't display headers */
137  verbosity;		/* verbosity level */
138
139/* When specified with -B, this will be displayed at the end of the line
140   for output that does not include the test header.  mostly this is
141   to help identify a specific netperf result when concurrent netperfs
142   are run. raj 2006-02-01 */
143char *result_brand = NULL;
144
145/* cpu variables */
146int
147  local_cpu_usage,	/* you guessed it			*/
148  remote_cpu_usage;	/* still right !			*/
149
150float
151  local_cpu_rate,
152  remote_cpu_rate;
153
154int
155  shell_num_cpus=1;
156
157/* the end-test conditions for the tests - either transactions, bytes,  */
158/* or time. different vars used for clarity - space is cheap ;-)        */
159int
160  test_time,		/* test ends by time			*/
161  test_len_ticks,       /* how many times will the timer go off before */
162			/* the test is over? */
163  test_bytes,		/* test ends on byte count		*/
164  test_trans;		/* test ends on tran count		*/
165
166/* the alignment conditions for the tests				*/
167int
168  local_recv_align,	/* alignment for local receives		*/
169  local_send_align,	/* alignment for local sends		*/
170  local_send_offset = 0,
171  local_recv_offset = 0,
172  remote_recv_align,	/* alignment for remote receives	*/
173  remote_send_align,	/* alignment for remote sends		*/
174  remote_send_offset = 0,
175  remote_recv_offset = 0;
176
177#if defined(WANT_INTERVALS) || defined(WANT_DEMO)
178int
179  interval_usecs,
180  interval_wate,
181  interval_burst;
182
183int demo_mode;                    /* are we actually in demo mode? */
184double demo_interval = 1000000.0; /* what is the desired interval to
185				     display interval results. default
186				     is one second in units of
187				     microseconds */
188double demo_units = 0.0;          /* what is our current best guess as
189				     to how many work units must be
190				     done to be near the desired
191				     reporting interval? */
192
193double units_this_tick;
194#endif
195
196#ifdef DIRTY
197int	loc_dirty_count;
198int	loc_clean_count;
199int	rem_dirty_count;
200int	rem_clean_count;
201#endif /* DIRTY */
202
203 /* some of the vairables for confidence intervals... */
204
205int  confidence_level;
206int  iteration_min;
207int  iteration_max;
208int  result_confidence_only = 0;
209
210double interval;
211
212 /* stuff to control the "width" of the buffer rings for sending and */
213 /* receiving data */
214int	send_width;
215int     recv_width;
216
217/* address family */
218int	af = AF_INET;
219
220/* did someone request processor affinity? */
221int cpu_binding_requested = 0;
222
223/* are we not establishing a control connection? */
224int no_control = 0;
225
226char netserver_usage[] = "\n\
227Usage: netserver [options] \n\
228\n\
229Options:\n\
230    -h                Display this text\n\
231    -d                Increase debugging output\n\
232    -L name,family    Use name to pick listen address and family for family\n\
233    -p portnum        Listen for connect requests on portnum.\n\
234    -4                Do IPv4\n\
235    -6                Do IPv6\n\
236    -v verbosity      Specify the verbosity level\n\
237    -V                Display version information and exit\n\
238\n";
239
240/* netperf_usage done as two concatenated strings to make the MS
241   compiler happy when compiling for x86_32.  fix from Spencer
242   Frink.  */
243
244char netperf_usage1[] = "\n\
245Usage: netperf [global options] -- [test options] \n\
246\n\
247Global options:\n\
248    -a send,recv      Set the local send,recv buffer alignment\n\
249    -A send,recv      Set the remote send,recv buffer alignment\n\
250    -B brandstr       Specify a string to be emitted with brief output\n\
251    -c [cpu_rate]     Report local CPU usage\n\
252    -C [cpu_rate]     Report remote CPU usage\n\
253    -d                Increase debugging output\n\
254    -D [secs,units] * Display interim results at least every secs seconds\n\
255                      using units as the initial guess for units per second\n\
256    -f G|M|K|g|m|k    Set the output units\n\
257    -F fill_file      Pre-fill buffers with data from fill_file\n\
258    -h                Display this text\n\
259    -H name|ip,fam *  Specify the target machine and/or local ip and family\n\
260    -i max,min        Specify the max and min number of iterations (15,1)\n\
261    -I lvl[,intvl]    Specify confidence level (95 or 99) (99) \n\
262                      and confidence interval in percentage (10)\n\
263    -l testlen        Specify test duration (>0 secs) (<0 bytes|trans)\n\
264    -L name|ip,fam *  Specify the local ip|name and address family\n\
265    -o send,recv      Set the local send,recv buffer offsets\n\
266    -O send,recv      Set the remote send,recv buffer offset\n\
267    -n numcpu         Set the number of processors for CPU util\n\
268    -N                Establish no control connection, do 'send' side only\n\
269    -p port,lport*    Specify netserver port number and/or local port\n\
270    -P 0|1            Don't/Do display test headers\n\
271    -r                Allow confidence to be hit on result only\n\
272    -t testname       Specify test to perform\n\
273    -T lcpu,rcpu      Request netperf/netserver be bound to local/remote cpu\n\
274    -v verbosity      Specify the verbosity level\n\
275    -W send,recv      Set the number of send,recv buffers\n\
276    -v level          Set the verbosity level (default 1, min 0)\n\
277    -V                Display the netperf version and exit\n";
278
279char netperf_usage2[] = "\n\
280For those options taking two parms, at least one must be specified;\n\
281specifying one value without a comma will set both parms to that\n\
282value, specifying a value with a leading comma will set just the second\n\
283parm, a value with a trailing comma will set just the first. To set\n\
284each parm to unique values, specify both and separate them with a\n\
285comma.\n\
286\n"
287"* For these options taking two parms, specifying one value with no comma\n\
288will only set the first parms and will leave the second at the default\n\
289value. To set the second value it must be preceded with a comma or be a\n\
290comma-separated pair. This is to retain previous netperf behaviour.\n";
291
292
293/* This routine will return the two arguments to the calling routine. */
294/* If the second argument is not specified, and there is no comma, */
295/* then the value of the second argument will be the same as the */
296/* value of the first. If there is a comma, then the value of the */
297/* second argument will be the value of the second argument ;-) */
298void
299break_args(char *s, char *arg1, char *arg2)
300
301{
302  char *ns;
303  ns = strchr(s,',');
304  if (ns) {
305    /* there was a comma arg2 should be the second arg*/
306    *ns++ = '\0';
307    while ((*arg2++ = *ns++) != '\0');
308  }
309  else {
310    /* there was not a comma, we can use ns as a temp s */
311    /* and arg2 should be the same value as arg1 */
312    ns = s;
313    while ((*arg2++ = *ns++) != '\0');
314  };
315  while ((*arg1++ = *s++) != '\0');
316}
317
318/* break_args_explicit
319
320   this routine is somewhat like break_args in that it will separate a
321   pair of comma-separated values.  however, if there is no comma,
322   this version will not ass-u-me that arg2 should be the same as
323   arg1. raj 2005-02-04 */
324void
325break_args_explicit(char *s, char *arg1, char *arg2)
326
327{
328  char *ns;
329  ns = strchr(s,',');
330  if (ns) {
331    /* there was a comma arg2 should be the second arg*/
332    *ns++ = '\0';
333    while ((*arg2++ = *ns++) != '\0');
334  }
335  else {
336    /* there was not a comma, so we should make sure that arg2 is \0
337       lest something become confused. raj 2005-02-04 */
338    *arg2 = '\0';
339  };
340  while ((*arg1++ = *s++) != '\0');
341
342}
343
344/* given a string with possible values for setting an address family,
345   convert that into one of the AF_mumble values - AF_INET, AF_INET6,
346   AF_UNSPEC as apropriate. the family_string is compared in a
347   case-insensitive manner */
348
349int
350parse_address_family(char family_string[])
351{
352
353  char temp[10];  /* gotta love magic constants :) */
354
355  strncpy(temp,family_string,10);
356
357  if (debug) {
358    fprintf(where,
359	    "Attempting to parse address family from %s derived from %s\n",
360	    temp,
361	    family_string);
362  }
363#if defined(AF_INET6)
364  if (strstr(temp,"6")) {
365    return(AF_INET6);
366  }
367#endif
368  if (strstr(temp,"inet") ||
369      strstr(temp,"4")) {
370    return(AF_INET);
371  }
372  if (strstr(temp,"unspec") ||
373      strstr(temp,"0")) {
374    return(AF_UNSPEC);
375  }
376  fprintf(where,
377	  "WARNING! %s not recognized as an address family, using AF_UNPSEC\n",
378	  family_string);
379  fprintf(where,
380	  "Are you sure netperf was configured for that address family?\n");
381  fflush(where);
382  return(AF_UNSPEC);
383}
384
385
386void
387set_defaults()
388{
389
390  /* stuff to say where this test is going                              */
391  strcpy(host_name,"");	      /* remote host name or ip addr  */
392  strcpy(local_host_name,""); /* we want it to be INADDR_ANY */
393  strcpy(test_name,"TCP_STREAM");	/* which test to run 		*/
394  strncpy(test_port,"12865",PORTBUFSIZE); /* where is the test waiting    */
395  strncpy(local_test_port,"0",PORTBUFSIZE);/* INPORT_ANY as it were */
396  address_family = AF_UNSPEC;
397  local_address_family = AF_UNSPEC;
398
399  /* output controlling variables                               */
400  debug			= 0;/* debugging level			*/
401  print_headers		= 1;/* do print test headers		*/
402  verbosity		= 1;/* verbosity level			*/
403  /* cpu variables */
404  local_cpu_usage	= 0;/* measure local cpu		*/
405  remote_cpu_usage	= 0;/* what do you think ;-)		*/
406
407  local_cpu_rate	= (float)0.0;
408  remote_cpu_rate	= (float)0.0;
409
410  /* the end-test conditions for the tests - either transactions, bytes,  */
411  /* or time. different vars used for clarity - space is cheap ;-)        */
412  test_time	= 10;	/* test ends by time			*/
413  test_bytes	= 0;	/* test ends on byte count		*/
414  test_trans	= 0;	/* test ends on tran count		*/
415
416  /* the alignment conditions for the tests				*/
417  local_recv_align	= 8;	/* alignment for local receives	*/
418  local_send_align	= 8;	/* alignment for local sends	*/
419  remote_recv_align	= 8;	/* alignment for remote receives*/
420  remote_send_align	= 8;	/* alignment for remote sends	*/
421
422#ifdef WANT_INTERVALS
423  /* rate controlling stuff */
424  interval_usecs  = 0;
425  interval_wate   = 1;
426  interval_burst  = 0;
427#endif /* WANT_INTERVALS */
428
429#ifdef DIRTY
430  /* dirty and clean cache stuff */
431  loc_dirty_count = 0;
432  loc_clean_count = 0;
433  rem_dirty_count = 0;
434  rem_clean_count = 0;
435#endif /* DIRTY */
436
437 /* some of the vairables for confidence intervals... */
438
439  confidence_level = 99;
440  iteration_min = 1;
441  iteration_max = 1;
442  interval = 0.05; /* five percent? */
443
444  no_control = 0;
445  strcpy(fill_file,"");
446}
447
448
449void
450print_netserver_usage()
451{
452  fwrite(netserver_usage, sizeof(char), strlen(netserver_usage), stderr);
453}
454
455
456void
457print_netperf_usage()
458{
459  fwrite(netperf_usage1, sizeof(char), strlen(netperf_usage1),  stderr);
460  fwrite(netperf_usage2, sizeof(char), strlen(netperf_usage2),  stderr);
461}
462
463void
464scan_cmd_line(int argc, char *argv[])
465{
466  extern int	optind;           /* index of first unused arg 	*/
467  extern char	*optarg;	  /* pointer to option string	*/
468
469  int		c;
470
471  char	arg1[BUFSIZ],  /* argument holders		*/
472    arg2[BUFSIZ];
473
474  program = (char *)malloc(strlen(argv[0]) + 1);
475  if (program == NULL) {
476    printf("malloc(%zu) failed!\n", strlen(argv[0]) + 1);
477    exit(1);
478  }
479  strcpy(program, argv[0]);
480
481  /* Go through all the command line arguments and break them */
482  /* out. For those options that take two parms, specifying only */
483  /* the first will set both to that value. Specifying only the */
484  /* second will leave the first untouched. To change only the */
485  /* first, use the form first, (see the routine break_args.. */
486
487  while ((c= getopt(argc, argv, GLOBAL_CMD_LINE_ARGS)) != EOF) {
488    switch (c) {
489    case '?':
490    case 'h':
491      print_netperf_usage();
492      exit(1);
493    case 'a':
494      /* set local alignments */
495      break_args(optarg,arg1,arg2);
496      if (arg1[0]) {
497	local_send_align = convert(arg1);
498      }
499      if (arg2[0])
500	local_recv_align = convert(arg2);
501      break;
502    case 'A':
503      /* set remote alignments */
504      break_args(optarg,arg1,arg2);
505      if (arg1[0]) {
506	remote_send_align = convert(arg1);
507      }
508      if (arg2[0])
509	remote_recv_align = convert(arg2);
510      break;
511    case 'c':
512      /* measure local cpu usage please. the user */
513      /* may have specified the cpu rate as an */
514      /* optional parm */
515      if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
516	/* there was an optional parm */
517	local_cpu_rate = (float)atof(argv[optind]);
518	optind++;
519      }
520      local_cpu_usage++;
521      break;
522    case 'C':
523      /* measure remote cpu usage please */
524      if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
525	/* there was an optional parm */
526	remote_cpu_rate = (float)atof(argv[optind]);
527	optind++;
528      }
529      remote_cpu_usage++;
530      break;
531    case 'd':
532      debug++;
533      break;
534    case 'D':
535#if (defined WANT_DEMO)
536      demo_mode++;
537      if (argv[optind] && isdigit((unsigned char)argv[optind][0])){
538	/* there was an optional parm */
539	break_args_explicit(argv[optind],arg1,arg2);
540	optind++;
541	if (arg1[0]) {
542	  demo_interval = atof(arg1) * 1000000.0;
543	}
544	if (arg2[0]) {
545	  demo_units = convert(arg2);
546	}
547      }
548#else
549      printf("Sorry, Demo Mode not configured into this netperf.\n");
550      printf("please consider reconfiguring netperf with\n");
551      printf("--enable-demo=yes and recompiling\n");
552#endif
553      break;
554    case 'f':
555      /* set the thruput formatting */
556      libfmt = *optarg;
557      break;
558    case 'F':
559      /* set the fill_file variable for pre-filling buffers */
560      strcpy(fill_file,optarg);
561      break;
562    case 'i':
563      /* set the iterations min and max for confidence intervals */
564      break_args(optarg,arg1,arg2);
565      if (arg1[0]) {
566	iteration_max = convert(arg1);
567      }
568      if (arg2[0] ) {
569	iteration_min = convert(arg2);
570      }
571      /* if the iteration_max is < iteration_min make iteration_max
572	 equal iteration_min */
573      if (iteration_max < iteration_min) iteration_max = iteration_min;
574      /* limit minimum to 3 iterations */
575      if (iteration_max < 3) iteration_max = 3;
576      if (iteration_min < 3) iteration_min = 3;
577      /* limit maximum to 30 iterations */
578      if (iteration_max > 30) iteration_max = 30;
579      if (iteration_min > 30) iteration_min = 30;
580      break;
581    case 'I':
582      /* set the confidence level (95 or 99) and width */
583      break_args(optarg,arg1,arg2);
584      if (arg1[0]) {
585	confidence_level = convert(arg1);
586      }
587      if((confidence_level != 95) && (confidence_level != 99)){
588	printf("Only 95%% and 99%% confidence level is supported\n");
589	exit(1);
590      }
591      if (arg2[0] ) {
592	interval = (double) convert(arg2)/100;
593      }
594      /* make sure that iteration_min and iteration_max are at least
595	 at a reasonable default value.  if a -i option has previously
596	 been parsed, these will no longer be 1, so we can check
597	 against 1 */
598      if (iteration_min == 1) iteration_min = 3;
599      if (iteration_max == 1) iteration_max = 10;
600
601      break;
602    case 'k':
603      /* local dirty and clean counts */
604#ifdef DIRTY
605      break_args(optarg,arg1,arg2);
606      if (arg1[0]) {
607	loc_dirty_count = convert(arg1);
608      }
609      if (arg2[0] ) {
610	loc_clean_count = convert(arg2);
611      }
612#else
613      printf("I don't know how to get dirty.\n");
614#endif /* DIRTY */
615      break;
616    case 'K':
617      /* remote dirty and clean counts */
618#ifdef DIRTY
619      break_args(optarg,arg1,arg2);
620      if (arg1[0]) {
621	rem_dirty_count = convert(arg1);
622      }
623      if (arg2[0] ) {
624	rem_clean_count = convert(arg2);
625      }
626#else
627      printf("I don't know how to get dirty.\n");
628#endif /* DIRTY */
629      break;
630    case 'n':
631      shell_num_cpus = atoi(optarg);
632      break;
633    case 'N':
634      no_control = 1;
635      break;
636    case 'o':
637      /* set the local offsets */
638      break_args(optarg,arg1,arg2);
639      if (arg1[0])
640	local_send_offset = convert(arg1);
641      if (arg2[0])
642	local_recv_offset = convert(arg2);
643      break;
644    case 'O':
645      /* set the remote offsets */
646      break_args(optarg,arg1,arg2);
647      if (arg1[0])
648	remote_send_offset = convert(arg1);
649      if (arg2[0])
650	remote_recv_offset = convert(arg2);
651      break;
652    case 'P':
653      /* to print or not to print, that is */
654      /* the header question */
655      print_headers = convert(optarg);
656      break;
657    case 'r':
658      /* the user wishes that we declare confidence when hit on the
659	 result even if not yet reached on CPU utilization.  only
660	 meaningful if cpu util is enabled */
661      result_confidence_only = 1;
662      break;
663    case 't':
664      /* set the test name */
665      strcpy(test_name,optarg);
666      break;
667    case 'T':
668      /* We want to set the processor on which netserver or netperf */
669      /* will run */
670      break_args(optarg,arg1,arg2);
671      if (arg1[0]) {
672	local_proc_affinity = convert(arg1);
673	bind_to_specific_processor(local_proc_affinity,0);
674      }
675      if (arg2[0]) {
676	remote_proc_affinity = convert(arg2);
677      }
678      cpu_binding_requested = 1;
679      break;
680    case 'W':
681      /* set the "width" of the user space data buffer ring. This will */
682      /* be the number of send_size buffers malloc'd in the tests */
683      break_args(optarg,arg1,arg2);
684      if (arg1[0])
685	send_width = convert(arg1);
686      if (arg2[0])
687	recv_width = convert(arg2);
688      break;
689    case 'l':
690      /* determine test end conditions */
691      /* assume a timed test */
692      test_time = convert(optarg);
693      test_bytes = test_trans = 0;
694      if (test_time < 0) {
695	test_bytes = -1 * test_time;
696	test_trans = test_bytes;
697	test_time = 0;
698      }
699      break;
700    case 'v':
701      /* say how much to say */
702      verbosity = convert(optarg);
703      break;
704    case 'p':
705      /* specify an alternate port number we use break_args_explicit
706	 here to maintain backwards compatibility with previous
707	 generations of netperf where having a single value did not
708	 set both remote _and_ local port number. raj 2005-02-04 */
709      break_args_explicit(optarg,arg1,arg2);
710      if (arg1[0])
711	strncpy(test_port,arg1,PORTBUFSIZE);
712      if (arg2[0])
713	strncpy(local_test_port,arg2,PORTBUFSIZE);
714      break;
715    case 'H':
716      /* save-off the host identifying information, use
717	 break_args_explicit since passing just one value should not
718	 set both */
719      break_args_explicit(optarg,arg1,arg2);
720      if (arg1[0])
721	strncpy(host_name,arg1,sizeof(host_name));
722      if (arg2[0])
723	address_family = parse_address_family(arg2);
724      break;
725    case 'L':
726      /* save-off the local control socket addressing information. use
727	 break_args_explicit since passing just one value should not
728	 set both */
729      break_args_explicit(optarg,arg1,arg2);
730      if (arg1[0])
731	strncpy(local_host_name,arg1,sizeof(local_host_name));
732      if (arg2[0])
733	local_address_family = parse_address_family(arg2);
734      break;
735    case 'w':
736      /* We want to send requests at a certain wate. */
737      /* Remember that there are 1000000 usecs in a */
738      /* second, and that the packet rate is */
739      /* expressed in packets per millisecond. */
740#ifdef WANT_INTERVALS
741      interval_usecs = convert_timespec(optarg);
742      interval_wate  = interval_usecs / 1000;
743#else
744      fprintf(where,
745	      "Packet rate control is not compiled in.\n");
746#endif
747      break;
748    case 'b':
749      /* we want to have a burst so many packets per */
750      /* interval. */
751#ifdef WANT_INTERVALS
752      interval_burst = convert(optarg);
753#else
754      fprintf(where,
755	      "Packet burst size is not compiled in. \n");
756#endif /* WANT_INTERVALS */
757      break;
758    case 'B':
759      result_brand = malloc(strlen(optarg)+1);
760      if (NULL != result_brand) {
761	strcpy(result_brand,optarg);
762      }
763      else {
764	fprintf(where,
765		"Unable to malloc space for result brand\n");
766      }
767      break;
768    case '4':
769      address_family = AF_INET;
770      local_address_family = AF_INET;
771      break;
772    case '6':
773#if defined(AF_INET6)
774      address_family = AF_INET6;
775      local_address_family = AF_INET6;
776#else
777      printf("This netperf was not compiled on an IPv6 capable system!\n");
778      exit(-1);
779#endif
780      break;
781    case 'V':
782      printf("Netperf version %s\n",NETPERF_VERSION);
783      exit(0);
784      break;
785    };
786  }
787  /* ok, what should our default hostname and local binding info be?
788   */
789  if ('\0' == host_name[0]) {
790    /* host_name was not set */
791    switch (address_family) {
792    case AF_INET:
793      strcpy(host_name,"localhost");
794      break;
795    case AF_UNSPEC:
796      /* what to do here? case it off the local_address_family I
797	 suppose */
798      switch (local_address_family) {
799      case AF_INET:
800      case AF_UNSPEC:
801	strcpy(host_name,"localhost");
802	break;
803#if defined(AF_INET6)
804      case AF_INET6:
805	strcpy(host_name,"::1");
806	break;
807#endif
808      default:
809	printf("Netperf does not understand %d as an address family\n",
810	       address_family);
811	exit(-1);
812      }
813      break;
814#if defined(AF_INET6)
815    case AF_INET6:
816      strcpy(host_name,"::1");
817      break;
818#endif
819    default:
820      printf("Netperf does not understand %d as an address family\n",
821	     address_family);
822      exit(-1);
823    }
824  }
825
826  /* now, having established the name to which the control will
827     connect, from what should it come? */
828  if ('\0' == local_host_name[0]) {
829    switch (local_address_family) {
830    case AF_INET:
831      strcpy(local_host_name,"0.0.0.0");
832      break;
833    case AF_UNSPEC:
834      switch (address_family) {
835      case AF_INET:
836      case AF_UNSPEC:
837	strcpy(local_host_name,"0.0.0.0");
838	break;
839#if defined(AF_INET6)
840      case AF_INET6:
841	strcpy(local_host_name,"::0");
842	break;
843#endif
844      default:
845	printf("Netperf does not understand %d as an address family\n",
846	       address_family);
847	exit(-1);
848      }
849      break;
850#if defined(AF_INET6)
851    case AF_INET6:
852      strcpy(local_host_name,"::0");
853      break;
854#endif
855    default:
856      printf("Netperf does not understand %d as an address family\n",
857	     address_family);
858      exit(-1);
859    }
860  }
861
862  /* so, if we aren't even going to establish a control connection we
863     should set certain "remote" settings to reflect this, regardless
864     of what else may have been set on the command line */
865  if (no_control) {
866    remote_recv_align = -1;
867    remote_send_align = -1;
868    remote_send_offset = -1;
869    remote_recv_offset = -1;
870    remote_cpu_rate = (float)-1.0;
871    remote_cpu_usage = 0;
872  }
873
874  /* parsing test-specific options used to be conditional on there
875    being a "--" in the option stream.  however, some of the tests
876    have other initialization happening in their "scan" routines so we
877    want to call them regardless. raj 2005-02-08 */
878    if ((strcasecmp(test_name,"TCP_STREAM") == 0) ||
879#ifdef HAVE_ICSC_EXS
880    (strcasecmp(test_name,"EXS_TCP_STREAM") == 0) ||
881#endif /* HAVE_ICSC_EXS */
882#ifdef HAVE_SENDFILE
883	(strcasecmp(test_name,"TCP_SENDFILE") == 0) ||
884#endif /* HAVE_SENDFILE */
885	(strcasecmp(test_name,"TCP_MAERTS") == 0) ||
886	(strcasecmp(test_name,"TCP_RR") == 0) ||
887	(strcasecmp(test_name,"TCP_CRR") == 0) ||
888	(strcasecmp(test_name,"TCP_CC") == 0) ||
889#ifdef DO_1644
890	(strcasecmp(test_name,"TCP_TRR") == 0) ||
891#endif /* DO_1644 */
892#ifdef DO_NBRR
893	(strcasecmp(test_name,"TCP_TRR") == 0) ||
894#endif /* DO_NBRR */
895	(strcasecmp(test_name,"UDP_STREAM") == 0) ||
896	(strcasecmp(test_name,"UDP_RR") == 0))
897      {
898	scan_sockets_args(argc, argv);
899      }
900
901#ifdef WANT_DLPI
902    else if ((strcasecmp(test_name,"DLCO_RR") == 0) ||
903	     (strcasecmp(test_name,"DLCL_RR") == 0) ||
904	     (strcasecmp(test_name,"DLCO_STREAM") == 0) ||
905	     (strcasecmp(test_name,"DLCL_STREAM") == 0))
906      {
907	scan_dlpi_args(argc, argv);
908      }
909#endif /* WANT_DLPI */
910
911#ifdef WANT_UNIX
912    else if ((strcasecmp(test_name,"STREAM_RR") == 0) ||
913	     (strcasecmp(test_name,"DG_RR") == 0) ||
914	     (strcasecmp(test_name,"STREAM_STREAM") == 0) ||
915	     (strcasecmp(test_name,"DG_STREAM") == 0))
916      {
917	scan_unix_args(argc, argv);
918      }
919#endif /* WANT_UNIX */
920
921#ifdef WANT_XTI
922    else if ((strcasecmp(test_name,"XTI_TCP_RR") == 0) ||
923	     (strcasecmp(test_name,"XTI_TCP_STREAM") == 0) ||
924	     (strcasecmp(test_name,"XTI_UDP_RR") == 0) ||
925	     (strcasecmp(test_name,"XTI_UDP_STREAM") == 0))
926      {
927	scan_xti_args(argc, argv);
928      }
929#endif /* WANT_XTI */
930
931#ifdef WANT_SCTP
932    else if ((strcasecmp(test_name,"SCTP_STREAM") == 0) ||
933	     (strcasecmp(test_name,"SCTP_RR") == 0) ||
934	     (strcasecmp(test_name,"SCTP_STREAM_MANY") == 0) ||
935	     (strcasecmp(test_name,"SCTP_RR_MANY") == 0))
936    {
937      scan_sctp_args(argc, argv);
938    }
939#endif
940
941#ifdef WANT_SDP
942    else if((strcasecmp(test_name,"SDP_STREAM") == 0) ||
943	    (strcasecmp(test_name,"SDP_MAERTS") == 0) ||
944	    (strcasecmp(test_name,"SDP_RR") == 0))
945      {
946	scan_sdp_args(argc, argv);
947      }
948#endif
949
950    /* what is our default value for the output units?  if the test
951       name contains "RR" or "rr" or "Rr" or "rR" then the default is
952       'x' for transactions. otherwise it is 'm' for megabits
953       (10^6) */
954
955    if ('?' == libfmt) {
956      /* we use a series of strstr's here because not everyone has
957	 strcasestr and I don't feel like up or downshifting text */
958      if ((strstr(test_name,"RR")) ||
959	  (strstr(test_name,"rr")) ||
960	  (strstr(test_name,"Rr")) ||
961	  (strstr(test_name,"rR"))) {
962	libfmt = 'x';
963      }
964      else {
965	libfmt = 'm';
966      }
967    }
968    else if ('x' == libfmt) {
969      /* now, a format of 'x' makes no sense for anything other than
970	 an RR test. if someone has been silly enough to try to set
971	 that, we will reset it silently to default - namely 'm' */
972      if ((strstr(test_name,"RR") == NULL) &&
973	  (strstr(test_name,"rr") == NULL) &&
974	  (strstr(test_name,"Rr") == NULL) &&
975	  (strstr(test_name,"rR") == NULL)) {
976	libfmt = 'm';
977      }
978    }
979}
980
981
982void
983dump_globals()
984{
985  printf("Program name: %s\n", program);
986  printf("Local send alignment: %d\n",local_send_align);
987  printf("Local recv alignment: %d\n",local_recv_align);
988  printf("Remote send alignment: %d\n",remote_send_align);
989  printf("Remote recv alignment: %d\n",remote_recv_align);
990  printf("Report local CPU %d\n",local_cpu_usage);
991  printf("Report remote CPU %d\n",remote_cpu_usage);
992  printf("Verbosity: %d\n",verbosity);
993  printf("Debug: %d\n",debug);
994  printf("Port: %s\n",test_port);
995  printf("Test name: %s\n",test_name);
996  printf("Test bytes: %d Test time: %d Test trans: %d\n",
997	 test_bytes,
998	 test_time,
999	 test_trans);
1000  printf("Host name: %s\n",host_name);
1001  printf("\n");
1002}
1003