• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 
5 #ifdef WANT_OMNI
6 char nettest_omni_id[]="\
7 @(#)nettest_omni.c (c) Copyright 2008-2012 Hewlett-Packard Co. Version 2.6.0";
8 
9 #include <stdio.h>
10 #if HAVE_SYS_TYPES_H
11 # include <sys/types.h>
12 #endif
13 #if HAVE_SYS_STAT_H
14 # include <sys/stat.h>
15 #endif
16 #if STDC_HEADERS
17 # include <stdlib.h>
18 # include <stddef.h>
19 #else
20 # if HAVE_STDLIB_H
21 #  include <stdlib.h>
22 # endif
23 #endif
24 #if HAVE_STRING_H
25 # if !STDC_HEADERS && HAVE_MEMORY_H
26 #  include <memory.h>
27 # endif
28 # include <string.h>
29 #endif
30 #if HAVE_STRINGS_H
31 # include <strings.h>
32 #endif
33 #if HAVE_INTTYPES_H
34 # include <inttypes.h>
35 #else
36 # if HAVE_STDINT_H
37 #  include <stdint.h>
38 # endif
39 #endif
40 #if HAVE_UNISTD_H
41 # include <unistd.h>
42 #endif
43 #if HAVE_SYS_IOCTL_H
44 # include <sys/ioctl.h>
45 #endif
46 #if HAVE_SCHED_H
47 # include <sched.h>
48 #endif
49 
50 #include <fcntl.h>
51 #ifndef WIN32
52 #include <errno.h>
53 #include <signal.h>
54 #endif
55 
56 #if TIME_WITH_SYS_TIME
57 # include <sys/time.h>
58 # include <time.h>
59 #else
60 # if HAVE_SYS_TIME_H
61 #  include <sys/time.h>
62 # else
63 #  include <time.h>
64 # endif
65 #endif
66 
67 #include <ctype.h>
68 
69 #ifdef NOSTDLIBH
70 #include <malloc.h>
71 #endif /* NOSTDLIBH */
72 
73 #include <assert.h>
74 
75 #ifndef WIN32
76 #include <sys/socket.h>
77 #include <netinet/in.h>
78 
79 /* it would seem that including both <netinet/tcp.h> and <linux/tcp.h>
80    is not a path to happiness and joy when one wishes to grab tcp_info
81    stats and not get something like the compiler complaining about
82    either redefinitions, or missing tcpi_total_retrans. */
83 #ifdef HAVE_LINUX_TCP_H
84 #include <linux/tcp.h>
85 #else
86 #include <netinet/tcp.h>
87 #endif
88 
89 /* this is to get us the definition of MSG_FASTOPEN. we may need to
90    cheat just a litle at first */
91 #ifdef HAVE_LINUX_SOCKET_H
92 # include <linux/socket.h>
93 # ifndef MSG_FASTOPEN
94 #  warning Using our own value for MSG_FASTOPEN
95 #  define MSG_FASTOPEN	0x20000000	/* Send data in TCP SYN */
96 # endif
97 # ifndef TCP_FASTOPEN
98 #  warning Using our own value for TCP_FASTOPEN
99 #  define TCP_FASTOPEN 23
100 # endif
101 #endif
102 
103 #ifdef HAVE_NETINET_SCTP_H
104 #include <netinet/sctp.h>
105 #endif
106 
107 #include <arpa/inet.h>
108 #include <netdb.h>
109 #else /* WIN32 */
110 #include <process.h>
111 #define netperf_socklen_t socklen_t
112 #include <winsock2.h>
113 /* while it is unlikely that anyone running Windows 2000 or NT 4 is
114    going to be trying to compile this, if they are they will want to
115    define DONT_IPV6 in the sources file */
116 #ifndef DONT_IPV6
117 #include <ws2tcpip.h>
118 #endif
119 #include <windows.h>
120 
121 #define sleep(x) Sleep((x)*1000)
122 
123 #include "missing\stdint.h"
124 #endif /* WIN32 */
125 
126 /* We don't want to use bare constants in the shutdown() call.  In the
127    extremely unlikely event that SHUT_WR isn't defined, we will define
128    it to the value we used to be passing to shutdown() anyway.  raj
129    2007-02-08 */
130 #if !defined(SHUT_WR)
131 #define SHUT_WR 1
132 #endif
133 
134 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
135 # include "missing/getaddrinfo.h"
136 #endif
137 
138 #include "netlib.h"
139 #include "netsh.h"
140 #include "nettest_bsd.h"
141 
142 /* we only really use this once, but the initial patch to
143    src/nettest_bsd.c used it in several places. keep it as a macro
144    just for kicks and just in case we do end-up needing to use it
145    multiple times. */
146 
147 #define WAIT_BEFORE_DATA_TRAFFIC() \
148 { \
149   if (wait_time_secs) \
150     sleep(wait_time_secs); \
151 } \
152 
153 
154 /* since someone can ask for latency stats, we will always include
155    this and do the other other things */
156 #include "hist.h"
157 
158 static HIST time_hist;
159 
160 
161 
162 #ifdef WANT_INTERVALS
163 int interval_count;
164 unsigned int interval_wait_microseconds;
165 
166 /* hoist the timestamps up here so we can use them to factor-out the
167    time spent "waiting" */
168 /* first out timestamp */
169 #ifdef HAVE_GETHRTIME
170 static hrtime_t intvl_one;
171 static hrtime_t intvl_two;
172 static hrtime_t intvl_wait_start;
173 static hrtime_t *intvl_one_ptr = &intvl_one;
174 static hrtime_t *intvl_two_ptr = &intvl_two;
175 static hrtime_t *temp_intvl_ptr = &intvl_one;
176 #elif defined(WIN32)
177 static LARGE_INTEGER intvl_one;
178 static LARGE_INTEGER intvl_two;
179 static LARGE_INTEGER intvl_wait_start;
180 static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
181 static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
182 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
183 #else
184 static struct timeval intvl_one;
185 static struct timeval intvl_two;
186 static struct timeval intvl_wait_start;
187 static struct timeval *intvl_one_ptr = &intvl_one;
188 static struct timeval *intvl_two_ptr = &intvl_two;
189 static struct timeval *temp_intvl_ptr = &intvl_one;
190 #endif
191 
192 #ifndef WANT_SPIN
193 #ifdef WIN32
194 #define INTERVALS_INIT() \
195     if (interval_burst) { \
196       /* zero means that we never pause, so we never should need the \
197          interval timer. we used to use it for demo mode, but we deal \
198 	 with that with a variant on watching the clock rather than \
199 	 waiting for a timer. raj 2006-02-06 */ \
200       start_itimer(interval_wate); \
201     } \
202     interval_count = interval_burst; \
203     interval_wait_microseconds = 0;
204 #else
205 sigset_t signal_set;
206 #define INTERVALS_INIT() \
207     if (interval_burst) { \
208       /* zero means that we never pause, so we never should need the \
209          interval timer. we used to use it for demo mode, but we deal \
210 	 with that with a variant on watching the clock rather than \
211 	 waiting for a timer. raj 2006-02-06 */ \
212       start_itimer(interval_wate); \
213     } \
214     interval_count = interval_burst; \
215     interval_wait_microseconds = 0; \
216     /* get the signal set for the call to sigsuspend */ \
217     if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \
218       fprintf(where, \
219 	      "%s: unable to get sigmask errno %d\n", \
220 	      __FUNCTION__, \
221 	      errno); \
222       fflush(where); \
223       exit(1); \
224     }
225 #endif /* WIN32 */
226 
227 #ifdef WIN32
228 #define INTERVALS_WAIT() \
229       /* in this case, the interval count is the count-down counter \
230 	 to decide to sleep for a little bit */ \
231       if ((interval_burst) && (--interval_count == 0)) { \
232 	/* call WaitForSingleObject and wait for the interval timer to get us \
233 	   out */ \
234 	if (debug > 1) { \
235 	  fprintf(where,"about to suspend\n"); \
236 	  fflush(where); \
237 	} \
238         HIST_timestamp(&intvl_wait_start); \
239     if (WaitForSingleObject(WinTimer, INFINITE) != WAIT_OBJECT_0) { \
240         fprintf(where, "WaitForSingleObject failed (%d)\n", GetLastError()); \
241 	  fflush(where); \
242 	  exit(1); \
243 	} \
244         HIST_timestamp(&intvl_two); \
245         interval_wait_microseconds += \
246           delta_micro(&intvl_wait_start,&intvl_two); \
247 	interval_count = interval_burst; \
248       }
249 #else
250 #define INTERVALS_WAIT() \
251       /* in this case, the interval count is the count-down couter \
252 	 to decide to sleep for a little bit */ \
253       if ((interval_burst) && (--interval_count == 0)) { \
254 	/* call sigsuspend and wait for the interval timer to get us \
255 	   out */ \
256 	if (debug > 1) { \
257 	  fprintf(where,"about to suspend\n"); \
258 	  fflush(where); \
259 	} \
260         HIST_timestamp(&intvl_wait_start); \
261 	if (sigsuspend(&signal_set) == EFAULT) { \
262 	  fprintf(where, \
263 		  "%s: fault with sigsuspend.\n", \
264                   __FUNCTION__); \
265 	  fflush(where); \
266 	  exit(1); \
267 	} \
268         HIST_timestamp(&intvl_two); \
269         interval_wait_microseconds += \
270           delta_micro(&intvl_wait_start,&intvl_two); \
271 	interval_count = interval_burst; \
272       }
273 #endif /* WIN32 */
274 #else
275 
276 #define INTERVALS_INIT() \
277       if (interval_burst) { \
278 	HIST_timestamp(intvl_one_ptr); \
279       } \
280       interval_wait_microseconds = 0; \
281       interval_count = interval_burst; \
282 
283 #define INTERVALS_WAIT() \
284       /* in this case, the interval count is the count-down couter \
285 	 to decide to sleep for a little bit */ \
286       if ((interval_burst) && (--interval_count == 0)) { \
287 	/* spin and wait for the interval timer to get us \
288 	   out */ \
289 	if (debug > 1) { \
290 	  fprintf(where,"about to spin suspend\n"); \
291 	  fflush(where); \
292 	} \
293         \
294         HIST_timestamp(&intvl_wait_start); \
295         do { \
296           HIST_timestamp(intvl_two_ptr); } \
297         while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs); \
298         interval_wait_microseconds += \
299           delta_micro(&intvl_wait_start,&intvl_two); \
300 	temp_intvl_ptr = intvl_one_ptr; \
301 	intvl_one_ptr = intvl_two_ptr; \
302 	intvl_two_ptr = temp_intvl_ptr; \
303 	interval_count = interval_burst; \
304       }
305 #endif
306 #endif
307 
308 #define NETPERF_WAITALL 0x1
309 
310 extern void get_uuid_string(char *string, size_t size);
311 
312 /* a boatload of globals while I settle things out */
313 char *output_selection_spec = NULL;
314 
315 char test_uuid[38];
316 
317 double result_confid_pct = -1.0;
318 double loc_cpu_confid_pct = -1.0;
319 double rem_cpu_confid_pct = -1.0;
320 double interval_pct = -1.0;
321 
322 int protocol;
323 int direction;
324 int remote_send_size = -1;
325 int remote_recv_size = -1;
326 int remote_send_size_req = -1;
327 int remote_recv_size_req = -1;
328 int remote_use_sendfile;
329 
330 extern int loc_dirty_count;
331 extern int loc_clean_count;
332 extern int rem_dirty_count;
333 extern int rem_clean_count;
334 int remote_checksum_off;
335 int connection_test;
336 int dont_give_up = 0;
337 int use_fastopen = 0;
338 int use_write = 0;
339 int need_to_connect;
340 int need_connection;
341 int bytes_to_send;
342 double bytes_per_send;
343 int failed_sends;
344 int bytes_to_recv;
345 double bytes_per_recv;
346 int null_message_ok = 0;
347 
348 int was_legacy = 0;
349 int legacy = 0;
350 int implicit_direction = 0;
351 int explicit_data_address = 0;
352 int want_defer_accept = 0;
353 
354 uint64_t      trans_completed = 0;
355 int64_t       units_remaining;
356 uint64_t      bytes_sent = 0;
357 uint64_t      bytes_received = 0;
358 uint64_t      local_send_calls = 0;
359 uint64_t      local_receive_calls = 0;
360 uint64_t      remote_bytes_sent;
361 uint64_t      remote_bytes_received;
362 uint64_t      remote_send_calls;
363 uint64_t      remote_receive_calls;
364 double        bytes_xferd;
365 double        remote_bytes_xferd;
366 double        remote_bytes_per_recv;
367 double        remote_bytes_per_send;
368 float         elapsed_time;
369 float         local_cpu_utilization;
370 float	      local_service_demand;
371 float         remote_cpu_utilization;
372 float	      remote_service_demand;
373 double	      thruput;
374 double        local_send_thruput;
375 double        local_recv_thruput;
376 double        remote_send_thruput;
377 double        remote_recv_thruput;
378 
379 /* kludges for omni output */
380 double      elapsed_time_double;
381 double      local_service_demand_double;
382 double      remote_service_demand_double;
383 double      transaction_rate = 1.0;
384 double      rtt_latency = -1.0;
385 int32_t     transport_mss = -2;
386 int32_t     local_transport_retrans = -2;
387 int32_t     remote_transport_retrans = -2;
388 char        *deprecated_str = "Deprecated";
389 int         remote_interface_vendor = -2;
390 int         remote_interface_device = -2;
391 int         remote_interface_subvendor = -2;
392 int         remote_interface_subdevice = -2;
393 int         local_interface_vendor = -2;
394 int         local_interface_device = -2;
395 int         local_interface_subvendor = -2;
396 int         local_interface_subdevice = -2;
397 int         local_cpu_frequency = 0;
398 int         remote_cpu_frequency = 0;
399 
400 int         local_security_type_id;
401 int         local_security_enabled_num;
402 int         remote_security_type_id;
403 int         remote_security_enabled_num;
404 
405 char        local_cong_control[16] = "";
406 char        remote_cong_control[16] = "";
407 char        local_cong_control_req[16] = "";
408 char        remote_cong_control_req[16] = "";
409 
410 int         receive_timeout = -1;
411 
412 /* new statistics based on code diffs from Google, with raj's own
413    personal twist added to make them compatible with the omni
414    tests... 20100913 */
415 
416 /* min and max "latency" */
417 int         min_latency = -1, max_latency = -1;
418 /* the percentiles */
419 int         p50_latency = -1, p90_latency = -1, p99_latency = -1;
420 /* mean and stddev - while the mean is reduntant with the *_RR test we
421    keep it because it won't be for other tests */
422 double      mean_latency = -1.0, stddev_latency = -1.0;
423 
424 /* default to zero to avoid randomizing */
425 int local_mask_len = 0;
426 int remote_mask_len = 0;
427 
428 int printing_initialized = 0;
429 
430 char *sd_str;
431 char *thruput_format_str;
432 
433 char *socket_type_str;
434 char *protocol_str;
435 char *direction_str;
436 
437 extern int first_burst_size;
438 
439 int  parallel_connections = 1;
440 
441 static int socket_debug = 0;
442 
443 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun))
444 #include <sys/sendfile.h>
445 #endif /* HAVE_SENDFILE && (__linux || __sun) */
446 
447 static int confidence_iteration;
448 
449 static  int local_cpu_method;
450 static  int remote_cpu_method;
451 
452 /* these will control the width of port numbers we try to use in the */
453 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
454 static int client_port_min = 5000;
455 static int client_port_max = 65535;
456 
457  /* different options for the sockets				*/
458 
459 int
460   loc_nodelay,		/* don't/do use NODELAY	locally		*/
461   rem_nodelay,		/* don't/do use NODELAY remotely	*/
462   loc_sndavoid,		/* avoid send copies locally		*/
463   loc_rcvavoid,		/* avoid recv copies locally		*/
464   rem_sndavoid,		/* avoid send copies remotely		*/
465   rem_rcvavoid; 	/* avoid recv_copies remotely		*/
466 
467 extern int
468   loc_tcpcork,
469   rem_tcpcork,
470   local_connected,
471   remote_connected;
472 
473 enum netperf_output_type {
474   NETPERF_TYPE_UNKNOWN,
475   NETPERF_TYPE_UINT32,
476   NETPERF_TYPE_INT32,
477   NETPERF_TYPE_UINT64,
478   NETPERF_TYPE_INT64,
479   NETPERF_TYPE_CHAR,
480   NETPERF_TYPE_FLOAT,
481   NETPERF_TYPE_DOUBLE,
482 };
483 
484 /* you should add to this in the order in which they should appear in
485    the default csv (everything) output */
486 
487 enum netperf_output_name {
488   NETPERF_OUTPUT_UNKNOWN,
489   OUTPUT_NONE,
490   SOCKET_TYPE,
491   PROTOCOL,
492   DIRECTION,
493   ELAPSED_TIME,
494   THROUGHPUT,
495   THROUGHPUT_UNITS,
496   LSS_SIZE_REQ,
497   LSS_SIZE,
498   LSS_SIZE_END,
499   LSR_SIZE_REQ,
500   LSR_SIZE,
501   LSR_SIZE_END,
502   RSS_SIZE_REQ,
503   RSS_SIZE,
504   RSS_SIZE_END,
505   RSR_SIZE_REQ,
506   RSR_SIZE,
507   RSR_SIZE_END,
508   LOCAL_SEND_SIZE,
509   LOCAL_RECV_SIZE,
510   REMOTE_SEND_SIZE,
511   REMOTE_RECV_SIZE,
512   REQUEST_SIZE,
513   RESPONSE_SIZE,
514   LOCAL_CPU_UTIL,
515   LOCAL_CPU_PERCENT_USER,
516   LOCAL_CPU_PERCENT_SYSTEM,
517   LOCAL_CPU_PERCENT_IOWAIT,
518   LOCAL_CPU_PERCENT_IRQ,
519   LOCAL_CPU_PERCENT_SWINTR,
520   LOCAL_CPU_METHOD,
521   LOCAL_SD,
522   REMOTE_CPU_UTIL,
523   REMOTE_CPU_PERCENT_USER,
524   REMOTE_CPU_PERCENT_SYSTEM,
525   REMOTE_CPU_PERCENT_IOWAIT,
526   REMOTE_CPU_PERCENT_IRQ,
527   REMOTE_CPU_PERCENT_SWINTR,
528   REMOTE_CPU_METHOD,
529   REMOTE_SD,
530   SD_UNITS,
531   CONFIDENCE_LEVEL,
532   CONFIDENCE_INTERVAL,
533   CONFIDENCE_ITERATION,
534   THROUGHPUT_CONFID,
535   LOCAL_CPU_CONFID,
536   REMOTE_CPU_CONFID,
537   TRANSACTION_RATE,
538   RT_LATENCY,
539   BURST_SIZE,
540   LOCAL_TRANSPORT_RETRANS,
541   REMOTE_TRANSPORT_RETRANS,
542   TRANSPORT_MSS,
543   LOCAL_SEND_THROUGHPUT,
544   LOCAL_RECV_THROUGHPUT,
545   REMOTE_SEND_THROUGHPUT,
546   REMOTE_RECV_THROUGHPUT,
547   LOCAL_CPU_BIND,
548   LOCAL_CPU_COUNT,
549   LOCAL_CPU_PEAK_UTIL,
550   LOCAL_CPU_PEAK_ID,
551   LOCAL_CPU_MODEL,
552   LOCAL_CPU_FREQUENCY,
553   REMOTE_CPU_BIND,
554   REMOTE_CPU_COUNT,
555   REMOTE_CPU_PEAK_UTIL,
556   REMOTE_CPU_PEAK_ID,
557   REMOTE_CPU_MODEL,
558   REMOTE_CPU_FREQUENCY,
559   SOURCE_PORT,
560   SOURCE_ADDR,
561   SOURCE_FAMILY,
562   DEST_PORT,
563   DEST_ADDR,
564   DEST_FAMILY,
565   LOCAL_SEND_CALLS,
566   LOCAL_RECV_CALLS,
567   LOCAL_BYTES_PER_RECV,
568   LOCAL_BYTES_PER_SEND,
569   LOCAL_BYTES_SENT,
570   LOCAL_BYTES_RECVD,
571   LOCAL_BYTES_XFERD,
572   LOCAL_SEND_OFFSET,
573   LOCAL_RECV_OFFSET,
574   LOCAL_SEND_ALIGN,
575   LOCAL_RECV_ALIGN,
576   LOCAL_SEND_WIDTH,
577   LOCAL_RECV_WIDTH,
578   LOCAL_SEND_DIRTY_COUNT,
579   LOCAL_RECV_DIRTY_COUNT,
580   LOCAL_RECV_CLEAN_COUNT,
581   LOCAL_NODELAY,
582   LOCAL_CORK,
583   REMOTE_SEND_CALLS,
584   REMOTE_RECV_CALLS,
585   REMOTE_BYTES_PER_RECV,
586   REMOTE_BYTES_PER_SEND,
587   REMOTE_BYTES_SENT,
588   REMOTE_BYTES_RECVD,
589   REMOTE_BYTES_XFERD,
590   REMOTE_SEND_OFFSET,
591   REMOTE_RECV_OFFSET,
592   REMOTE_SEND_ALIGN,
593   REMOTE_RECV_ALIGN,
594   REMOTE_SEND_WIDTH,
595   REMOTE_RECV_WIDTH,
596   REMOTE_SEND_DIRTY_COUNT,
597   REMOTE_RECV_DIRTY_COUNT,
598   REMOTE_RECV_CLEAN_COUNT,
599   REMOTE_NODELAY,
600   REMOTE_CORK,
601   LOCAL_SYSNAME,
602   LOCAL_SYSTEM_MODEL,
603   LOCAL_RELEASE,
604   LOCAL_VERSION,
605   LOCAL_MACHINE,
606   REMOTE_SYSNAME,
607   REMOTE_SYSTEM_MODEL,
608   REMOTE_RELEASE,
609   REMOTE_VERSION,
610   REMOTE_MACHINE,
611   LOCAL_INTERFACE_NAME,
612   LOCAL_INTERFACE_VENDOR,
613   LOCAL_INTERFACE_DEVICE,
614   LOCAL_INTERFACE_SUBVENDOR,
615   LOCAL_INTERFACE_SUBDEVICE,
616   LOCAL_DRIVER_NAME,
617   LOCAL_DRIVER_VERSION,
618   LOCAL_DRIVER_FIRMWARE,
619   LOCAL_DRIVER_BUS,
620   LOCAL_INTERFACE_SLOT,
621   REMOTE_INTERFACE_NAME,
622   REMOTE_INTERFACE_VENDOR,
623   REMOTE_INTERFACE_DEVICE,
624   REMOTE_INTERFACE_SUBVENDOR,
625   REMOTE_INTERFACE_SUBDEVICE,
626   REMOTE_DRIVER_NAME,
627   REMOTE_DRIVER_VERSION,
628   REMOTE_DRIVER_FIRMWARE,
629   REMOTE_DRIVER_BUS,
630   REMOTE_INTERFACE_SLOT,
631   LOCAL_INTERVAL_USECS,
632   LOCAL_INTERVAL_BURST,
633   REMOTE_INTERVAL_USECS,
634   REMOTE_INTERVAL_BURST,
635   LOCAL_SECURITY_TYPE_ID,
636   LOCAL_SECURITY_TYPE,
637   LOCAL_SECURITY_ENABLED_NUM,
638   LOCAL_SECURITY_ENABLED,
639   LOCAL_SECURITY_SPECIFIC,
640   REMOTE_SECURITY_TYPE_ID,
641   REMOTE_SECURITY_TYPE,
642   REMOTE_SECURITY_ENABLED_NUM,
643   REMOTE_SECURITY_ENABLED,
644   REMOTE_SECURITY_SPECIFIC,
645   RESULT_BRAND,
646   UUID,
647   MIN_LATENCY,
648   MAX_LATENCY,
649   P50_LATENCY,
650   P90_LATENCY,
651   P99_LATENCY,
652   MEAN_LATENCY,
653   STDDEV_LATENCY,
654   LOCAL_SOCKET_PRIO,
655   REMOTE_SOCKET_PRIO,
656   LOCAL_SOCKET_TOS,
657   REMOTE_SOCKET_TOS,
658   LOCAL_CONG_CONTROL,
659   REMOTE_CONG_CONTROL,
660   LOCAL_FILL_FILE,
661   REMOTE_FILL_FILE,
662   COMMAND_LINE,    /* COMMAND_LINE should always be "last" */
663   OUTPUT_END,
664   NETPERF_OUTPUT_MAX
665 };
666 
667 /* flags for the output groups, lower 16 bits for remote, upper 16
668    bits for local */
669 
670 #define OMNI_WANT_REM_IFNAME  0X00000001
671 #define OMNI_WANT_LOC_IFNAME  0X00010000
672 #define OMNI_WANT_REM_IFSLOT  0X00000002
673 #define OMNI_WANT_LOC_IFSLOT  0X00020000
674 #define OMNI_WANT_REM_IFIDS   0X00000004
675 #define OMNI_WANT_LOC_IFIDS   0X00040000
676 #define OMNI_WANT_REM_DRVINFO 0X00000008
677 #define OMNI_WANT_LOC_DRVINFO 0X00080000
678 #define OMNI_WANT_STATS       0X00100010
679 #define OMNI_WANT_REM_CONG    0X00000020
680 #define OMNI_WANT_LOC_CONG    0X00200000
681 
682 unsigned int desired_output_groups = 0;
683 
684 typedef struct netperf_output_elt {
685   enum netperf_output_name output_name;  /* belt and suspenders */
686   int max_line_len; /* length of the longest of the "lines" */
687   int tot_line_len; /* total length of all lines, including spaces */
688   char *line[4];
689   char *format;        /* format to apply to value */
690   void *display_value; /* where to find the value */
691   enum netperf_output_type output_type; /* what type is the value? */
692   int  output_default; /* is it included in the default output */
693   unsigned int output_group; /* used to avoid some lookups */
694 } netperf_output_elt_t;
695 
696 netperf_output_elt_t netperf_output_source[NETPERF_OUTPUT_MAX];
697 
698 #define NETPERF_MAX_BLOCKS 4
699 
700 /* let us simply use one, two-dimensional list, and either use or some
701    of the additional dimension depending on the type of output we are
702    doing.  this should help simplify matters. raj 20110120 */
703 
704 enum netperf_output_name output_list[NETPERF_MAX_BLOCKS][NETPERF_OUTPUT_MAX];
705 
706 /* some things for setting the source IP address on outgoing UDP
707    sends. borrows liberally from
708    http://stackoverflow.com/questions/3062205/setting-the-source-ip-for-a-udp-socket */
709 
710 int want_use_pktinfo = 0;
711 int use_pktinfo = 0;
712 int have_pktinfo = 0;
713 #ifdef IP_PKTINFO
714 struct in_pktinfo in_pktinfo;
715 #endif
716 
direction_to_str(int direction)717 char *direction_to_str(int direction) {
718   if (NETPERF_RECV_ONLY(direction)) return "Receive";
719   if (NETPERF_XMIT_ONLY(direction)) return "Send";
720   if (NETPERF_CC(direction)) return "Connection";
721   else if (connection_test) {
722     return "Connect|Send|Recv";
723   }
724   else return "Send|Recv";
725 }
726 
727 static unsigned short
get_port_number(struct addrinfo * res)728 get_port_number(struct addrinfo *res)
729 {
730   switch(res->ai_family) {
731   case AF_INET: {
732     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
733     return(ntohs(foo->sin_port));
734     break;
735   }
736 #if defined(AF_INET6)
737   case AF_INET6: {
738     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
739     return(ntohs(foo->sin6_port));
740     break;
741   }
742 #endif
743   default:
744     fprintf(where,
745 	    "Unexpected Address Family %u\n",res->ai_family);
746     fflush(where);
747     exit(-1);
748   }
749 }
750 
751 /* does this need to become conditional on the presence of the macros
752    or might we ass-u-me that we will not be compiled on something so
753    old as to not have what we use? raj 20090803 */
754 static int
is_multicast_addr(struct addrinfo * res)755 is_multicast_addr(struct addrinfo *res) {
756   switch(res->ai_family) {
757   case AF_INET: {
758     /* IPv4 multicast runs from 224.0.0.0 to 239.255.255.255 or
759        0xE0000000 to 0xEFFFFFFF. Thankfully though there are macros
760        available to make the checks for one */
761     struct in_addr bar = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
762     /* and here I thought IN_MULTICAST would operate on things in
763        network byte order???  raj 20100315 */
764     return IN_MULTICAST(ntohl(bar.s_addr));
765   }
766 #if defined(AF_INET6)
767   case AF_INET6: {
768     struct in6_addr *bar = &(((struct sockaddr_in6 *)res->ai_addr)->sin6_addr);
769     return IN6_IS_ADDR_MULTICAST(bar);
770   }
771 #endif
772   default:
773     fprintf(where,
774 	    "Unexpected Address Family for Multicast Check %u\n",
775 	    res->ai_family);
776     fflush(where);
777     return 0;  /* or should we exit? */
778   }
779 }
780 
781 static void
set_multicast_ttl(SOCKET sock)782 set_multicast_ttl(SOCKET sock) {
783   int optlen = sizeof(int);
784 
785   /* now set/get the TTL */
786   if (multicast_ttl >= 0) {
787     if (setsockopt(sock,
788 		   IPPROTO_IP,
789 #if defined(IP_MULTICAST_TTL)
790 		   IP_MULTICAST_TTL,
791 #else
792 		   IP_TTL,
793 #endif
794 		   (const char *)&multicast_ttl,
795 		   sizeof(multicast_ttl)) == SOCKET_ERROR) {
796       fprintf(where,
797 	      "setsockopt(IP_TTL) failed errno %d\n",
798 	      errno);
799     }
800   }
801   if (getsockopt(sock,
802 		 IPPROTO_IP,
803 		 IP_TTL,
804 		 (char *)&multicast_ttl,
805 		 (netperf_socklen_t *)&optlen) < 0) {
806     fprintf(where,
807 	    "getsockopt(IP_TTL) failed errno %d\n",
808 	    errno);
809     multicast_ttl = -2;
810   }
811 }
812 
813 /* we presume we are only called with something which is actually a
814    multicast address. raj 20100315 */
815 static void
join_multicast_addr(SOCKET sock,struct addrinfo * res)816 join_multicast_addr(SOCKET sock, struct addrinfo *res) {
817   switch(res->ai_family) {
818   case AF_INET: {
819     struct ip_mreq mreq;
820     struct in_addr bar = ((struct sockaddr_in *)res->ai_addr)->sin_addr;
821     int optlen = sizeof(int);
822     int one    = 1;
823 
824     mreq.imr_multiaddr.s_addr=bar.s_addr;
825     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
826     if (setsockopt(sock,
827 		   IPPROTO_IP,
828 		   IP_ADD_MEMBERSHIP,
829 		   (const char *)&mreq,
830 		   sizeof(mreq)) == 0) {
831 
832       /* let others do the same */
833       if (setsockopt(sock,
834 		     SOL_SOCKET,
835 		     SO_REUSEADDR,
836 		     (const char *)&one,
837 		     sizeof(one)) == SOCKET_ERROR) {
838 	if (debug) {
839 	  fprintf(where,
840 		  "join_multicast_addr SO_REUSADDR failed errno %d\n",
841 		  errno);
842 	  fflush(where);
843 	}
844       }
845 
846       /* now set/get the TTL */
847       if (multicast_ttl >= 0) {
848 	if (setsockopt(sock,
849 		       IPPROTO_IP,
850 		       IP_TTL,
851 		       (const char *)&multicast_ttl,
852 		       sizeof(multicast_ttl)) == SOCKET_ERROR) {
853 	  fprintf(where,
854 		  "setsockopt(IP_TTL) failed errno %d\n",
855 		  errno);
856 	}
857       }
858       if (getsockopt(sock,
859 		     IPPROTO_IP,
860 		     IP_TTL,
861 		     (char *)&multicast_ttl,
862 		     (netperf_socklen_t *)&optlen) == SOCKET_ERROR) {
863 	fprintf(where,
864 		"getsockopt(IP_TTL) failed errno %d\n",
865 		errno);
866 	multicast_ttl = -2;
867       }
868     }
869     else {
870       if (debug) {
871 	fprintf(where,
872 		"setsockopt(IP_ADD_MEMBERSHIP) failed errno %d\n",
873 		errno);
874 	fflush(where);
875       }
876     }
877     break;
878   }
879   case AF_INET6: {
880     fprintf(where,"I do not know how to join an IPv6 multicast group\n");
881     break;
882   }
883 
884   }
885   return;
886 }
887 
888 static void
extract_inet_address_and_port(struct addrinfo * res,void * addr,int len,int * port)889 extract_inet_address_and_port(struct addrinfo *res, void *addr, int len, int *port)
890 {
891  switch(res->ai_family) {
892   case AF_INET: {
893     struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
894     *port = foo->sin_port;
895     memcpy(addr,&(foo->sin_addr),min(len,sizeof(foo->sin_addr)));
896     break;
897   }
898 #if defined(AF_INET6)
899   case AF_INET6: {
900     struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
901     *port = foo->sin6_port;
902     memcpy(addr,&(foo->sin6_addr),min(len,sizeof(foo->sin6_addr)));
903     break;
904   }
905 #endif
906   default:
907     *port = 0xDEADBEEF;
908     strncpy(addr,"UNKN FAMILY",len);
909   }
910 }
911 
912 void
pick_next_port_number(struct addrinfo * local_res,struct addrinfo * remote_res)913 pick_next_port_number(struct addrinfo *local_res, struct addrinfo *remote_res) {
914 
915   static int myport_init = 0;
916   static unsigned short myport = 0;
917 
918   if (0 == myport_init)  {
919     /* pick a nice random spot between client_port_min and
920        client_port_max for our initial port number, but only for a
921        connection oriented test. otherwise, we will want to set myport
922        to a specific port provided by the user if they have so provided
923        a specific port :)  raj 2008-01-08 */
924     srand(getpid());
925     if (client_port_max - client_port_min) {
926       myport = client_port_min +
927 	(rand() % (client_port_max - client_port_min));
928     }
929     else {
930       myport = (unsigned short)client_port_min;
931     }
932     /* there will be a ++ before the first call to bind, so subtract one */
933     myport--;
934     myport_init = 1;
935   }
936 
937   /* newport: */
938   /* pick a new port number */
939   myport++;
940 
941   /* check to see if we are using the port number on which the
942      server is sitting _before_ we check against the boundaries lest
943      the server sits at the upper boundary. if this happens to be a
944      loopback test, trying to use the same portnumber would lead to
945      unsatisfying results and should be avoided.  if this isn't a
946      loopback test, avoiding using the same port number doesn't
947      seriously affect anything anyway */
948 
949   if (myport == get_port_number(remote_res)) myport++;
950 
951   /* wrap the port number when we reach the upper bound.  for
952      students of networking history, some ancient stacks (1980's and
953      early 1990's perhaps) mistakenly treated these port numbers as
954      signed 16 bit quantities.  we make no effort here to support
955      such stacks. raj 2008-01-08 */
956   if (myport >= client_port_max) {
957     myport = (unsigned short)client_port_min;
958   }
959 
960   /* set up the data socket */
961   set_port_number(local_res, (unsigned short)myport);
962 }
963 
964 /* at some point this should become a table lookup... raj 20090813 */
965 char *
netperf_output_enum_to_str(enum netperf_output_name output_name)966 netperf_output_enum_to_str(enum netperf_output_name output_name)
967 {
968   switch (output_name) {
969   case OUTPUT_NONE:
970     return "OUTPUT_NONE";
971   case   COMMAND_LINE:
972     return "COMMAND_LINE";
973   case UUID:
974     return "UUID";
975   case RESULT_BRAND:
976     return "RESULT_BRAND";
977   case   SOCKET_TYPE:
978     return "SOCKET_TYPE";
979   case   DIRECTION:
980     return "DIRECTION";
981   case   PROTOCOL:
982     return "PROTOCOL";
983   case   ELAPSED_TIME:
984     return "ELAPSED_TIME";
985   case   SOURCE_PORT:
986     return "SOURCE_PORT";
987   case   SOURCE_ADDR:
988     return "SOURCE_ADDR";
989   case SOURCE_FAMILY:
990     return "SOURCE_FAMILY";
991   case   DEST_PORT:
992     return "DEST_PORT";
993   case   DEST_ADDR:
994     return "DEST_ADDR";
995   case DEST_FAMILY:
996     return "DEST_FAMILY";
997   case THROUGHPUT:
998     return "THROUGHPUT";
999   case LOCAL_SEND_THROUGHPUT:
1000     return "LOCAL_SEND_THROUGHPUT";
1001   case LOCAL_RECV_THROUGHPUT:
1002     return "LOCAL_RECV_THROUGHPUT";
1003   case REMOTE_SEND_THROUGHPUT:
1004     return "REMOTE_SEND_THROUGHPUT";
1005   case REMOTE_RECV_THROUGHPUT:
1006     return "REMOTE_RECV_THROUGHPUT";
1007   case THROUGHPUT_UNITS:
1008     return "THROUGHPUT_UNITS";
1009   case CONFIDENCE_LEVEL:
1010     return "CONFIDENCE_LEVEL";
1011   case CONFIDENCE_INTERVAL:
1012     return "CONFIDENCE_INTERVAL";
1013   case CONFIDENCE_ITERATION:
1014     return "CONFIDENCE_ITERATION";
1015   case THROUGHPUT_CONFID:
1016     return "THROUGHPUT_CONFID";
1017   case LOCAL_CPU_CONFID:
1018     return "LOCAL_CPU_CONFID";
1019   case REMOTE_CPU_CONFID:
1020     return "REMOTE_CPU_CONFID";
1021   case RT_LATENCY:
1022     return "RT_LATENCY";
1023   case TRANSACTION_RATE:
1024     return "TRANSACTION_RATE";
1025   case BURST_SIZE:
1026     return "BURST_SIZE";
1027   case LOCAL_TRANSPORT_RETRANS:
1028     return "LOCAL_TRANSPORT_RETRANS";
1029   case REMOTE_TRANSPORT_RETRANS:
1030     return "REMOTE_TRANSPORT_RETRANS";
1031   case TRANSPORT_MSS:
1032     return "TRANSPORT_MSS";
1033   case REQUEST_SIZE:
1034     return "REQUEST_SIZE";
1035   case RESPONSE_SIZE:
1036     return "RESPONSE_SIZE";
1037   case   LSS_SIZE_REQ:
1038     return "LSS_SIZE_REQ";
1039   case   LSS_SIZE:
1040     return "LSS_SIZE";
1041   case   LSS_SIZE_END:
1042     return "LSS_SIZE_END";
1043   case   LSR_SIZE_REQ:
1044     return "LSR_SIZE_REQ";
1045   case   LSR_SIZE:
1046     return "LSR_SIZE";
1047   case   LSR_SIZE_END:
1048     return "LSR_SIZE_END";
1049   case   LOCAL_SEND_SIZE:
1050     return "LOCAL_SEND_SIZE";
1051   case   LOCAL_RECV_SIZE:
1052     return "LOCAL_RECV_SIZE";
1053   case   LOCAL_SEND_CALLS:
1054     return "LOCAL_SEND_CALLS";
1055   case   LOCAL_RECV_CALLS:
1056     return "LOCAL_RECV_CALLS";
1057   case   LOCAL_BYTES_PER_RECV:
1058     return "LOCAL_BYTES_PER_RECV";
1059   case   LOCAL_BYTES_PER_SEND:
1060     return "LOCAL_BYTES_PER_SEND";
1061   case   LOCAL_BYTES_SENT:
1062     return "LOCAL_BYTES_SENT";
1063   case   LOCAL_BYTES_RECVD:
1064     return "LOCAL_BYTES_RECVD";
1065   case   LOCAL_BYTES_XFERD:
1066     return "LOCAL_BYTES_XFERD";
1067   case LOCAL_SEND_OFFSET:
1068     return "LOCAL_SEND_OFFSET";
1069   case LOCAL_RECV_OFFSET:
1070     return "LOCAL_RECV_OFFSET";
1071   case LOCAL_RECV_ALIGN:
1072     return "LOCAL_RECV_ALIGN";
1073   case LOCAL_SEND_ALIGN:
1074     return "LOCAL_SEND_ALIGN";
1075   case LOCAL_SEND_WIDTH:
1076     return "LOCAL_SEND_WIDTH";
1077   case LOCAL_RECV_WIDTH:
1078     return "LOCAL_RECV_WIDTH";
1079   case   LOCAL_SEND_DIRTY_COUNT:
1080     return "LOCAL_SEND_DIRTY_COUNT";
1081   case   LOCAL_RECV_DIRTY_COUNT:
1082     return "LOCAL_RECV_DIRTY_COUNT";
1083   case   LOCAL_RECV_CLEAN_COUNT:
1084     return "LOCAL_RECV_CLEAN_COUNT";
1085   case   LOCAL_CPU_UTIL:
1086     return "LOCAL_CPU_UTIL";
1087   case   LOCAL_CPU_PERCENT_USER:
1088     return "LOCAL_CPU_PERCENT_USER";
1089   case   LOCAL_CPU_PERCENT_SYSTEM:
1090     return "LOCAL_CPU_PERCENT_SYSTEM";
1091   case   LOCAL_CPU_PERCENT_IOWAIT:
1092     return "LOCAL_CPU_PERCENT_IOWAIT";
1093   case   LOCAL_CPU_PERCENT_IRQ:
1094     return "LOCAL_CPU_PERCENT_IRQ";
1095   case   LOCAL_CPU_PERCENT_SWINTR:
1096     return "LOCAL_CPU_PERCENT_SWINTR";
1097   case   LOCAL_CPU_BIND:
1098     return "LOCAL_CPU_BIND";
1099   case   LOCAL_SD:
1100     return "LOCAL_SD";
1101   case   SD_UNITS:
1102     return "SD_UNITS";
1103   case   LOCAL_CPU_METHOD:
1104     return "LOCAL_CPU_METHOD";
1105   case LOCAL_CPU_COUNT:
1106     return "LOCAL_CPU_COUNT";
1107   case   LOCAL_CPU_PEAK_UTIL:
1108     return "LOCAL_CPU_PEAK_UTIL";
1109   case LOCAL_CPU_PEAK_ID:
1110     return "LOCAL_CPU_PEAK_ID";
1111   case   LOCAL_NODELAY:
1112     return "LOCAL_NODELAY";
1113   case   LOCAL_CORK:
1114     return "LOCAL_CORK";
1115   case   RSS_SIZE_REQ:
1116     return "RSS_SIZE_REQ";
1117   case   RSS_SIZE:
1118     return "RSS_SIZE";
1119   case   RSS_SIZE_END:
1120     return "RSS_SIZE_END";
1121   case   RSR_SIZE_REQ:
1122     return "RSR_SIZE_REQ";
1123   case   RSR_SIZE:
1124     return "RSR_SIZE";
1125   case   RSR_SIZE_END:
1126     return "RSR_SIZE_END";
1127   case   REMOTE_SEND_SIZE:
1128     return "REMOTE_SEND_SIZE";
1129   case   REMOTE_RECV_SIZE:
1130     return "REMOTE_RECV_SIZE";
1131   case   REMOTE_SEND_CALLS:
1132     return "REMOTE_SEND_CALLS";
1133   case   REMOTE_RECV_CALLS:
1134     return "REMOTE_RECV_CALLS";
1135   case   REMOTE_BYTES_PER_RECV:
1136     return "REMOTE_BYTES_PER_RECV";
1137   case   REMOTE_BYTES_PER_SEND:
1138     return "REMOTE_BYTES_PER_SEND";
1139   case   REMOTE_BYTES_SENT:
1140     return "REMOTE_BYTES_SENT";
1141   case   REMOTE_BYTES_RECVD:
1142     return "REMOTE_BYTES_RECVD";
1143   case   REMOTE_BYTES_XFERD:
1144     return "REMOTE_BYTES_XFERD";
1145   case REMOTE_SEND_OFFSET:
1146     return "REMOTE_SEND_OFFSET";
1147   case REMOTE_RECV_OFFSET:
1148     return "REMOTE_RECV_OFFSET";
1149   case REMOTE_RECV_ALIGN:
1150     return "REMOTE_RECV_ALIGN";
1151   case REMOTE_SEND_ALIGN:
1152     return "REMOTE_SEND_ALIGN";
1153   case REMOTE_SEND_WIDTH:
1154     return "REMOTE_SEND_WIDTH";
1155   case REMOTE_RECV_WIDTH:
1156     return "REMOTE_RECV_WIDTH";
1157   case   REMOTE_SEND_DIRTY_COUNT:
1158     return "REMOTE_SEND_DIRTY_COUNT";
1159   case   REMOTE_RECV_DIRTY_COUNT:
1160     return "REMOTE_RECV_DIRTY_COUNT";
1161   case   REMOTE_RECV_CLEAN_COUNT:
1162     return "REMOTE_RECV_CLEAN_COUNT";
1163   case   REMOTE_CPU_UTIL:
1164     return "REMOTE_CPU_UTIL";
1165   case   REMOTE_CPU_PERCENT_USER:
1166     return "REMOTE_CPU_PERCENT_USER";
1167   case   REMOTE_CPU_PERCENT_SYSTEM:
1168     return "REMOTE_CPU_PERCENT_SYSTEM";
1169   case   REMOTE_CPU_PERCENT_IOWAIT:
1170     return "REMOTE_CPU_PERCENT_IOWAIT";
1171   case   REMOTE_CPU_PERCENT_IRQ:
1172     return "REMOTE_CPU_PERCENT_IRQ";
1173   case   REMOTE_CPU_PERCENT_SWINTR:
1174     return "REMOTE_CPU_PERCENT_SWINTR";
1175   case   REMOTE_CPU_BIND:
1176     return "REMOTE_CPU_BIND";
1177   case   REMOTE_SD:
1178     return "REMOTE_SD";
1179   case   REMOTE_CPU_METHOD:
1180     return "REMOTE_CPU_METHOD";
1181   case REMOTE_CPU_COUNT:
1182     return "REMOTE_CPU_COUNT";
1183   case REMOTE_CPU_PEAK_UTIL:
1184     return "REMOTE_CPU_PEAK_UTIL";
1185   case REMOTE_CPU_PEAK_ID:
1186     return "REMOTE_CPU_PEAK_ID";
1187   case   REMOTE_NODELAY:
1188     return "REMOTE_NODELAY";
1189   case   REMOTE_CORK:
1190     return "REMOTE_CORK";
1191   case LOCAL_INTERFACE_SLOT:
1192     return "LOCAL_INTERFACE_SLOT";
1193   case REMOTE_INTERFACE_SLOT:
1194     return "REMOTE_INTERFACE_SLOT";
1195   case REMOTE_INTERFACE_SUBDEVICE:
1196     return "REMOTE_INTERFACE_SUBDEVICE";
1197   case REMOTE_INTERFACE_SUBVENDOR:
1198     return "REMOTE_INTERFACE_SUBVENDOR";
1199   case REMOTE_INTERFACE_DEVICE:
1200     return "REMOTE_INTERFACE_DEVICE";
1201   case REMOTE_INTERFACE_VENDOR:
1202     return "REMOTE_INTERFACE_VENDOR";
1203   case LOCAL_INTERFACE_SUBDEVICE:
1204     return "LOCAL_INTERFACE_SUBDEVICE";
1205   case LOCAL_INTERFACE_SUBVENDOR:
1206     return "LOCAL_INTERFACE_SUBVENDOR";
1207   case LOCAL_INTERFACE_DEVICE:
1208     return "LOCAL_INTERFACE_DEVICE";
1209   case LOCAL_INTERFACE_VENDOR:
1210     return "LOCAL_INTERFACE_VENDOR";
1211   case LOCAL_INTERFACE_NAME:
1212     return "LOCAL_INTERFACE_NAME";
1213   case REMOTE_INTERFACE_NAME:
1214     return "REMOTE_INTERFACE_NAME";
1215   case REMOTE_DRIVER_NAME:
1216     return "REMOTE_DRIVER_NAME";
1217   case REMOTE_DRIVER_VERSION:
1218     return "REMOTE_DRIVER_VERSION";
1219   case REMOTE_DRIVER_FIRMWARE:
1220     return "REMOTE_DRIVER_FIRMWARE";
1221   case REMOTE_DRIVER_BUS:
1222     return "REMOTE_DRIVER_BUS";
1223   case LOCAL_DRIVER_NAME:
1224     return "LOCAL_DRIVER_NAME";
1225   case LOCAL_DRIVER_VERSION:
1226     return "LOCAL_DRIVER_VERSION";
1227   case LOCAL_DRIVER_FIRMWARE:
1228     return "LOCAL_DRIVER_FIRMWARE";
1229   case LOCAL_INTERVAL_USECS:
1230     return "LOCAL_INTERVAL_USECS";
1231   case LOCAL_INTERVAL_BURST:
1232     return "LOCAL_INTERVAL_BURST";
1233   case REMOTE_INTERVAL_USECS:
1234     return "REMOTE_INTERVAL_USECS";
1235   case REMOTE_INTERVAL_BURST:
1236     return "REMOTE_INTERVAL_BURST";
1237   case LOCAL_SECURITY_TYPE_ID:
1238     return "LOCAL_SECURITY_TYPE_ID";
1239   case LOCAL_SECURITY_ENABLED_NUM:
1240     return "LOCAL_SECURITY_ENABLED_NUM";
1241   case LOCAL_SECURITY_TYPE:
1242     return "LOCAL_SECURITY_TYPE";
1243   case LOCAL_SECURITY_ENABLED:
1244     return "LOCAL_SECURITY_ENABLED";
1245   case LOCAL_SECURITY_SPECIFIC:
1246     return "LOCAL_SECURITY_SPECIFIC";
1247   case REMOTE_SECURITY_TYPE_ID:
1248     return "REMOTE_SECURITY_TYPE_ID";
1249   case REMOTE_SECURITY_ENABLED_NUM:
1250     return "REMOTE_SECURITY_ENABLED_NUM";
1251   case REMOTE_SECURITY_TYPE:
1252     return "REMOTE_SECURITY_TYPE";
1253   case REMOTE_SECURITY_ENABLED:
1254     return "REMOTE_SECURITY_ENABLED";
1255   case REMOTE_SECURITY_SPECIFIC:
1256     return "REMOTE_SECURITY_SPECIFIC";
1257   case LOCAL_DRIVER_BUS:
1258     return "LOCAL_DRIVER_BUS";
1259   case REMOTE_SYSNAME:
1260     return "REMOTE_SYSNAME";
1261   case REMOTE_MACHINE:
1262     return "REMOTE_MACHINE";
1263   case REMOTE_VERSION:
1264     return "REMOTE_VERSION";
1265   case REMOTE_RELEASE:
1266     return "REMOTE_RELEASE";
1267   case LOCAL_SYSNAME:
1268     return "LOCAL_SYSNAME";
1269   case LOCAL_MACHINE:
1270     return "LOCAL_MACHINE";
1271   case LOCAL_VERSION:
1272     return "LOCAL_VERSION";
1273   case LOCAL_RELEASE:
1274     return "LOCAL_RELEASE";
1275   case REMOTE_CPU_MODEL:
1276     return "REMOTE_CPU_MODEL";
1277   case REMOTE_CPU_FREQUENCY:
1278     return "REMOTE_CPU_FREQUENCY";
1279   case REMOTE_SYSTEM_MODEL:
1280     return "REMOTE_SYSTEM_MODEL";
1281   case LOCAL_CPU_MODEL:
1282     return "LOCAL_CPU_MODEL";
1283   case LOCAL_CPU_FREQUENCY:
1284     return "LOCAL_CPU_FREQUENCY";
1285   case LOCAL_SYSTEM_MODEL:
1286     return "LOCAL_SYSTEM_MODEL";
1287   case MIN_LATENCY:
1288     return "MIN_LATENCY";
1289   case MAX_LATENCY:
1290     return "MAX_LATENCY";
1291   case P50_LATENCY:
1292     return "P50_LATENCY";
1293   case P90_LATENCY:
1294     return "P90_LATENCY";
1295   case P99_LATENCY:
1296     return "P99_LATENCY";
1297   case MEAN_LATENCY:
1298     return "MEAN_LATENCY";
1299   case STDDEV_LATENCY:
1300     return "STDDEV_LATENCY";
1301   case LOCAL_SOCKET_PRIO:
1302     return "LOCAL_SOCKET_PRIO";
1303   case REMOTE_SOCKET_PRIO:
1304     return "REMOTE_SOCKET_PRIO";
1305   case LOCAL_SOCKET_TOS:
1306     return "LOCAL_SOCKET_TOS";
1307   case REMOTE_SOCKET_TOS:
1308     return "REMOTE_SOCKET_TOS";
1309   case LOCAL_CONG_CONTROL:
1310     return "LOCAL_CONG_CONTROL";
1311   case REMOTE_CONG_CONTROL:
1312     return "REMOTE_CONG_CONTROL";
1313   case LOCAL_FILL_FILE:
1314     return "LOCAL_FILL_FILE";
1315   case REMOTE_FILL_FILE:
1316     return "REMOTE_FILL_FILE";
1317   case OUTPUT_END:
1318     return "OUTPUT_END";
1319   default:
1320     return "!UNKNOWN OUTPUT SELECTOR!";
1321   }
1322 }
1323 
1324 void
print_netperf_output_entry(FILE * where,enum netperf_output_name what)1325 print_netperf_output_entry(FILE *where, enum netperf_output_name what)
1326 {
1327 }
1328 
1329 void print_omni_init_list();
1330 
1331 void
dump_netperf_output_list(FILE * where)1332 dump_netperf_output_list(FILE *where) {
1333 
1334   int i,j;
1335 
1336   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
1337     fprintf(where,"Output Block %d\n",i + 1);
1338     for (j = 0; j < NETPERF_OUTPUT_MAX; j++) {
1339       fprintf(where,"%s ",netperf_output_enum_to_str(output_list[i][j]));
1340     }
1341     fprintf(where,"\n");
1342   }
1343   fflush(where);
1344 }
1345 
1346 void
dump_netperf_output_choices(FILE * where,int csv)1347 dump_netperf_output_choices(FILE *where, int csv) {
1348   int i;
1349 
1350   print_omni_init_list();
1351 
1352   for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++){
1353     if (OUTPUT_NONE != i) {
1354       fprintf(where,"%c",(csv) ? ',' : '\n');
1355     }
1356     fprintf(where,
1357 	    "%s",
1358 	    netperf_output_enum_to_str(netperf_output_source[i].output_name));
1359   }
1360   fprintf(where,"\n");
1361   fflush(where);
1362 }
1363 
1364 void
dump_netperf_output_source(FILE * where)1365 dump_netperf_output_source(FILE *where)
1366 {
1367   int i;
1368 
1369   /* belts and suspenders everyone... */
1370   for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++) {
1371     fprintf(where,
1372 	    "Output Name: %s\n"
1373 	    "\tmax_line_len %d tot_line_len %d display_value %p\n"
1374 	    "\tline[0]: |%s|\n"
1375 	    "\tline[1]: |%s|\n"
1376 	    "\tline[2]: |%s|\n"
1377 	    "\tline[3]: |%s|\n"
1378 	    "\tformat: |%s|\n",
1379 	    netperf_output_enum_to_str(netperf_output_source[i].output_name),
1380 	    netperf_output_source[i].max_line_len,
1381 	    netperf_output_source[i].tot_line_len,
1382 	    netperf_output_source[i].display_value,
1383 	    (netperf_output_source[i].line[0] == NULL) ? "" :
1384 	    netperf_output_source[i].line[0],
1385 	    (netperf_output_source[i].line[1] == NULL) ? "" :
1386 	    netperf_output_source[i].line[1],
1387 	    (netperf_output_source[i].line[2] == NULL) ? "" :
1388 	    netperf_output_source[i].line[2],
1389 	    (netperf_output_source[i].line[3] == NULL) ? "" :
1390 	    netperf_output_source[i].line[3],
1391 	    (netperf_output_source[i].format == NULL) ? "" :
1392 	    netperf_output_source[i].format);
1393   }
1394   fflush(where);
1395 }
1396 
1397 #define MY_MAX(a,b) ((a > b) ? a : b)
1398 
1399 #define NETPERF_LINE_MAX(x) \
1400     MY_MAX(MY_MAX(MY_MAX(strlen(netperf_output_source[x].line[0]),\
1401 		         strlen(netperf_output_source[x].line[1])),\
1402 	          strlen(netperf_output_source[x].line[2])),\
1403 	   strlen(netperf_output_source[x].line[3]))
1404 
1405 #define NETPERF_LINE_TOT(x) \
1406     strlen(netperf_output_source[x].line[0]) +\
1407     strlen(netperf_output_source[x].line[1]) +\
1408     strlen(netperf_output_source[x].line[2]) +\
1409     strlen(netperf_output_source[x].line[3]) + 4
1410 
1411 enum netperf_output_name
match_string_to_output_mnenomic(char * candidate)1412 match_string_to_output_mnenomic(char *candidate) {
1413 
1414   enum netperf_output_name name;
1415   for (name = OUTPUT_NONE; name < NETPERF_OUTPUT_MAX; name++) {
1416     if(!strcasecmp(candidate,netperf_output_enum_to_str(name)))
1417       return name;
1418   }
1419   return NETPERF_OUTPUT_UNKNOWN;
1420 }
1421 
1422 enum netperf_output_name
match_string_to_output(char * candidate)1423 match_string_to_output(char *candidate)
1424 {
1425   char *h1,*temp;
1426   enum netperf_output_name name;
1427   int k,len;
1428 
1429   /* at some point we may need/want to worry about leading and
1430      trailing spaces, but for now we will leave that onus on the
1431      user. */
1432 
1433   for (name = OUTPUT_NONE; name < NETPERF_OUTPUT_MAX; name++) {
1434     /* try for a match based on the nmemonic/enum */
1435     if (!strcasecmp(candidate,netperf_output_enum_to_str(name)))
1436       return name;
1437 
1438     /* try for a match on the actual header text */
1439     temp = malloc(NETPERF_LINE_TOT(name));
1440     h1 = temp;
1441     if (h1 != NULL) {
1442       for (k = 0; ((k < 4) &&
1443 		   (NULL != netperf_output_source[name].line[k]) &&
1444 		   (strcmp("",netperf_output_source[name].line[k]))); k++) {
1445 	len = sprintf(h1,
1446 		      "%s",
1447 		      netperf_output_source[name].line[k]);
1448 	*(h1 + len) = ' ';
1449 	/* now move to the next starting column. for csv we aren't worried
1450 	   about alignment between the header and the value lines */
1451 	h1 += len + 1;
1452       }
1453       /* this time we want null termination please */
1454       *(h1 - 1) = 0;
1455       if (!strcasecmp(candidate,temp)) {
1456 	free(temp);
1457 	return name;
1458       }
1459       else
1460 	free(temp);
1461     }
1462   }
1463   /* if we get here it means there was no match */
1464   return OUTPUT_NONE;
1465 }
1466 
1467 
1468 void
set_output_list_all()1469 set_output_list_all() {
1470 
1471   int i, j;  /* line, column */
1472   enum netperf_output_name k;
1473 
1474   /* Line One SOCKET_TYPE to RESPONSE_SIZE */
1475   i = 0;
1476   j = 0;
1477   for (k = SOCKET_TYPE; k <= RESPONSE_SIZE; k++) {
1478     output_list[i][j++] = k;
1479     desired_output_groups |= netperf_output_source[k].output_group;
1480   }
1481 
1482   /* Line Two LOCAL_CPU_UTIL to TRANSPORT_MSS */
1483   i = 1;
1484   j = 0;
1485   for (k = LOCAL_CPU_UTIL; k <= TRANSPORT_MSS; k++) {
1486     output_list[i][j++] = k;
1487     desired_output_groups |= netperf_output_source[k].output_group;
1488   }
1489 
1490   /* Line Three LOCAL_SEND_THROUGHPUT throught REMOTE_CORK */
1491   i = 2;
1492   j = 0;
1493   for (k = LOCAL_SEND_THROUGHPUT; k <= REMOTE_CORK; k++) {
1494     output_list[i][j++] = k;
1495     desired_output_groups |= netperf_output_source[k].output_group;
1496   }
1497 
1498   /* Line Four LOCAL_SYSNAME through COMMAND_LINE */
1499   i = 3;
1500   j = 0;
1501   for (k = LOCAL_SYSNAME; k <= COMMAND_LINE; k++) {
1502     output_list[i][j++] = k;
1503     desired_output_groups |= netperf_output_source[k].output_group;
1504   }
1505 
1506 }
1507 
1508 void
parse_output_selection_file(char * selection_file)1509 parse_output_selection_file(char *selection_file) {
1510   FILE *selections;
1511   char name[81]; /* best be more than enough */
1512   int namepos;
1513   int c;
1514   int j;
1515   int line,column;
1516 
1517   selections = fopen(selection_file,"r");
1518   if (!selections) {
1519     fprintf(where,
1520 	    "Could not open output selection file '%s' errno %d\n",
1521 	    selection_file,
1522 	    errno);
1523     fflush(where);
1524     exit(-1);
1525   }
1526 
1527   line = 0;
1528   column = 1;
1529   namepos = 0;
1530   name[0] = 0;
1531   name[80] = 0;
1532   j = 0;
1533   while (((c = fgetc(selections)) != EOF) && (line < 4)) {
1534     if (namepos == 80) {
1535       /* too long */
1536 
1537       fprintf(where,
1538 	      "Output selection starting column %d on line %d is too long\n",
1539 	      line + 1,
1540 	      column);
1541       fflush(where);
1542       exit(-1);
1543     }
1544     if (c == ',') {
1545       /* time to check for a match, but only if we won't overflow the
1546 	 current row of the array  */
1547       if (j == NETPERF_OUTPUT_MAX) {
1548 	fprintf(where,"Too many output selectors on line %d\n",line);
1549 	fflush(where);
1550 	exit(-1);
1551       }
1552       name[namepos] = 0;
1553       output_list[line][j++] = match_string_to_output(name);
1554       namepos = 0;
1555     }
1556     else if (c == '\n') {
1557       /* move to the next line after checking for a match */
1558       name[namepos] = 0;
1559       output_list[line++][j++] = match_string_to_output(name);
1560       namepos = 0;
1561       j = 0;
1562     }
1563     else if (isprint(c)) {
1564       name[namepos++] = (char)c;
1565     }
1566     column++;
1567   }
1568 
1569   /* ok, do we need/want to do anything here? at present we will
1570      silently ignore the rest of the file if we exit the loop on line
1571      count */
1572   if ((c == EOF) && (namepos > 0)) {
1573     name[namepos] = 0;
1574     output_list[line][j] =   match_string_to_output(name);
1575   }
1576 
1577 }
1578 
1579 void
parse_output_selection_line(int line,char * list)1580 parse_output_selection_line(int line, char *list) {
1581 
1582   char *token;
1583   int j;
1584   enum netperf_output_name name;
1585 
1586   /* belt and suspenders */
1587   if (line < 0) {
1588     fprintf(where,
1589 	    "parse_output_selection_line called with negative line number %d\n",line);
1590     fflush(where);
1591     exit(-1);
1592   }
1593 
1594   /* silently ignore extra lines and only warn if debug is set */
1595   if (line >= NETPERF_MAX_BLOCKS) {
1596     if (debug) {
1597       fprintf(where,
1598 	      "There can be no more than %d output selection lines."
1599 	      " Ignoring output selection line %d |%s|\n",
1600 	      NETPERF_MAX_BLOCKS,
1601 	      line + 1,
1602 	      list);
1603       fflush(where);
1604     }
1605     return;
1606   }
1607 
1608 
1609   j=0;
1610   token = strtok(list," ,");
1611   while ((token) && (j < NETPERF_OUTPUT_MAX)) {
1612 
1613     name = match_string_to_output_mnenomic(token);
1614 
1615     if ((name == NETPERF_OUTPUT_UNKNOWN) && (debug)) {
1616       fprintf(where,"Ignoring unknown output selector %d |%s| on line %d\n",
1617 	      j + 1,
1618 	      token,
1619 	      line +1);
1620       fflush(where);
1621     }
1622     else {
1623       output_list[line][j] = name;
1624       desired_output_groups |= netperf_output_source[name].output_group;
1625       j++;
1626     }
1627 
1628     token = strtok(NULL," ,");
1629   }
1630   if ((token) && (debug)) {
1631     fprintf(where,
1632 	    "There can be no more than %d output selectors per line. "
1633 	    "Ignoring remaining selectors on line %d\n",
1634 	    NETPERF_OUTPUT_MAX,line +1);
1635     fflush(where);
1636   }
1637 }
1638 
1639 void
parse_output_selection_direct(char * output_selection)1640 parse_output_selection_direct(char *output_selection) {
1641 
1642   char *source,*line,*remainder,*temp;
1643   char *f1, *f2, *f3;
1644   int i,len,done;
1645 
1646   len = strlen(output_selection);
1647 
1648   source = strdup(output_selection);
1649   line = (char *) malloc(len+1);
1650   remainder = (char *) malloc(len+1);
1651 
1652   if ((NULL == source) ||
1653       (NULL == line) ||
1654       (NULL == remainder)) {
1655     fprintf(where,"Unable to malloc memory for output selection parsing\n");
1656     fflush(where);
1657     exit(-1);
1658   }
1659 
1660   f1 = source;
1661   f2 = line;
1662   f3 = remainder;
1663 
1664   i = 0;
1665   done = 0;
1666   do {
1667     break_args_explicit_sep(source,';',line,remainder);
1668     if (line[0]) {
1669       parse_output_selection_line(i,line);
1670     }
1671     if (remainder[0]) {
1672       temp = source;
1673       source = remainder;
1674       remainder = temp;
1675       i++;
1676       /*
1677       if (i == NETPERF_MAX_BLOCKS) {
1678 	fprintf(where,
1679 		"Too many output blocks requested, maximum is %d\n",
1680 		NETPERF_MAX_BLOCKS);
1681 	fflush(where);
1682 	exit(-1);
1683       }
1684       */
1685       continue;
1686     }
1687     else {
1688       done = 1;
1689     }
1690   } while (!done);
1691 
1692   free(f1);
1693   free(f2);
1694   free(f3);
1695 
1696 }
1697 
1698 /* building blocks for output selection */
1699 #define NETPERF_TPUT "ELAPSED_TIME,THROUGHPUT,THROUGHPUT_UNITS"
1700 #define NETPERF_OUTPUT_STREAM "LSS_SIZE_END,RSR_SIZE_END,LOCAL_SEND_SIZE"
1701 #define NETPERF_OUTPUT_MAERTS "RSS_SIZE_END,LSR_SIZE_END,REMOTE_SEND_SIZE"
1702 #define NETPERF_CPU "LOCAL_CPU_UTIL,LOCAL_CPU_PERCENT_USER,LOCAL_CPU_PERCENT_SYSTEM,LOCAL_CPU_PERCENT_IOWAIT,LOCAL_CPU_PERCENT_IRQ,LOCAL_CPU_PERCENT_SWINTR,LOCAL_CPU_METHOD,REMOTE_CPU_UTIL,REMOTE_CPU_PERCENT_USER,REMOTE_CPU_PERCENT_SYSTEM,REMOTE_CPU_PERCENT_IOWAIT,REMOTE_CPU_PERCENT_IRQ,REMOTE_CPU_PERCENT_SWINTR,REMOTE_CPU_METHOD,LOCAL_SD,REMOTE_SD,SD_UNITS"
1703 #define NETPERF_RR "LSS_SIZE_END,LSR_SIZE_END,RSR_SIZE_END,RSS_SIZE_END,REQUEST_SIZE,RESPONSE_SIZE"
1704 
1705 void
set_output_list_by_test()1706 set_output_list_by_test() {
1707 
1708   char *stream_no_cpu = NETPERF_OUTPUT_STREAM "," NETPERF_TPUT;
1709   char *stream_cpu = NETPERF_OUTPUT_STREAM "," NETPERF_TPUT "," NETPERF_CPU;
1710   char *maerts_no_cpu = NETPERF_OUTPUT_MAERTS "," NETPERF_TPUT;
1711   char *maerts_cpu =  NETPERF_OUTPUT_MAERTS "," NETPERF_TPUT "," NETPERF_CPU;
1712   char *rr_no_cpu = NETPERF_RR "," NETPERF_TPUT;
1713   char *rr_cpu = NETPERF_RR "," NETPERF_TPUT "," NETPERF_CPU;
1714 
1715   if (debug) {
1716     fprintf(where,"%s setting the output list by test\n",
1717 	    __FUNCTION__);
1718     fflush(where);
1719   }
1720 
1721   if (NETPERF_XMIT_ONLY(direction)) {
1722     if (!(local_cpu_usage || remote_cpu_usage))
1723       parse_output_selection_direct(stream_no_cpu);
1724     else
1725       parse_output_selection_direct(stream_cpu);
1726   }
1727   else if (NETPERF_RECV_ONLY(direction)) {
1728     if (!(local_cpu_usage || remote_cpu_usage))
1729       parse_output_selection_direct(maerts_no_cpu);
1730     else
1731       parse_output_selection_direct(maerts_cpu);
1732   }
1733   else if (NETPERF_CC(direction)) {
1734     if (!(local_cpu_usage || remote_cpu_usage))
1735       parse_output_selection_direct(rr_no_cpu);
1736     else
1737       parse_output_selection_direct(rr_cpu);
1738   }
1739   else if (NETPERF_IS_RR(direction)) {
1740     if (!(local_cpu_usage || remote_cpu_usage))
1741       parse_output_selection_direct(rr_no_cpu);
1742     else
1743       parse_output_selection_direct(rr_cpu);
1744   }
1745   else {
1746     /* no idea */
1747     if (debug) {
1748       fprintf(where,"Cannot determine default test output, using mins\n");
1749       fflush(where);
1750     }
1751     parse_output_selection_direct(NETPERF_TPUT "," NETPERF_CPU);
1752   }
1753 }
1754 
1755 void
parse_output_selection(char * output_selection)1756 parse_output_selection(char *output_selection) {
1757 
1758   if (debug) {
1759     fprintf(where,"%s is parsing the output selection '%s'\n",
1760 	    __FUNCTION__,
1761 	    output_selection);
1762     fflush(where);
1763   }
1764 
1765   /* is it the magic keyword? */
1766   if (strcasecmp(output_selection,"all") == 0) {
1767     set_output_list_all();
1768   }
1769   /* do not forget the case when the output_selection is a single
1770      mnemonic without any separators... */
1771   else if (strchr(output_selection,',') ||
1772 	   strchr(output_selection,';') ||
1773 	   (match_string_to_output_mnenomic(output_selection) !=
1774 	    NETPERF_OUTPUT_UNKNOWN)) {
1775     parse_output_selection_direct(output_selection);
1776   }
1777   else {
1778     parse_output_selection_file(output_selection);
1779   }
1780   if (debug > 2) {
1781     dump_netperf_output_list(stderr);
1782   }
1783   return;
1784 }
1785 
1786 static void
set_output_elt(enum netperf_output_name name,char * line0,char * line1,char * line2,char * line3,char * format,void * value,unsigned int out_default,unsigned int group,enum netperf_output_type type)1787 set_output_elt(enum netperf_output_name name,
1788 	       char *line0, char *line1, char *line2, char *line3,
1789 	       char *format,
1790 	       void *value,
1791 	       unsigned int out_default,
1792 	       unsigned int group,
1793 	       enum netperf_output_type type) {
1794 
1795   netperf_output_source[name].output_name = name;
1796   netperf_output_source[name].line[0] = line0;
1797   netperf_output_source[name].line[1] = line1;
1798   netperf_output_source[name].line[2] = line2;
1799   netperf_output_source[name].line[3] = line3;
1800   netperf_output_source[name].format = format;
1801   netperf_output_source[name].display_value = value;
1802   netperf_output_source[name].output_default = out_default;
1803   netperf_output_source[name].output_group = group;
1804   netperf_output_source[name].max_line_len = NETPERF_LINE_MAX(name);
1805   netperf_output_source[name].tot_line_len = NETPERF_LINE_TOT(name);
1806   netperf_output_source[name].output_type = type;
1807 }
1808 
1809 void
print_omni_init_list()1810 print_omni_init_list() {
1811 
1812   int i;
1813 
1814   if (debug) {
1815     fprintf(where,"%s called\n",
1816 	    __FUNCTION__);
1817   }
1818 
1819   /* belts and suspenders everyone... */
1820   for (i = NETPERF_OUTPUT_UNKNOWN; i < NETPERF_OUTPUT_MAX; i++) {
1821     netperf_output_source[i].output_name = i;
1822     netperf_output_source[i].max_line_len = 0;
1823     netperf_output_source[i].tot_line_len = 0;
1824     netperf_output_source[i].line[0] = "";
1825     netperf_output_source[i].line[1] = "";
1826     netperf_output_source[i].line[2] = "";
1827     netperf_output_source[i].line[3] = "";
1828     netperf_output_source[i].format = "";
1829     netperf_output_source[i].display_value = NULL;
1830     netperf_output_source[i].output_default = 1;
1831     netperf_output_source[i].output_group = 0;
1832     netperf_output_source[i].output_type = NETPERF_TYPE_UNKNOWN;
1833   }
1834 
1835   set_output_elt(OUTPUT_NONE, " ", "", "", "", "%s", &" ",1, 0,
1836 		 NETPERF_TYPE_CHAR);
1837 
1838   set_output_elt(COMMAND_LINE, "Command","Line","","","\"%s\"",
1839 		 command_line,1, 0, NETPERF_TYPE_CHAR);
1840 
1841   set_output_elt(UUID, "Test", "UUID", "", "", "%s", test_uuid, 1, 0,
1842 		 NETPERF_TYPE_CHAR);
1843 
1844   set_output_elt(RESULT_BRAND, "Result", "Tag", "", "", "\"%s\"",
1845 		 result_brand, 1, 0, NETPERF_TYPE_CHAR);
1846 
1847   set_output_elt(SOCKET_TYPE, "Socket", "Type", "", "", "%s",
1848 		 socket_type_str, 1, 0, NETPERF_TYPE_CHAR);
1849 
1850   set_output_elt(DIRECTION, "Direction", "", "", "", "%s",
1851 		 direction_str, 1, 0, NETPERF_TYPE_CHAR);
1852 
1853   set_output_elt(PROTOCOL, "Protocol", "", "", "", "%s",
1854 		 protocol_str, 1, 0, NETPERF_TYPE_CHAR);
1855 
1856   set_output_elt(ELAPSED_TIME, "Elapsed", "Time", "(sec)", "", "%.2f",
1857 		 &elapsed_time_double, 1, 0, NETPERF_TYPE_DOUBLE);
1858 
1859   set_output_elt(SOURCE_PORT, "Source", "Port", "", "", "%s",
1860 		 local_data_port, 1, 0, NETPERF_TYPE_CHAR);
1861 
1862   set_output_elt(SOURCE_ADDR, "Source", "Address", "", "", "%s",
1863 		 local_data_address, 1, 0, NETPERF_TYPE_CHAR);
1864 
1865   set_output_elt(SOURCE_FAMILY, "Source", "Family", "", "", "%d",
1866 		 &local_data_family, 1, 0, NETPERF_TYPE_INT32);
1867 
1868   set_output_elt(DEST_PORT, "Destination", "Port", "", "", "%s",
1869 		 remote_data_port, 1, 0, NETPERF_TYPE_CHAR);
1870 
1871   set_output_elt(DEST_ADDR, "Destination", "Address", "", "", "%s",
1872 		 remote_data_address, 1, 0, NETPERF_TYPE_CHAR);
1873 
1874   set_output_elt(DEST_FAMILY, "Destination", "Family", "", "", "%d",
1875 		 &remote_data_family, 1, 0, NETPERF_TYPE_INT32);
1876 
1877   set_output_elt(THROUGHPUT, "Throughput", "", "", "", "%.2f",
1878 		 &thruput, 1, 0, NETPERF_TYPE_DOUBLE);
1879 
1880   set_output_elt(LOCAL_SEND_THROUGHPUT, "Local", "Send", "Throughput", "",
1881 		 "%.2f", &local_send_thruput, 1, 0, NETPERF_TYPE_DOUBLE);
1882 
1883   set_output_elt(LOCAL_RECV_THROUGHPUT, "Local", "Recv", "Throughput", "",
1884 		 "%.2f", &local_recv_thruput, 1, 0, NETPERF_TYPE_DOUBLE);
1885 
1886   set_output_elt(REMOTE_SEND_THROUGHPUT, "Remote", "Send", "Throughput", "",
1887 		 "%.2f", &remote_send_thruput, 1, 0, NETPERF_TYPE_DOUBLE);
1888 
1889   set_output_elt(REMOTE_RECV_THROUGHPUT, "Remote", "Recv", "Throughput", "",
1890 		 "%.2f", &remote_recv_thruput, 1, 0, NETPERF_TYPE_DOUBLE);
1891 
1892   set_output_elt(THROUGHPUT_UNITS, "Throughput", "Units", "", "", "%s/s",
1893 		 thruput_format_str, 1, 0, NETPERF_TYPE_CHAR);
1894 
1895   set_output_elt(CONFIDENCE_LEVEL, "Confidence", "Level", "Percent", "", "%d",
1896 		 &confidence_level, 1, 0, NETPERF_TYPE_INT32);
1897 
1898   set_output_elt(CONFIDENCE_INTERVAL, "Confidence", "Width", "Target", "",
1899 		 "%f", &interval_pct, 1, 0, NETPERF_TYPE_DOUBLE);
1900 
1901   set_output_elt(CONFIDENCE_ITERATION, "Confidence", "Iterations", "Run", "",
1902 		 "%d", &confidence_iteration, 1, 0, NETPERF_TYPE_INT32);
1903 
1904   set_output_elt(THROUGHPUT_CONFID, "Throughput", "Confidence", "Width (%)",
1905 		 "", "%.3f", &result_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE);
1906 
1907   set_output_elt(LOCAL_CPU_CONFID, "Local", "CPU", "Confidence", "Width (%)",
1908 		 "%.3f", &loc_cpu_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE);
1909 
1910   set_output_elt(REMOTE_CPU_CONFID, "Remote", "CPU", "Confidence", "Width (%)",
1911 		 "%.3f", &rem_cpu_confid_pct, 1, 0, NETPERF_TYPE_DOUBLE);
1912 
1913   set_output_elt(RT_LATENCY, "Round", "Trip", "Latency", "usec/tran", "%.3f",
1914 		 &rtt_latency, 1, 0, NETPERF_TYPE_DOUBLE);
1915 
1916   set_output_elt(TRANSACTION_RATE, "Transaction", "Rate", "Tran/s", "", "%.3f",
1917 		 &transaction_rate, 1, 0, NETPERF_TYPE_DOUBLE);
1918 
1919   set_output_elt(TRANSPORT_MSS, "Transport", "MSS", "bytes", "", "%d",
1920 		 &transport_mss, 1, 0, NETPERF_TYPE_INT32);
1921 
1922   set_output_elt(LOCAL_TRANSPORT_RETRANS, "Local", "Transport",
1923 		 "Retransmissions", "", "%d", &local_transport_retrans, 1, 0,
1924 		 NETPERF_TYPE_INT32);
1925 
1926   set_output_elt(REMOTE_TRANSPORT_RETRANS, "Remote", "Transport",
1927 		 "Retransmissions", "", "%d", &remote_transport_retrans, 1, 0,
1928 		 NETPERF_TYPE_INT32);
1929 
1930   set_output_elt(REQUEST_SIZE, "Request", "Size", "Bytes", "", "%d",
1931 		 &req_size, 1, 0, NETPERF_TYPE_INT32);
1932 
1933   set_output_elt(RESPONSE_SIZE, "Response", "Size", "Bytes", "", "%d",
1934 		 &rsp_size, 1, 0, NETPERF_TYPE_INT32);
1935 
1936   set_output_elt(BURST_SIZE, "Initial", "Burst", "Requests", "", "%d",
1937 		 &first_burst_size, 1, 0, NETPERF_TYPE_INT32);
1938 
1939   set_output_elt(LSS_SIZE_REQ, "Local", "Send Socket", "Size", "Requested",
1940 		 "%d", &lss_size_req, 1, 0, NETPERF_TYPE_INT32);
1941 
1942   set_output_elt(LSS_SIZE, "Local", "Send Socket", "Size", "Initial", "%d",
1943 		 &lss_size, 1, 0, NETPERF_TYPE_INT32);
1944 
1945   set_output_elt(LSS_SIZE_END, "Local", "Send Socket", "Size", "Final", "%d",
1946 		 &lss_size_end, 1, 0, NETPERF_TYPE_INT32);
1947 
1948   set_output_elt(LSR_SIZE_REQ, "Local", "Recv Socket", "Size", "Requested",
1949 		 "%d", &lsr_size_req, 1, 0, NETPERF_TYPE_INT32);
1950 
1951   set_output_elt(LSR_SIZE, "Local", "Recv Socket", "Size", "Initial", "%d",
1952 		 &lsr_size, 1, 0, NETPERF_TYPE_INT32);
1953 
1954   set_output_elt(LSR_SIZE_END, "Local", "Recv Socket", "Size", "Final", "%d",
1955 		 &lsr_size_end, 1, 0, NETPERF_TYPE_INT32);
1956 
1957   set_output_elt(LOCAL_SEND_SIZE, "Local", "Send", "Size", "", "%d",
1958 		 &send_size, 1, 0, NETPERF_TYPE_INT32);
1959 
1960   set_output_elt(LOCAL_RECV_SIZE, "Local", "Recv", "Size", "", "%d",
1961 		 &recv_size, 1, 0, NETPERF_TYPE_INT32);
1962 
1963   set_output_elt(LOCAL_SEND_CALLS, "Local", "Send", "Calls", "", "%"PRIu64,
1964 		 &local_send_calls, 1, 0, NETPERF_TYPE_UINT64);
1965 
1966   set_output_elt(LOCAL_RECV_CALLS, "Local", "Recv", "Calls", "", "%"PRIu64,
1967 		 &local_receive_calls, 1, 0, NETPERF_TYPE_UINT64);
1968 
1969   set_output_elt(LOCAL_BYTES_PER_RECV, "Local", "Bytes", "Per", "Recv", "%.2f",
1970 		 &bytes_per_recv, 1, 0, NETPERF_TYPE_DOUBLE);
1971 
1972   set_output_elt(LOCAL_BYTES_PER_SEND, "Local", "Bytes", "Per", "Send", "%.2f",
1973 		 &bytes_per_send, 1, 0, NETPERF_TYPE_DOUBLE);
1974 
1975   set_output_elt(LOCAL_BYTES_RECVD, "Local", "Bytes", "Received", "", "%"PRIu64,
1976 		 &bytes_received, 1, 0, NETPERF_TYPE_UINT64);
1977 
1978   set_output_elt(LOCAL_BYTES_SENT, "Local", "Bytes", "Sent", "", "%"PRIu64,
1979 		 &bytes_sent, 1, 0, NETPERF_TYPE_UINT64);
1980 
1981   set_output_elt(LOCAL_BYTES_XFERD, "Local", "Bytes", "Xferred", "", "%.0f",
1982 		 &bytes_xferd, 1, 0, NETPERF_TYPE_DOUBLE);
1983 
1984   set_output_elt(LOCAL_SEND_WIDTH, "Local", "Send", "Width", "", "%d",
1985 		 &send_width, 1, 0, NETPERF_TYPE_INT32);
1986 
1987   set_output_elt(LOCAL_RECV_WIDTH, "Local", "Recv", "Width", "", "%d",
1988 		 &recv_width, 1, 0, NETPERF_TYPE_INT32);
1989 
1990   set_output_elt(LOCAL_SEND_OFFSET, "Local", "Send", "Offset", "", "%d",
1991 		 &local_send_offset, 1, 0, NETPERF_TYPE_INT32);
1992 
1993   set_output_elt(LOCAL_RECV_OFFSET, "Local", "Recv", "Offset", "", "%d",
1994 		 &local_recv_offset, 1, 0, NETPERF_TYPE_INT32);
1995 
1996   set_output_elt(LOCAL_RECV_ALIGN, "Local", "Recv", "Alignment", "", "%d",
1997 		 &local_recv_align, 1, 0, NETPERF_TYPE_INT32);
1998 
1999   set_output_elt(LOCAL_SEND_ALIGN, "Local", "Send", "Alignment", "", "%d",
2000 		 &local_send_align, 1, 0, NETPERF_TYPE_INT32);
2001 
2002   set_output_elt(LOCAL_SEND_DIRTY_COUNT, "Local", "Send", "Dirty", "Count",
2003 		 "%d", &loc_dirty_count, 1, 0, NETPERF_TYPE_INT32);
2004 
2005   set_output_elt(LOCAL_RECV_DIRTY_COUNT, "Local", "Recv", "Dirty", "Count",
2006 		 "%d", &loc_dirty_count, 1, 0, NETPERF_TYPE_INT32);
2007 
2008   set_output_elt(LOCAL_RECV_CLEAN_COUNT, "Local", "Recv", "Clean", "Count",
2009 		 "%d", &loc_clean_count, 1, 0, NETPERF_TYPE_INT32);
2010 
2011   set_output_elt(LOCAL_CPU_UTIL, "Local", "CPU", "Util", "%", "%.2f",
2012 		 &local_cpu_utilization, 1, 0, NETPERF_TYPE_FLOAT);
2013 
2014   set_output_elt(LOCAL_CPU_PERCENT_USER, "Local", "CPU", "User", "%", "%.2f",
2015 		 &lib_local_cpu_stats.cpu_user, 1, 0, NETPERF_TYPE_FLOAT);
2016 
2017   set_output_elt(LOCAL_CPU_PERCENT_SYSTEM,
2018                  "Local", "CPU", "System", "%", "%.2f",
2019 		 &lib_local_cpu_stats.cpu_system, 1, 0, NETPERF_TYPE_FLOAT);
2020 
2021   set_output_elt(LOCAL_CPU_PERCENT_IOWAIT,
2022                  "Local", "CPU", "I/O", "%", "%.2f",
2023 		 &lib_local_cpu_stats.cpu_iowait, 1, 0, NETPERF_TYPE_FLOAT);
2024 
2025   set_output_elt(LOCAL_CPU_PERCENT_IRQ,
2026                  "Local", "CPU", "IRQ", "%", "%.2f",
2027 		 &lib_local_cpu_stats.cpu_irq, 1, 0, NETPERF_TYPE_FLOAT);
2028 
2029   set_output_elt(LOCAL_CPU_PERCENT_SWINTR,
2030                  "Local", "CPU", "swintr", "%", "%.2f",
2031 		 &lib_local_cpu_stats.cpu_swintr, 1, 0, NETPERF_TYPE_FLOAT);
2032 
2033   set_output_elt(LOCAL_CPU_PEAK_UTIL, "Local", "Peak", "Per CPU", "Util %",
2034 		 "%.2f", &lib_local_cpu_stats.peak_cpu_util, 1, 0,
2035                  NETPERF_TYPE_FLOAT);
2036 
2037   set_output_elt(LOCAL_CPU_PEAK_ID, "Local", "Peak", "Per CPU", "ID", "%d",
2038 		 &lib_local_cpu_stats.peak_cpu_id, 1, 0, NETPERF_TYPE_INT32);
2039 
2040   set_output_elt(LOCAL_CPU_BIND, "Local", "CPU", "Bind", "", "%d",
2041 		 &local_proc_affinity, 1, 0, NETPERF_TYPE_INT32);
2042 
2043   set_output_elt(LOCAL_SD, "Local", "Service", "Demand", "", "%.3f",
2044 		 &local_service_demand_double, 1, 0, NETPERF_TYPE_DOUBLE);
2045 
2046   set_output_elt(SD_UNITS, "Service", "Demand", "Units", "", "%s",
2047 		 sd_str, 1, 0, NETPERF_TYPE_CHAR);
2048 
2049   set_output_elt(LOCAL_CPU_METHOD, "Local", "CPU", "Util", "Method", "%c",
2050 		 &local_cpu_method, 1, 0, NETPERF_TYPE_INT32);
2051 
2052   set_output_elt(LOCAL_CPU_COUNT, "Local", "CPU", "Count", "", "%d",
2053 		 &lib_num_loc_cpus, 1, 0, NETPERF_TYPE_INT32);
2054 
2055   set_output_elt(LOCAL_NODELAY, "Local", "NODELAY", "", "", "%d",
2056 		 &loc_nodelay, 1, 0, NETPERF_TYPE_INT32);
2057 
2058   set_output_elt(LOCAL_CORK, "Local", "Cork", "", "", "%d",
2059 		 &loc_tcpcork, 1, 0, NETPERF_TYPE_INT32);
2060 
2061   set_output_elt(RSS_SIZE_REQ, "Remote", "Send Socket", "Size", "Requested",
2062 		 "%d", &rss_size_req, 1, 0, NETPERF_TYPE_INT32);
2063 
2064   set_output_elt(RSS_SIZE, "Remote", "Send Socket", "Size", "Initial", "%d",
2065 		 &rss_size, 1, 0, NETPERF_TYPE_INT32);
2066 
2067   set_output_elt(RSS_SIZE_END, "Remote", "Send Socket", "Size", "Final", "%d",
2068 		 &rss_size_end, 1, 0, NETPERF_TYPE_INT32);
2069 
2070   set_output_elt(RSR_SIZE_REQ, "Remote", "Recv Socket", "Size", "Requested",
2071 		 "%d", &rsr_size_req, 1, 0, NETPERF_TYPE_INT32);
2072 
2073   set_output_elt(RSR_SIZE, "Remote", "Recv Socket", "Size", "Initial", "%d",
2074 		 &rsr_size, 1, 0, NETPERF_TYPE_INT32);
2075 
2076   set_output_elt(RSR_SIZE_END, "Remote", "Recv Socket", "Size", "Final", "%d",
2077 		 &rsr_size_end, 1, 0, NETPERF_TYPE_INT32);
2078 
2079   set_output_elt(REMOTE_SEND_SIZE, "Remote", "Send", "Size", "", "%d",
2080 		 &remote_send_size, 1, 0, NETPERF_TYPE_INT32);
2081 
2082   set_output_elt(REMOTE_RECV_SIZE, "Remote", "Recv", "Size", "", "%d",
2083 		 &remote_recv_size, 1, 0, NETPERF_TYPE_INT32);
2084 
2085   set_output_elt(REMOTE_SEND_CALLS, "Remote", "Send", "Calls", "", "%"PRIu64,
2086 		 &remote_send_calls, 1, 0, NETPERF_TYPE_UINT64);
2087 
2088   set_output_elt(REMOTE_RECV_CALLS, "Remote", "Recv", "Calls", "", "%"PRIu64,
2089 		 &remote_receive_calls, 1, 0, NETPERF_TYPE_UINT64);
2090 
2091   set_output_elt(REMOTE_BYTES_PER_RECV, "Remote", "Bytes", "Per", "Recv",
2092 		 "%.2f", &remote_bytes_per_recv, 1, 0, NETPERF_TYPE_DOUBLE);
2093 
2094   set_output_elt(REMOTE_BYTES_PER_SEND, "Remote", "Bytes", "Per", "Send",
2095 		 "%.2f", &remote_bytes_per_send, 1, 0, NETPERF_TYPE_DOUBLE);
2096 
2097   set_output_elt(REMOTE_BYTES_RECVD, "Remote", "Bytes", "Received", "",
2098 		 "%"PRIu64, &remote_bytes_received, 1, 0, NETPERF_TYPE_UINT64);
2099 
2100   set_output_elt(REMOTE_BYTES_SENT, "Remote", "Bytes", "Sent", "", "%"PRIu64,
2101 		 &remote_bytes_sent, 1, 0, NETPERF_TYPE_UINT64);
2102 
2103   set_output_elt(REMOTE_BYTES_XFERD, "Remote", "Bytes", "Xferred", "", "%.0f",
2104 		 &remote_bytes_xferd, 1, 0, NETPERF_TYPE_DOUBLE);
2105 
2106   set_output_elt(REMOTE_SEND_WIDTH, "Remote", "Send", "Width", "", "%d",
2107 		 &remote_send_width, 1, 0, NETPERF_TYPE_INT32);
2108 
2109   set_output_elt(REMOTE_RECV_WIDTH, "Remote", "Recv", "Width", "", "%d",
2110 		 &remote_recv_width, 1, 0, NETPERF_TYPE_INT32);
2111 
2112   set_output_elt(REMOTE_SEND_OFFSET, "Remote", "Send", "Offset", "", "%d",
2113 		 &remote_send_offset, 1, 0, NETPERF_TYPE_INT32);
2114 
2115   set_output_elt(REMOTE_RECV_OFFSET, "Remote", "Recv", "Offset", "", "%d",
2116 		 &remote_recv_offset, 1, 0, NETPERF_TYPE_INT32);
2117 
2118   set_output_elt(REMOTE_RECV_ALIGN, "Remote", "Recv", "Alignment", "", "%d",
2119 		 &remote_recv_align, 1, 0, NETPERF_TYPE_INT32);
2120 
2121   set_output_elt(REMOTE_SEND_ALIGN, "Remote", "Send", "Alignment", "", "%d",
2122 		 &remote_send_align, 1, 0, NETPERF_TYPE_INT32);
2123 
2124   set_output_elt(REMOTE_SEND_DIRTY_COUNT, "Remote", "Send", "Dirty", "Count",
2125 		 "%d", &rem_dirty_count, 1, 0, NETPERF_TYPE_INT32);
2126 
2127   set_output_elt(REMOTE_RECV_DIRTY_COUNT, "Remote", "Recv", "Dirty", "Count",
2128 		 "%d", &rem_dirty_count, 1, 0, NETPERF_TYPE_INT32);
2129 
2130   set_output_elt(REMOTE_RECV_CLEAN_COUNT, "Remote", "Recv", "Clean", "Count",
2131 		 "%d", &rem_clean_count, 1, 0, NETPERF_TYPE_INT32);
2132 
2133   set_output_elt(REMOTE_CPU_UTIL, "Remote", "CPU", "Util", "%", "%.2f",
2134 		 &remote_cpu_utilization, 1, 0, NETPERF_TYPE_FLOAT);
2135 
2136   set_output_elt(REMOTE_CPU_PERCENT_USER, "Remote", "CPU", "User", "%", "%.2f",
2137 		 &lib_remote_cpu_stats.cpu_user, 1, 0, NETPERF_TYPE_FLOAT);
2138 
2139   set_output_elt(REMOTE_CPU_PERCENT_SYSTEM,
2140                  "Remote", "CPU", "System", "%", "%.2f",
2141 		 &lib_remote_cpu_stats.cpu_system, 1, 0, NETPERF_TYPE_FLOAT);
2142 
2143   set_output_elt(REMOTE_CPU_PERCENT_IOWAIT,
2144                  "Remote", "CPU", "I/O", "%", "%.2f",
2145 		 &lib_remote_cpu_stats.cpu_iowait, 1, 0, NETPERF_TYPE_FLOAT);
2146 
2147   set_output_elt(REMOTE_CPU_PERCENT_IRQ,
2148                  "Remote", "CPU", "IRQ", "%", "%.2f",
2149 		 &lib_remote_cpu_stats.cpu_irq, 1, 0, NETPERF_TYPE_FLOAT);
2150 
2151   set_output_elt(REMOTE_CPU_PERCENT_SWINTR,
2152                  "Remote", "CPU", "swintr", "%", "%.2f",
2153 		 &lib_remote_cpu_stats.cpu_swintr, 1, 0, NETPERF_TYPE_FLOAT);
2154 
2155   set_output_elt(REMOTE_CPU_PEAK_UTIL, "Remote", "Peak", "Per CPU", "Util %",
2156 		 "%.2f", &lib_remote_cpu_stats.peak_cpu_util, 1, 0,
2157                  NETPERF_TYPE_FLOAT);
2158 
2159   set_output_elt(REMOTE_CPU_PEAK_ID, "Remote", "Peak", "Per CPU", "ID", "%d",
2160 		 &lib_remote_cpu_stats.peak_cpu_id, 1, 0, NETPERF_TYPE_INT32);
2161 
2162   set_output_elt(REMOTE_CPU_BIND, "Remote", "CPU", "Bind", "", "%d",
2163 		 &remote_proc_affinity, 1, 0, NETPERF_TYPE_INT32);
2164 
2165   set_output_elt(REMOTE_SD, "Remote", "Service", "Demand", "", "%.3f",
2166 		 &remote_service_demand_double, 1, 0, NETPERF_TYPE_DOUBLE);
2167 
2168   set_output_elt(REMOTE_CPU_METHOD, "Remote", "CPU", "Util", "Method", "%c",
2169 		 &remote_cpu_method, 1, 0, NETPERF_TYPE_INT32);
2170 
2171   set_output_elt(REMOTE_CPU_COUNT, "Remote", "CPU", "Count", "", "%d",
2172 		 &lib_num_rem_cpus, 1, 0, NETPERF_TYPE_INT32);
2173 
2174   set_output_elt(REMOTE_NODELAY, "Remote", "NODELAY", "", "", "%d",
2175 		 &rem_nodelay, 1, 0, NETPERF_TYPE_INT32);
2176 
2177   set_output_elt(REMOTE_CORK, "Remote", "Cork", "", "", "%d",
2178 		 &rem_tcpcork, 1, 0, NETPERF_TYPE_INT32);
2179 
2180   set_output_elt(LOCAL_DRIVER_NAME, "Local", "Driver", "Name", "", "%s",
2181 		 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO,
2182 		 NETPERF_TYPE_CHAR);
2183 
2184   set_output_elt(LOCAL_DRIVER_VERSION, "Local", "Driver", "Version", "", "%s",
2185 		 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO,
2186 		 NETPERF_TYPE_CHAR);
2187 
2188   set_output_elt(LOCAL_DRIVER_FIRMWARE, "Local", "Driver", "Firmware", "",
2189 		 "%s", deprecated_str, 1, OMNI_WANT_LOC_DRVINFO,
2190 		 NETPERF_TYPE_CHAR);
2191 
2192   set_output_elt(LOCAL_DRIVER_BUS, "Local", "Driver", "Bus", "", "%s",
2193 		 deprecated_str, 1, OMNI_WANT_LOC_DRVINFO, NETPERF_TYPE_CHAR);
2194 
2195   set_output_elt(REMOTE_DRIVER_NAME, "Remote", "Driver", "Name", "", "%s",
2196 		 deprecated_str, 1, OMNI_WANT_REM_DRVINFO,
2197 		 NETPERF_TYPE_CHAR);
2198 
2199   set_output_elt(REMOTE_DRIVER_VERSION, "Remote", "Driver", "Version", "",
2200 		 "%s", deprecated_str, 1, OMNI_WANT_REM_DRVINFO,
2201 		 NETPERF_TYPE_CHAR);
2202 
2203   set_output_elt(REMOTE_DRIVER_FIRMWARE, "Remote", "Driver", "Firmware", "",
2204 		 "%s", deprecated_str, 1, OMNI_WANT_REM_DRVINFO,
2205 		 NETPERF_TYPE_CHAR);
2206 
2207   set_output_elt(REMOTE_DRIVER_BUS, "Remote", "Driver", "Bus", "", "%s",
2208 		 deprecated_str, 1, OMNI_WANT_REM_DRVINFO,
2209 		 NETPERF_TYPE_CHAR);
2210 
2211   set_output_elt(LOCAL_INTERFACE_SUBDEVICE, "Local", "Interface", "Subdevice",
2212 		 "", "0x%.4x", &local_interface_subdevice, 1,
2213 		 OMNI_WANT_LOC_IFIDS, NETPERF_TYPE_INT32);
2214 
2215   set_output_elt(LOCAL_INTERFACE_DEVICE, "Local", "Interface", "Device", "",
2216 		 "0x%.4x", &local_interface_device, 1, OMNI_WANT_LOC_IFIDS,
2217 		 NETPERF_TYPE_INT32);
2218 
2219   set_output_elt(LOCAL_INTERFACE_SUBVENDOR, "Local", "Interface", "Subvendor",
2220 		 "", "0x%.4x", &local_interface_subvendor, 1,
2221 		 OMNI_WANT_LOC_IFIDS, NETPERF_TYPE_UINT32);
2222 
2223   set_output_elt(LOCAL_INTERFACE_VENDOR, "Local", "Interface", "Vendor", "",
2224 		 "0x%.4x", &local_interface_vendor, 1, OMNI_WANT_LOC_IFIDS,
2225 		 NETPERF_TYPE_UINT32);
2226 
2227   set_output_elt(REMOTE_INTERFACE_SUBDEVICE, "Remote", "Interface",
2228 		 "Subdevice", "", "0x%.4x", &remote_interface_subdevice, 1,
2229 		 OMNI_WANT_REM_IFIDS, NETPERF_TYPE_UINT32);
2230 
2231   set_output_elt(REMOTE_INTERFACE_DEVICE, "Remote", "Interface", "Device", "",
2232 		 "0x%.4x", &remote_interface_device, 1, OMNI_WANT_REM_IFIDS,
2233 		 NETPERF_TYPE_UINT32);
2234 
2235   set_output_elt(REMOTE_INTERFACE_SUBVENDOR, "Remote", "Interface",
2236 		 "Subvendor", "", "0x%.4x", &remote_interface_subvendor, 1,
2237 		 OMNI_WANT_REM_IFIDS, NETPERF_TYPE_UINT32);
2238 
2239   set_output_elt(REMOTE_INTERFACE_VENDOR, "Remote", "Interface", "Vendor", "",
2240 		 "0x%.4x", &remote_interface_vendor, 1, OMNI_WANT_REM_IFIDS,
2241 		 NETPERF_TYPE_UINT32);
2242 
2243   set_output_elt(LOCAL_INTERFACE_NAME, "Local", "Interface", "Name", "", "%s",
2244 		 deprecated_str, 1, OMNI_WANT_LOC_IFNAME,
2245 		 NETPERF_TYPE_CHAR);
2246 
2247   set_output_elt(REMOTE_INTERFACE_NAME, "Remote", "Interface", "Name", "",
2248 		 "%s", deprecated_str, 1, OMNI_WANT_REM_IFNAME,
2249 		 NETPERF_TYPE_CHAR);
2250 
2251   set_output_elt(LOCAL_INTERFACE_SLOT, "Local", "Interface", "Slot", "", "%s",
2252 		 deprecated_str, 1, OMNI_WANT_LOC_IFSLOT,
2253 		 NETPERF_TYPE_CHAR);
2254 
2255   set_output_elt(REMOTE_INTERFACE_SLOT,  "Remote",  "Interface",  "Slot",  "",
2256 		 "%s",  deprecated_str, 1, OMNI_WANT_REM_IFSLOT,
2257 		 NETPERF_TYPE_CHAR);
2258 
2259   set_output_elt(REMOTE_MACHINE, "Remote", "Machine", "", "", "%s",
2260 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2261 
2262   set_output_elt(REMOTE_VERSION, "Remote", "Version", "", "", "%s",
2263 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2264 
2265   set_output_elt(REMOTE_RELEASE, "Remote", "Release", "", "", "%s",
2266 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2267 
2268   set_output_elt(REMOTE_SYSNAME, "Remote", "Sysname", "", "", "%s",
2269 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2270 
2271   set_output_elt(LOCAL_MACHINE, "Local", "Machine", "", "", "%s",
2272 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2273 
2274   set_output_elt(LOCAL_VERSION, "Local", "Version", "", "", "%s",
2275 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2276 
2277   set_output_elt(LOCAL_RELEASE, "Local", "Release", "", "", "%s",
2278 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2279 
2280   set_output_elt(LOCAL_SYSNAME, "Local", "Sysname", "", "", "%s",
2281 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2282 
2283   set_output_elt(REMOTE_INTERVAL_USECS, "Remote", "Interval", "Usecs", "",
2284 		 "%d", &remote_interval_usecs, 1, 0, NETPERF_TYPE_INT32);
2285 
2286   set_output_elt(REMOTE_INTERVAL_BURST, "Remote", "Interval", "Burst", "",
2287 		 "%d", &remote_interval_burst, 1, 0, NETPERF_TYPE_INT32);
2288 
2289   set_output_elt(LOCAL_SECURITY_ENABLED, "Local", "OS", "Security", "Enabled",
2290 		 "%s", deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2291 
2292   set_output_elt(LOCAL_SECURITY_TYPE, "Local", "OS", "Security", "Type", "%s",
2293 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2294 
2295   set_output_elt(LOCAL_SECURITY_SPECIFIC, "Local", "OS", "Security",
2296 		 "Specific", "%s", deprecated_str, 1, 0,
2297 		 NETPERF_TYPE_CHAR);
2298 
2299   set_output_elt(LOCAL_SECURITY_ENABLED_NUM, "Local", "OS", "Security",
2300 		 "Enabled Num", "%d", &local_security_enabled_num, 1, 0,
2301 		 NETPERF_TYPE_INT32);
2302 
2303   set_output_elt(LOCAL_SECURITY_TYPE_ID, "Local", "OS", "Security", "Type ID",
2304 		 "%d", &local_security_type_id, 1, 0, NETPERF_TYPE_INT32);
2305 
2306   set_output_elt(REMOTE_SECURITY_ENABLED, "Remote", "OS", "Security",
2307 		 "Enabled", "%s", deprecated_str, 1, 0,
2308 		 NETPERF_TYPE_CHAR);
2309 
2310   set_output_elt(REMOTE_SECURITY_TYPE, "Remote", "OS", "Security", "Type",
2311 		 "%s", deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2312 
2313   set_output_elt(REMOTE_SECURITY_SPECIFIC, "Remote", "OS", "Security",
2314 		 "Specific", "%s", deprecated_str, 1, 0,
2315 		 NETPERF_TYPE_CHAR);
2316 
2317   set_output_elt(REMOTE_SECURITY_ENABLED_NUM, "Remote", "OS", "Security",
2318 		 "Enabled", "%d", &remote_security_enabled_num, 1, 0,
2319 		 NETPERF_TYPE_INT32);
2320 
2321   set_output_elt(REMOTE_SECURITY_TYPE_ID, "Remote", "OS", "Security", "Type",
2322 		 "%d", &remote_security_type_id, 1, 0, NETPERF_TYPE_INT32);
2323 
2324   set_output_elt(LOCAL_INTERVAL_USECS, "Local", "Interval", "Usecs", "", "%d",
2325 		 &interval_usecs, 1, 0, NETPERF_TYPE_INT32);
2326 
2327   set_output_elt(LOCAL_INTERVAL_BURST, "Local", "Interval", "Burst", "", "%d",
2328 		 &interval_burst, 1, 0, NETPERF_TYPE_INT32);
2329 
2330   set_output_elt(REMOTE_SYSTEM_MODEL, "Remote", "System", "Model", "", "%s",
2331 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2332 
2333   set_output_elt(REMOTE_CPU_MODEL, "Remote", "CPU", "Model", "", "%s",
2334 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2335 
2336   set_output_elt(REMOTE_CPU_FREQUENCY, "Remote", "CPU", "Frequency", "MHz",
2337 		 "%d", &remote_cpu_frequency, 1, 0, NETPERF_TYPE_INT32);
2338 
2339   set_output_elt(LOCAL_SYSTEM_MODEL, "Local", "System", "Model", "", "%s",
2340 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2341 
2342   set_output_elt(LOCAL_CPU_MODEL, "Local", "CPU", "Model", "", "%s",
2343 		 deprecated_str, 1, 0, NETPERF_TYPE_CHAR);
2344 
2345   set_output_elt(LOCAL_CPU_FREQUENCY, "Local", "CPU", "Frequency", "MHz", "%d",
2346 		 &local_cpu_frequency, 1, 0, NETPERF_TYPE_INT32);
2347 
2348   set_output_elt(MIN_LATENCY, "Minimum", "Latency", "Microseconds", "", "%d",
2349 		 &min_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32);
2350 
2351   set_output_elt(MAX_LATENCY, "Maximum", "Latency", "Microseconds", "", "%d",
2352 		 &max_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32);
2353 
2354   set_output_elt(P50_LATENCY, "50th", "Percentile", "Latency", "Microseconds",
2355 		 "%d", &p50_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32);
2356 
2357   set_output_elt(P90_LATENCY, "90th", "Percentile", "Latency", "Microseconds",
2358 		 "%d", &p90_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32);
2359 
2360   set_output_elt(P99_LATENCY, "99th", "Percentile", "Latency", "Microseconds",
2361 		 "%d", &p99_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_INT32);
2362 
2363   set_output_elt(MEAN_LATENCY, "Mean", "Latency", "Microseconds", "", "%.2f",
2364 		 &mean_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_DOUBLE);
2365 
2366   set_output_elt(STDDEV_LATENCY, "Stddev", "Latency", "Microseconds", "",
2367 		 "%.2f", &stddev_latency, 0, OMNI_WANT_STATS, NETPERF_TYPE_DOUBLE);
2368 
2369   set_output_elt(LOCAL_SOCKET_PRIO, "Local", "Socket", "Priority", "", "%d",
2370 		 &local_socket_prio, 1, 0, NETPERF_TYPE_INT32);
2371 
2372   set_output_elt(REMOTE_SOCKET_PRIO, "Remote", "Socket", "Priority", "", "%d"
2373 		 , &remote_socket_prio, 1, 0, NETPERF_TYPE_INT32);
2374 
2375   set_output_elt(LOCAL_SOCKET_TOS, "Local", "Socket", "TOS", "", "0x%.2x",
2376 		 &local_socket_tos, 1, 0, NETPERF_TYPE_INT32);
2377 
2378   set_output_elt(REMOTE_SOCKET_TOS, "Remote", "Socket", "TOS", "", "0x%.2x",
2379 		 &remote_socket_tos, 1, 0, NETPERF_TYPE_INT32);
2380 
2381   set_output_elt(LOCAL_CONG_CONTROL, "Local", "Congestion", "Control",
2382 		 "Algorithm", "%s", local_cong_control, 0,
2383 		 OMNI_WANT_LOC_CONG, NETPERF_TYPE_CHAR);
2384 
2385   set_output_elt(REMOTE_CONG_CONTROL, "Remote", "Congestion", "Control",
2386 		 "Algorithm", "%s", remote_cong_control, 0,
2387 		 OMNI_WANT_REM_CONG, NETPERF_TYPE_CHAR);
2388 
2389   set_output_elt(LOCAL_FILL_FILE, "Local", "Fill", "File", "", "%s",
2390 		 local_fill_file, 0, 0, NETPERF_TYPE_CHAR);
2391 
2392   set_output_elt(REMOTE_FILL_FILE, "Remote", "Fill", "File", "", "%s",
2393 		 remote_fill_file, 0, 0, NETPERF_TYPE_CHAR);
2394 
2395   set_output_elt(OUTPUT_END, "This", "Is", "The", "End", "%s",
2396 		 NULL, 0, 0, NETPERF_TYPE_CHAR);
2397 
2398 }
2399 
2400 void
print_omni_init()2401 print_omni_init() {
2402 
2403   int i,j;
2404 
2405   if (debug) {
2406     fprintf(where,"%s entered\n",
2407 	    __FUNCTION__);
2408     fflush(where);
2409   }
2410 
2411   /* why is this before the if you ask? because some of the output
2412      specifiers are char * rather than char[] and when I wanted to
2413      start setting output_group flags I was needing to call
2414      print_omni_init() before the char * 's were malloced, which meant
2415      the netperf_output_source got NULL pointers.  there is
2416      undoubtedly a cleaner way to do all this. raj 20110629 */
2417 
2418   print_omni_init_list();
2419 
2420   if (printing_initialized) return;
2421 
2422   printing_initialized = 1;
2423 
2424 
2425   /* belts and suspenders */
2426   for (j = 0; j < NETPERF_MAX_BLOCKS; j++)
2427     for (i = 0; i < NETPERF_OUTPUT_MAX; i++)
2428       output_list[j][i] = OUTPUT_END;
2429 
2430 
2431   if (output_selection_spec) {
2432       parse_output_selection(output_selection_spec);
2433   }
2434   else {
2435       set_output_list_by_test();
2436   }
2437 
2438 }
2439 
2440 /* why? because one cannot simply pass a pointer to snprintf - well
2441    except when it is expecting one... */
2442 int
my_snprintf(char * buffer,size_t size,netperf_output_elt_t * output_elt)2443 my_snprintf(char *buffer, size_t size, netperf_output_elt_t *output_elt)
2444 {
2445   switch (output_elt->output_type) {
2446   case NETPERF_TYPE_CHAR:
2447     return snprintf(buffer, size,
2448 		    output_elt->format,
2449 		    (char *)output_elt->display_value);
2450     break;
2451   case NETPERF_TYPE_INT32:
2452     return snprintf(buffer, size,
2453 		    output_elt->format,
2454 		    *(int *)(output_elt->display_value));
2455     break;
2456   case NETPERF_TYPE_UINT32:
2457     return snprintf(buffer, size,
2458 		    output_elt->format,
2459 		    *(unsigned int *)(output_elt->display_value));
2460     break;
2461   case NETPERF_TYPE_INT64:
2462     return snprintf(buffer, size,
2463 		    output_elt->format,
2464 		    *(long long *)(output_elt->display_value));
2465     break;
2466   case NETPERF_TYPE_UINT64:
2467     return snprintf(buffer, size,
2468 		    output_elt->format,
2469 		    *(unsigned long long *)(output_elt->display_value));
2470     break;
2471   case NETPERF_TYPE_FLOAT:
2472     return snprintf(buffer, size,
2473 		    output_elt->format,
2474 		    *(float *)(output_elt->display_value));
2475     break;
2476   case NETPERF_TYPE_DOUBLE:
2477     return snprintf(buffer, size,
2478 		    output_elt->format,
2479 		    *(double *)(output_elt->display_value));
2480     break;
2481   default:
2482     fprintf(stderr,
2483 	    "Unknown/unsupported output_elt output_type of %d\n",
2484 	    output_elt->output_type);
2485     fflush(stderr);
2486     exit(-1);
2487   }
2488 }
2489 
2490 void
print_omni_csv()2491 print_omni_csv()
2492 {
2493 
2494   int i,j,k,buflen,vallen;
2495 
2496   char *hdr1 = NULL;
2497   char *val1 = NULL;
2498   char *h1 = NULL;
2499   char *v1 = NULL;
2500   char tmpval[1024];
2501 
2502   buflen = 0;
2503   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
2504     for (j = 0;
2505 	 ((j < NETPERF_OUTPUT_MAX) &&
2506 	  (output_list[i][j] != OUTPUT_END));
2507 	 j++) {
2508       if ((netperf_output_source[output_list[i][j]].format != NULL) &&
2509 	  (netperf_output_source[output_list[i][j]].display_value != NULL)) {
2510 	vallen =
2511 	  my_snprintf(tmpval,
2512 		      1024,
2513 		      &(netperf_output_source[output_list[i][j]]));
2514 	if (vallen == -1) {
2515 	  fprintf(where,"my_snprintf failed on %s with format %s\n",
2516 		  netperf_output_enum_to_str(j),
2517 		  netperf_output_source[output_list[i][j]].format);
2518 	  fflush(where);
2519 	}
2520 	vallen += 1; /* forget not the terminator */
2521       }
2522       else
2523 	vallen = 0;
2524 
2525       if (vallen >
2526 	  netperf_output_source[output_list[i][j]].tot_line_len)
2527 	netperf_output_source[output_list[i][j]].tot_line_len = vallen;
2528 
2529       buflen +=
2530 	netperf_output_source[output_list[i][j]].tot_line_len;
2531     }
2532   }
2533 
2534   if (print_headers) hdr1 = malloc(buflen + 1);
2535   val1 = malloc(buflen + 1);
2536 
2537   if (((hdr1 == NULL) && (print_headers)) ||
2538       (val1 == NULL)) {
2539     fprintf(where,"unable to allocate output buffers\n");
2540     fflush(where);
2541     exit(-1);
2542   }
2543 
2544   if (print_headers) memset(hdr1,' ',buflen + 1);
2545   memset(val1,' ',buflen + 1);
2546 
2547   /* ostensibly, we now "know" that we have enough space in all our
2548      strings, and we have spaces where we want them etc */
2549   h1 = hdr1;
2550   v1 = val1;
2551   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
2552     for (j = 0;
2553 	 ((j < NETPERF_OUTPUT_MAX) &&
2554 	  (output_list[i][j] != OUTPUT_END));
2555 	 j++) {
2556       int len;
2557       len = 0;
2558       if (print_headers) {
2559 	for (k = 0; ((k < 4) &&
2560 		     (NULL !=
2561 		      netperf_output_source[output_list[i][j]].line[k]) &&
2562 		     (strcmp("",netperf_output_source[output_list[i][j]].line[k]))); k++) {
2563 
2564 	  len = sprintf(h1,
2565 			"%s",
2566 			netperf_output_source[output_list[i][j]].line[k]);
2567 	  *(h1 + len) = ' ';
2568 	  /* now move to the next starting column. for csv we aren't worried
2569 	     about alignment between the header and the value lines */
2570 	  h1 += len + 1;
2571 	}
2572 	*(h1 - 1) = ',';
2573       }
2574       if ((netperf_output_source[output_list[i][j]].format != NULL) &&
2575 	  (netperf_output_source[output_list[i][j]].display_value != NULL)) {
2576 	/* tot_line_len is bogus here, but should be "OK" ? */
2577 	len = my_snprintf(v1,
2578 			  netperf_output_source[output_list[i][j]].tot_line_len,
2579 			  &(netperf_output_source[output_list[i][j]]));
2580 
2581 	/* nuke the trailing \n" from the string routine.  */
2582 	*(v1 + len) = ',';
2583 	v1 += len + 1;
2584       }
2585       else {
2586 	/* we need a ',' even if there is no value */
2587 	*v1 = ',';
2588 	v1 += 2;
2589       }
2590     }
2591   }
2592 
2593   /* ok, _now_ null terminate each line by nuking the last comma.  do
2594      we have an OBOB here? */
2595   if (print_headers) *(h1-1) = 0;
2596   *(v1-1) = 0;
2597   /* and now spit it out, but only if it is going to have something
2598      in it. we don't want a bunch of blank lines or nulls...  */
2599   if (output_list[0][0] != OUTPUT_END) {
2600     if (print_headers) printf("%s\n",hdr1);
2601     printf("%s\n",val1);
2602   }
2603 
2604   if (hdr1 != NULL) free(hdr1);
2605   if (val1 != NULL) free(val1);
2606 
2607 }
2608 
2609 void
print_omni_keyword()2610 print_omni_keyword()
2611 {
2612   /* this one should be the simplest of all - no buffers to allocate,
2613      just spit it all out. raj 20080805 */
2614 
2615   int i,j;
2616   char tmpval[1024];
2617   int vallen;
2618 
2619   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
2620     for (j = 0;
2621 	 ((j < NETPERF_OUTPUT_MAX) &&
2622 	  (output_list[i][j] != OUTPUT_END));
2623 	 j++) {
2624       if ((netperf_output_source[output_list[i][j]].format != NULL) &&
2625 	  (netperf_output_source[output_list[i][j]].display_value != NULL)) {
2626 	vallen =
2627 	  my_snprintf(tmpval,
2628 		      1024,
2629 		      &(netperf_output_source[output_list[i][j]]));
2630 	if (vallen == -1) {
2631 	  snprintf(tmpval,
2632 		   1024,
2633 		   "my_snprintf failed with format %s\n",
2634 		   netperf_output_source[output_list[i][j]].format);
2635 	}
2636 	fprintf(where,
2637 		"%s=%s\n",netperf_output_enum_to_str(output_list[i][j]),
2638 		tmpval);
2639       }
2640     }
2641   }
2642   fflush(where);
2643 }
2644 
2645 void
print_omni_human()2646 print_omni_human()
2647 {
2648 
2649   int i,j,k,buflen,buflen_max;
2650 
2651   char *hdr[4];
2652   char *val1 = NULL;
2653   char tmpval[1024];  /* excessive, but we may have the command line */
2654   int  vallen;
2655 
2656   for (k = 0; k < 4; k ++) {
2657     hdr[k] = NULL;
2658   }
2659 
2660   /* decisions, decisions... walk the list twice to only need to
2661      allocate the charcter buffers once, or walk it once and possibly
2662      reallocate them as I go... oh, lets walk it twice just for fun to
2663      start. since only now do we know that the values are around to be
2664      printed, we should try the snprintf for the value and see how
2665      much space it wants and update max_line_len accordingly */
2666   buflen_max = 0;
2667   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
2668     buflen = 0;
2669     for (j = 0;
2670 	 ((j < NETPERF_OUTPUT_MAX) &&
2671 	  (output_list[i][j] != OUTPUT_END));
2672 	 j++) {
2673       if ((netperf_output_source[output_list[i][j]].format != NULL) &&
2674 	  (netperf_output_source[output_list[i][j]].display_value !=
2675 	   NULL))
2676 	/* need to count the \n */
2677 	vallen = my_snprintf(tmpval,
2678 			     1024,
2679 			     &(netperf_output_source[output_list[i][j]])) + 1;
2680       else
2681 	vallen = 0;
2682 
2683       if (vallen >
2684 	  netperf_output_source[output_list[i][j]].max_line_len)
2685 	netperf_output_source[output_list[i][j]].max_line_len = vallen;
2686 
2687       buflen +=
2688 	netperf_output_source[output_list[i][j]].max_line_len + 1;
2689     }
2690 
2691     if (buflen > buflen_max)
2692       buflen_max = buflen;
2693   }
2694 
2695   /* more belts and suspenders */
2696   for (k = 0; (k < 4) && (print_headers); k++) {
2697     hdr[k] = malloc(buflen_max+1);
2698   }
2699   val1 = malloc(buflen_max+1);
2700 
2701   /* we could probably be more succinct here but perhaps the compiler
2702      can figure that out for us :) */
2703   for (k = 0; (k < 4) && (print_headers); k++) {
2704     if (hdr[k] == NULL) {
2705       fprintf(where,"Unable to allocate output buffers\n");
2706       fflush(where);
2707       exit(-1);
2708     }
2709   }
2710 
2711   /* ostensibly, we now "know" that we have enough space in all our
2712      strings, and we have spaces where we want them etc */
2713   for (i = 0; i < NETPERF_MAX_BLOCKS; i++) {
2714     char *h[4];
2715     char *v1 = val1;
2716 
2717     for (k = 0; k < 4; k++) h[k] = hdr[k];
2718 
2719     /* we want to blank things out each time since we skip around a lot */
2720     for (k = 0; (k < 4) && (print_headers); k++) {
2721       memset(hdr[k],' ',buflen_max+1);
2722     }
2723     memset(val1,' ',buflen_max+1);
2724 
2725 
2726     for (j = 0;
2727 	 ((j < NETPERF_OUTPUT_MAX) &&
2728 	  (output_list[i][j] != OUTPUT_END));
2729 	 j++) {
2730       if (print_headers) {
2731 	for (k = 0; k < 4; k++) {
2732 	  memcpy(h[k],
2733 		 netperf_output_source[output_list[i][j]].line[k],
2734 		 strlen(netperf_output_source[output_list[i][j]].line[k]));
2735 	}
2736       }
2737       if ((netperf_output_source[output_list[i][j]].format != NULL) &&
2738 	  (netperf_output_source[output_list[i][j]].display_value != NULL)) {
2739 	int len;
2740 	len = my_snprintf(v1,
2741 			  netperf_output_source[output_list[i][j]].max_line_len,
2742 			  &(netperf_output_source[output_list[i][j]]));
2743 	/* nuke the trailing \n" from the string routine.  */
2744 	*(v1 + len) = ' ';
2745       }
2746       /* now move to the next starting column */
2747     for (k = 0; (k < 4) && (print_headers); k++) {
2748 	h[k] +=
2749 	  netperf_output_source[output_list[i][j]].max_line_len + 1;
2750       }
2751       v1 += netperf_output_source[output_list[i][j]].max_line_len + 1;
2752     }
2753     /* ok, _now_ null terminate each line.  do we have an OBOB here? */
2754     for (k = 0; (k < 4) && (print_headers); k++) {
2755       *h[k] = 0;
2756     }
2757     *v1 = 0;
2758     /* and now spit it out, but only if it is going to have something
2759        in it. we don't want a bunch of blank lines or nulls... at some
2760      point we might want to work backwards collapsine whitespace from
2761      the right but for now, we won't bother */
2762     if (output_list[i][0] != OUTPUT_END) {
2763       if (i > 0) printf("\n"); /* we want a blank line between blocks ? */
2764       for (k = 0; (k < 4) && (print_headers); k++) {
2765 	printf("%s\n",hdr[k]);
2766       }
2767       printf("%s\n",val1);
2768     }
2769   };
2770   for (k = 0; k < 4; k++) {
2771     if (hdr[k] != NULL) free(hdr[k]);
2772   }
2773 }
2774 
2775 void
print_omni()2776 print_omni()
2777 {
2778 
2779   print_omni_init();
2780 
2781   if (debug > 2)
2782     dump_netperf_output_source(where);
2783 
2784   switch (netperf_output_mode) {
2785   case CSV:
2786     print_omni_csv();
2787     break;
2788   case KEYVAL:
2789     print_omni_keyword();
2790     break;
2791   case HUMAN:
2792     print_omni_human();
2793     break;
2794   default:
2795     fprintf(where,"Yo Rick! There is a bug in netperf_output_mode!\n");
2796     fflush(where);
2797     exit(-1);
2798   }
2799 
2800 }
2801 /* for the next few routines (connect, accept, send, recv,
2802    disconnect/close) we will use a return of -1 to mean times up, -2
2803    to mean a transient error (eg ENOBUFS on a UDP send call) and -3 to
2804    mean hard error.  this means it is ok for the connect routine to
2805    return a 0 (zero) if that happens to be the fd/SOCKET we get and in
2806    theory we will be able to support zero-length messages on those
2807    protocols which support it.  all in theory of course. raj
2808    2008-01-09 */
2809 
2810 int
connect_data_socket(SOCKET send_socket,struct addrinfo * remote_res,int dont_give_up)2811 connect_data_socket(SOCKET send_socket, struct addrinfo *remote_res, int dont_give_up)
2812 {
2813   int ret;
2814 
2815   /* Connect up to the remote port on the data socket  */
2816   if ((ret = connect(send_socket,
2817 		     remote_res->ai_addr,
2818 		     remote_res->ai_addrlen)) == INVALID_SOCKET) {
2819     if (SOCKET_EINTR(ret))  {
2820       /* we interpret this to mean that the test is supposed to be
2821 	 over, so return a value of -1 to the caller */
2822       return -1;
2823     }
2824     if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret) || dont_give_up) {
2825       /* likely something our explicit bind() would have caught in
2826 	 the past, so go get another port, via create_data_socket.
2827 	 yes, this is a bit more overhead than before, but the
2828 	 condition should be rather rare. we only get a new port if
2829 	 this was a connection-including test like TCP_CRR or
2830 	 TCP_CC. Otherwise we need to return an error. raj
2831 	 2008-01-08 */
2832       return -2;
2833     }
2834     else
2835       /* -3 means there was an error */
2836       return -3;
2837   }
2838   return 0;
2839 }
2840 
2841 static
send_pktinfo(SOCKET data_socket,char * buffer,int len,struct sockaddr * destination,int destlen)2842 int send_pktinfo(SOCKET data_socket, char *buffer, int len, struct sockaddr *destination, int destlen) {
2843 #ifdef IP_PKTINFO
2844   struct msghdr msg;
2845   struct iovec iovec[1];
2846   char msg_control[512];
2847   struct cmsghdr *cmsg;
2848   int cmsg_space = 0;
2849 
2850   iovec[0].iov_base = buffer;
2851   iovec[0].iov_len = len;
2852   msg.msg_name = destination;
2853   msg.msg_namelen = destlen;
2854   msg.msg_iov = iovec;
2855   msg.msg_iovlen = 1;
2856   msg.msg_control = msg_control;
2857   msg.msg_controllen = sizeof(msg_control);
2858   msg.msg_flags = 0;
2859 
2860   cmsg = CMSG_FIRSTHDR(&msg);
2861   if (have_pktinfo) {
2862     cmsg->cmsg_level = IPPROTO_IP;
2863     cmsg->cmsg_type = IP_PKTINFO;
2864     cmsg->cmsg_len = CMSG_LEN(sizeof(in_pktinfo));
2865     *(struct in_pktinfo*)CMSG_DATA(cmsg) = in_pktinfo;
2866     cmsg_space += CMSG_SPACE(sizeof(in_pktinfo));
2867   }
2868   msg.msg_controllen = cmsg_space;
2869   return sendmsg(data_socket, &msg, 0);
2870 #else
2871   return -1;
2872 #endif /* IP_PKTINFO */
2873 }
2874 
2875 
2876 int
send_data(SOCKET data_socket,struct ring_elt * send_ring,uint32_t bytes_to_send,struct sockaddr * destination,int destlen,int protocol)2877 send_data(SOCKET data_socket, struct ring_elt *send_ring, uint32_t bytes_to_send, struct sockaddr *destination, int destlen, int protocol) {
2878 
2879   int len;
2880 
2881   /* if the user has supplied a destination, we use sendto, otherwise
2882      we use send.  we ass-u-me blocking operations always, so no need
2883      to check for eagain or the like. */
2884 
2885   if (debug > 2) {
2886     fprintf(where,
2887 	    "%s sock %d, ring elt %p, bytes %d, dest %p, len %d\n",
2888 	    __FUNCTION__,
2889 	    data_socket,
2890 	    send_ring,
2891 	    bytes_to_send,
2892 	    destination,
2893 	    destlen);
2894     fflush(where);
2895   }
2896 
2897   if (destination) {
2898     if (have_pktinfo) {
2899       len = send_pktinfo(data_socket,
2900 			 send_ring->buffer_ptr,
2901 			 bytes_to_send,
2902 			 destination,
2903 			 destlen);
2904     }
2905     else {
2906       len = sendto(data_socket,
2907 		   send_ring->buffer_ptr,
2908 		   bytes_to_send,
2909 #if defined(MSG_FASTOPEN)
2910 		   (use_fastopen && protocol == IPPROTO_TCP) ? MSG_FASTOPEN : 0,
2911 #else
2912 		   0,
2913 #endif
2914 		   destination,
2915 		   destlen);
2916     }
2917   }
2918   else {
2919     if (!use_write) {
2920       len = send(data_socket,
2921 		 send_ring->buffer_ptr,
2922 		 bytes_to_send,
2923 		 0);
2924     }
2925     else {
2926 #ifndef WIN32
2927       len = write(data_socket,
2928 		  send_ring->buffer_ptr,
2929 		  bytes_to_send);
2930 #else
2931       fprintf(where,"I'm sorry Dave I cannot write() under Windows\n");
2932       fflush(where);
2933       return -3;
2934 #endif
2935     }
2936   }
2937   if(len != bytes_to_send) {
2938     /* don't forget that some platforms may do a partial send upon
2939        receipt of the interrupt and not return an EINTR... */
2940     if (SOCKET_EINTR(len) || (len >= 0))
2941       {
2942 	/* we hit the end of a  timed test. */
2943 	return -1;
2944       }
2945     /* if this is UDP it is possible to receive an ENOBUFS on the send
2946        call and it would not be a fatal error.  of course if we were
2947        to return 0 then it would make the test think it was over when
2948        it really wasn't.  the question becomes what to do.  for the
2949        time being, the answer will likely be to return something like
2950        -2 to indicate a non-fatal error happened on the send and let
2951        the caller figure it out :) we won't actually check to see if
2952        this is UDP - it is the author's experience in many, Many, MANY
2953        years that the only time an ENOBUFS has been returned in a
2954        netperf test has been with UDP.  famous last words :) */
2955     if (errno == ENOBUFS)
2956       return -2;
2957     else {
2958       fprintf(where,"%s: data send error: %s (errno %d)\n",
2959 	      __FUNCTION__, strerror(errno), errno);
2960       return -3;
2961     }
2962   }
2963   return len;
2964 }
2965 
2966 #if defined(__linux)
2967 static int
recv_data_no_copy(SOCKET data_socket,struct ring_elt * recv_ring,uint32_t bytes_to_recv,struct sockaddr * source,netperf_socklen_t * sourcelen,uint32_t flags,uint32_t * num_receives)2968 recv_data_no_copy(SOCKET data_socket, struct ring_elt *recv_ring, uint32_t bytes_to_recv, struct sockaddr *source, netperf_socklen_t *sourcelen, uint32_t flags, uint32_t *num_receives) {
2969 
2970 #ifndef SPLICE_F_MOVE
2971 # define SPLICE_F_MOVE 0x01
2972 #endif
2973 #ifndef SPLICE_F_NONBLOCK
2974 # define SPLICE_F_NONBLOCK 0x02
2975 #endif
2976 
2977   static int pfd[2] = {-1, -1};
2978   static int fdnull = -1;
2979 
2980 
2981   char *temp_message_ptr;
2982   int bytes_left;
2983   int bytes_recvd;
2984   int my_recvs;
2985   int my_flags = SPLICE_F_MOVE | SPLICE_F_NONBLOCK; /* values
2986 						       suggested by
2987 						       Eric Dumazet */
2988   int ret;
2989 
2990   if (pfd[0] == -1) {
2991     if (pipe(pfd)) {
2992       fprintf(where,
2993 	      "%s pipe call failed with errno %d '%s'\n",
2994 	      __FUNCTION__,
2995 	      errno,
2996 	      strerror(errno));
2997       return -4;  /* this will cause recv_data to do things the
2998 		     old-fashioned way for the test */
2999     }
3000     if ((fdnull = open("/dev/null",O_WRONLY)) == -1) {
3001       fprintf(where,
3002 	      "%s open call failed with errno %d '%s'\n",
3003 	      __FUNCTION__,
3004 	      errno,
3005 	      strerror(errno));
3006       return -4;
3007     }
3008   }
3009 
3010   /* receive data off the data_socket, ass-u-me-ing a blocking socket
3011      all the way!-) 2008-01-08 */
3012   my_recvs = 0;
3013   bytes_left = bytes_to_recv;
3014 
3015   if (debug > 1) {
3016     fprintf(where,
3017 	    "%s sock %d, ring elt %p, bytes %d, source %p, srclen %d, flags %x, num_recv %p\n",
3018 	    __FUNCTION__,
3019 	    data_socket,
3020 	    recv_ring,
3021 	    bytes_to_recv,
3022 	    source,
3023 	    (source != NULL) ? *sourcelen : -1,
3024 	    flags,
3025 	    num_receives);
3026     fflush(where);
3027   }
3028   do {
3029 
3030     bytes_recvd = splice(data_socket,
3031 			 NULL,
3032 			 pfd[1],
3033 			 NULL,
3034 			 bytes_left,
3035 			 my_flags);
3036 
3037 
3038     if (bytes_recvd > 0) {
3039       /* per Eric Dumazet, we should just let this second splice call
3040 	 move as many bytes as it can and not worry about how much.
3041 	 this should make the call more robust when made on a system
3042 	 under memory pressure */
3043       splice(pfd[0], NULL, fdnull, NULL, 1 << 30, my_flags);
3044       bytes_left -= bytes_recvd;
3045     }
3046     else {
3047       break;
3048     }
3049     my_recvs++; /* should the pair of splices count as one? */
3050   } while ((bytes_left > 0) && (flags & NETPERF_WAITALL));
3051 
3052   *num_receives = my_recvs;
3053 
3054   /* OK, we are out of the loop - now what? */
3055   if (bytes_recvd < 0) {
3056     /* did the timer hit, or was there an error? */
3057     if (SOCKET_EINTR(bytes_recvd))
3058       {
3059 	/* We hit the end of a timed test. */
3060 	return -1;
3061       }
3062     /* it was a hard error */
3063     return -3;
3064   }
3065 
3066 
3067   /* this looks a little funny, but should be correct.  if we had
3068      NETPERF_WAITALL set and we got here, it means we got all the
3069      bytes of the request/response.  otherwise we would have hit the
3070      error or end of test cases.  if NETPERF_WAITALL isn't set, this
3071      is a STREAM test, and we will have only made one call to recv, so
3072      bytes_recvd will be accurate. */
3073   if (bytes_left)
3074     return bytes_recvd;
3075   else
3076     return bytes_to_recv;
3077 
3078 }
3079 
3080 #endif
3081 
3082 static
recv_pktinfo(SOCKET data_socket,char * message_ptr,int bytes_to_recv,int my_flags,struct sockaddr * source,netperf_socklen_t * sourcelen)3083 int recv_pktinfo(SOCKET data_socket, char *message_ptr, int bytes_to_recv,  int my_flags, struct sockaddr *source, netperf_socklen_t *sourcelen) {
3084 
3085 #ifdef IP_PKTINFO
3086   struct iovec  my_iovec;
3087   struct msghdr my_header;
3088   struct cmsghdr *cmsg;
3089   struct in_pktinfo *pktinfo;
3090 
3091   char control_buf[512];
3092   int onoff = 1;
3093   int ret;
3094 
3095   my_iovec.iov_base = message_ptr;
3096   my_iovec.iov_len = bytes_to_recv;
3097 
3098   my_header.msg_name = source;
3099   my_header.msg_namelen = *sourcelen;
3100   my_header.msg_iov = &my_iovec;
3101   my_header.msg_iovlen = 1;
3102   my_header.msg_control = control_buf;
3103   my_header.msg_controllen = sizeof(control_buf);
3104 
3105   /* not going to bother checking, if it doesn't work we are no
3106      worse-off than we were before. we are going to ignore IPv6 for
3107      the time being */
3108   setsockopt(data_socket, IPPROTO_IP, IP_PKTINFO, &onoff, sizeof(onoff));
3109 
3110   ret = recvmsg(data_socket, &my_header, 0);
3111 
3112   if (ret >= 0) {
3113     struct sockaddr_in me;
3114     struct sockaddr_in clear;
3115     netperf_socklen_t melen = sizeof(me);
3116     for (cmsg = CMSG_FIRSTHDR(&my_header);
3117 	 cmsg != NULL;
3118 	 cmsg = CMSG_NXTHDR(&my_header, cmsg)) {
3119       if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
3120 	in_pktinfo = *(struct in_pktinfo *)CMSG_DATA(cmsg);
3121 	have_pktinfo = 1;
3122       }
3123     }
3124   }
3125 
3126   onoff = 0;
3127   setsockopt(data_socket, IPPROTO_IP, IP_PKTINFO, &onoff, sizeof(onoff));
3128 
3129   return ret;
3130 #else
3131   return -1;
3132 #endif
3133 }
3134 
3135 
3136 int
recv_data(SOCKET data_socket,struct ring_elt * recv_ring,uint32_t bytes_to_recv,struct sockaddr * source,netperf_socklen_t * sourcelen,uint32_t flags,uint32_t * num_receives)3137 recv_data(SOCKET data_socket, struct ring_elt *recv_ring, uint32_t bytes_to_recv, struct sockaddr *source, netperf_socklen_t *sourcelen, uint32_t flags, uint32_t *num_receives) {
3138 
3139   char *temp_message_ptr;
3140   int bytes_left;
3141   int bytes_recvd;
3142   int my_recvs;
3143   int my_flags = 0; /* will we one day want to set MSG_WAITALL? */
3144 
3145 #if defined(__linux)
3146   int ret;
3147   if (loc_rcvavoid == 1) {
3148     ret = recv_data_no_copy(data_socket, recv_ring, bytes_to_recv, source, sourcelen, flags, num_receives);
3149     if (ret != -4)
3150       return ret;
3151     else
3152       loc_rcvavoid = 0;
3153   }
3154 #endif
3155 
3156   /* receive data off the data_socket, ass-u-me-ing a blocking socket
3157      all the way!-) 2008-01-08 */
3158   my_recvs = 0;
3159   bytes_left = bytes_to_recv;
3160   temp_message_ptr  = recv_ring->buffer_ptr;
3161 
3162   if (debug > 1) {
3163     fprintf(where,
3164 	    "%s sock %d, ring elt %p, bytes %d, source %p, srclen %d, flags %x, num_recv %p\n",
3165 	    __FUNCTION__,
3166 	    data_socket,
3167 	    recv_ring,
3168 	    bytes_to_recv,
3169 	    source,
3170 	    (source != NULL) ? *sourcelen : -1,
3171 	    flags,
3172 	    num_receives);
3173     fflush(where);
3174   }
3175   do {
3176     if (source) {
3177       /* call recvfrom it does look a little silly here inside the do
3178 	 while, but I think it is ok - a UDP or other DGRAM or
3179 	 SEQPACKET (?) socket, which should be the only time we
3180 	 pass-in a source pointer will have a semantic that should get
3181 	 us out of the dowhile on the first call anyway.  if it
3182 	 turns-out not to be the case, then we can hoist the if above
3183 	 the do and put the dowhile in the else. */
3184       if (use_pktinfo) {
3185 	bytes_recvd = recv_pktinfo(data_socket,
3186 				   temp_message_ptr,
3187 				   bytes_left,
3188 				   my_flags,
3189 				   source,
3190 				   sourcelen);
3191 	use_pktinfo = 0;
3192       }
3193       else {
3194 	bytes_recvd = recvfrom(data_socket,
3195 			       temp_message_ptr,
3196 			       bytes_left,
3197 			       my_flags,
3198 			       source,
3199 			       sourcelen);
3200       }
3201     }
3202     else {
3203       /* just call recv */
3204       bytes_recvd = recv(data_socket,
3205 			 temp_message_ptr,
3206 			 bytes_left,
3207 			 my_flags);
3208     }
3209     if (bytes_recvd > 0) {
3210       bytes_left -= bytes_recvd;
3211       temp_message_ptr += bytes_recvd;
3212     }
3213     else {
3214       break;
3215     }
3216     my_recvs++;
3217   } while ((bytes_left > 0) && (flags & NETPERF_WAITALL));
3218 
3219   *num_receives = my_recvs;
3220 
3221   /* OK, we are out of the loop - now what? */
3222   if (bytes_recvd < 0) {
3223     /* did the timer hit, or was there an error? */
3224     if (SOCKET_EINTR(bytes_recvd))
3225       {
3226 	/* We hit the end of a timed test. */
3227 	return -1;
3228       }
3229     if (SOCKET_EAGAIN(bytes_recvd) ||
3230 	SOCKET_EWOULDBLOCK(bytes_recvd)) {
3231       return -2;
3232     }
3233     /* it was a hard error */
3234     return -3;
3235   }
3236 
3237 
3238   /* this looks a little funny, but should be correct.  if we had
3239      NETPERF_WAITALL set and we got here, it means we got all the
3240      bytes of the request/response.  otherwise we would have hit the
3241      error or end of test cases.  if NETPERF_WAITALL isn't set, this
3242      is a STREAM test, and we will have only made one call to recv, so
3243      bytes_recvd will be accurate. */
3244   if (bytes_left)
3245     return bytes_recvd;
3246   else
3247     return bytes_to_recv;
3248 
3249 }
3250 
3251 
3252 int
close_data_socket(SOCKET data_socket,struct sockaddr * peer,int peerlen,int protocol)3253 close_data_socket(SOCKET data_socket, struct sockaddr *peer, int peerlen, int protocol)
3254 {
3255 
3256   int ret;
3257   char buffer[4];
3258 
3259   if (debug) {
3260     fprintf(where,
3261 	    "%s sock %d peer %p peerlen %d protocol %d\n",
3262 	    __FUNCTION__,
3263 	    data_socket,
3264 	    peer,
3265 	    peerlen,
3266 	    protocol);
3267     fflush(where);
3268   }
3269 
3270   if (protocol == IPPROTO_UDP) {
3271     /* try to give the remote a signal. what this means if we ever
3272        wanted to actually send zero-length messages remains to be seen
3273        :)  */
3274     int i;
3275     for (i = 0; i < 3; i++) {
3276       if (peer)
3277 	ret = sendto(data_socket,
3278 		     buffer,
3279 		     0,
3280 		     0,
3281 		     peer,
3282 		     peerlen);
3283       else
3284 	ret = send(data_socket,
3285 		   buffer,
3286 		   0,
3287 		   0);
3288       if (SOCKET_EINTR(ret)) {
3289 	close(data_socket);
3290 	return -1;
3291       }
3292     }
3293   }
3294   ret = close(data_socket);
3295 
3296   if (SOCKET_EINTR(ret)) {
3297     /* end of test */
3298     return -1;
3299   }
3300   else if (ret == 0) {
3301     return ret;
3302   }
3303   else
3304     return -3;
3305 
3306 }
3307 
3308 int
disconnect_data_socket(SOCKET data_socket,int initiate,int do_close,struct sockaddr * peer,int peerlen)3309 disconnect_data_socket(SOCKET data_socket, int initiate, int do_close, struct sockaddr *peer, int peerlen)
3310 {
3311 
3312   char buffer[4];
3313   int bytes_recvd;
3314 
3315   if (debug) {
3316     fprintf(where,
3317 	    "%s sock %d init %d do_close %d protocol %d\n",
3318 	    __FUNCTION__,
3319 	    data_socket,
3320 	    initiate,
3321 	    do_close,
3322 	    protocol);
3323     fflush(where);
3324   }
3325 
3326   /* at some point we'll need to abstract this a little.  for now, if
3327      the protocol is UDP, we try to send some number of zero-length
3328      datagrams to allow the remote to get out of its loop without
3329      having to wait for the padded timer to expire. if it isn't UDP,
3330      we assume a reliable connection and can do the usual graceful
3331      shutdown thing */
3332 
3333   /* this needs to be revisited for the netperf receiving case when
3334      the test is terminated by a Ctrl-C.  raj 2012-01-24 */
3335 
3336   if (protocol != IPPROTO_UDP) {
3337     if (initiate)
3338       shutdown(data_socket, SHUT_WR);
3339 
3340     /* we are expecting to get either a return of zero indicating
3341        connection close, or an error. of course, we *may* never
3342        receive anything from the remote which means we probably really
3343        aught to have a select here but until we are once bitten we
3344        will remain twice bold. */
3345     bytes_recvd = recv(data_socket,
3346 		       buffer,
3347 		       1,
3348 		       0);
3349 
3350     if (bytes_recvd != 0) {
3351       /* connection close, call close. we assume that the requisite
3352          number of bytes have been received */
3353       if (SOCKET_EINTR(bytes_recvd))
3354 	{
3355 	  /* We hit the end of a timed test. */
3356 	  return -1;
3357 	}
3358       return -3;
3359     }
3360   }
3361   else {
3362     int i;
3363     for (i = 0; i < 3; i++) {
3364       if (peer)
3365 	bytes_recvd = sendto(data_socket,
3366 			     buffer,
3367 			     0,
3368 			     0,
3369 			     peer,
3370 			     peerlen);
3371       else
3372 	bytes_recvd = send(data_socket,
3373 			   buffer,
3374 			   0,
3375 			   0);
3376       /* we only really care if the timer expired on us */
3377       if (SOCKET_EINTR(bytes_recvd)) {
3378 	if (do_close)
3379 	  close(data_socket);
3380 	return -1;
3381       }
3382     }
3383   }
3384 
3385   if (do_close)
3386     close(data_socket);
3387 
3388   return 0;
3389 }
3390 
3391 #ifdef HAVE_LINUX_TCP_H
3392 static void
dump_tcp_info(struct tcp_info * tcp_info)3393 dump_tcp_info(struct tcp_info *tcp_info)
3394 {
3395 
3396   fprintf(stderr,
3397 	  "tcpi_rto %d tcpi_ato %d tcpi_pmtu %d tcpi_rcv_ssthresh %d\n"
3398 	  "tcpi_rtt %d tcpi_rttvar %d tcpi_snd_ssthresh %d tpci_snd_cwnd %d\n"
3399 	  "tcpi_reordering %d tcpi_total_retrans %d\n",
3400 	  tcp_info->tcpi_rto,
3401 	  tcp_info->tcpi_ato,
3402 	  tcp_info->tcpi_pmtu,
3403 	  tcp_info->tcpi_rcv_ssthresh,
3404 	  tcp_info->tcpi_rtt,
3405 	  tcp_info->tcpi_rttvar,
3406 	  tcp_info->tcpi_snd_ssthresh,
3407 	  tcp_info->tcpi_snd_cwnd,
3408 	  tcp_info->tcpi_reordering,
3409 	  tcp_info->tcpi_total_retrans);
3410 
3411   return;
3412 }
3413 
3414 #endif
3415 
3416 static int
get_transport_retrans(SOCKET socket,int protocol)3417 get_transport_retrans(SOCKET socket, int protocol) {
3418 
3419 #ifdef HAVE_LINUX_TCP_H
3420   struct tcp_info tcp_info;
3421 
3422   int ret;
3423   netperf_socklen_t infosize;
3424 
3425   if (protocol != IPPROTO_TCP)
3426     return -1;
3427 
3428   infosize = sizeof(struct tcp_info);
3429 
3430   if ((ret = getsockopt(socket,protocol,TCP_INFO,&tcp_info,&infosize)) < 0) {
3431     if (debug) {
3432       fprintf(where,
3433 	      "%s: getsockopt errno %d %s\n",
3434 	      __FUNCTION__,
3435 	      errno,
3436 	      strerror(errno));
3437       fflush(where);
3438     }
3439     return -1;
3440   }
3441   else {
3442 
3443     /* we assume that if we have LINUX_TCP_H we also have getenv */
3444     if (debug > 1 || getenv("DUMP_TCP_INFO")) {
3445       dump_tcp_info(&tcp_info);
3446     }
3447     return tcp_info.tcpi_total_retrans;
3448   }
3449 
3450 
3451 #else
3452   return -1;
3453 #endif
3454 }
3455 
3456 
3457 static void
get_transport_info(SOCKET socket,int * mss,int protocol)3458 get_transport_info(SOCKET socket, int *mss, int protocol)
3459 {
3460 
3461   netperf_socklen_t sock_opt_len;
3462   int option;
3463   sock_opt_len = sizeof(netperf_socklen_t);
3464 
3465   switch (protocol) {
3466 #if defined(IPPROTO_TCP) && defined(TCP_MAXSEG)
3467   case IPPROTO_TCP:
3468     option = TCP_MAXSEG;
3469     break;
3470 #endif
3471 
3472 #if defined(IPPROTO_SCTP) && defined(SCTP_MAXSEG)
3473   case IPPROTO_SCTP:
3474     option = SCTP_MAXSEG;
3475     break;
3476 #endif
3477   default:
3478     *mss = -1;
3479     return;
3480   }
3481 
3482   if (getsockopt(socket,
3483 		 protocol,
3484 		 option,
3485 		 (char *)mss,
3486 		 &sock_opt_len) == SOCKET_ERROR) {
3487     fprintf(where,
3488 	    "%s: getsockopt: errno %d\n",
3489 	    __FUNCTION__,
3490 	    errno);
3491     fflush(where);
3492     *mss = -1;
3493   }
3494 
3495 }
3496 
3497 static void
get_transport_cong_control(SOCKET socket,int protocol,char cong_control[],int len)3498 get_transport_cong_control(SOCKET socket, int protocol, char cong_control[], int len)
3499 {
3500 #ifdef TCP_CONGESTION
3501   int my_len = len;
3502   if (protocol != IPPROTO_TCP) {
3503     strncpy(cong_control,"TCP Only",len);
3504   }
3505   else if (getsockopt(socket,
3506 		      protocol, TCP_CONGESTION, cong_control, &my_len) ==
3507 	   SOCKET_ERROR) {
3508     snprintf(cong_control,len,"%d errno",errno);
3509   }
3510 #else
3511   strncpy(cong_control,"Unavailable",len);
3512 #endif
3513   cong_control[len-1] = '\0';
3514 }
3515 
3516 static void
set_transport_cong_control(SOCKET socket,int protocol,char cong_control[],int len)3517 set_transport_cong_control(SOCKET socket, int protocol, char cong_control[], int len)
3518 {
3519 #ifdef TCP_CONGESTION
3520   if (protocol == IPPROTO_TCP) {
3521     /* if it fails, we'll pick that up via the subsequent "get" */
3522     setsockopt(socket, protocol, TCP_CONGESTION, cong_control, len);
3523   }
3524 #endif
3525 }
3526 
3527 static void
set_receive_timeout(SOCKET sock,int timeout)3528 set_receive_timeout(SOCKET sock, int timeout)
3529 {
3530 #ifdef SO_RCVTIMEO
3531 #ifndef WIN32
3532   struct timeval foo;
3533 
3534   foo.tv_sec = timeout;
3535   foo.tv_usec = 0;
3536 
3537   if (setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,&foo,sizeof(foo)) < 0) {
3538     if (debug) {
3539       fprintf(where,"Note - attempt to set a receive timeout on the data socket failed with errno %d (%s)\n",
3540 	      errno,
3541 	      strerror(errno));
3542       fflush(where);
3543     }
3544   }
3545 #endif
3546 #endif
3547 }
3548 
3549 static SOCKET
omni_create_data_socket(struct addrinfo * res)3550 omni_create_data_socket(struct addrinfo *res)
3551 {
3552   SOCKET temp_socket;
3553 
3554   temp_socket = create_data_socket(res);
3555 
3556   if (temp_socket != SOCKET_ERROR) {
3557     if (local_cong_control_req[0] != '\0') {
3558       set_transport_cong_control(temp_socket,
3559 				 res->ai_protocol,
3560 				 local_cong_control_req,
3561 				 sizeof(local_cong_control_req));
3562     }
3563 
3564     if ((res->ai_protocol == IPPROTO_UDP) &&
3565 	(receive_timeout != -1)) {
3566       set_receive_timeout(temp_socket, receive_timeout);
3567     }
3568 
3569     if (socket_debug) {
3570       int one = 1;
3571       setsockopt(temp_socket,
3572 		 SOL_SOCKET,
3573 		 SO_DEBUG,
3574 		 &one,
3575 		 sizeof(one));
3576     }
3577   }
3578   return temp_socket;
3579 }
3580 /* choosing the default send size is a trifle more complicated than it
3581    used to be as we have to account for different protocol limits */
3582 
3583 #define UDP_LENGTH_MAX (0xFFFF - 28)
3584 
3585 static int
choose_send_size(int lss,int protocol)3586 choose_send_size(int lss, int protocol) {
3587 
3588   int send_size;
3589 
3590   if (lss > 0) {
3591     send_size = lss_size;
3592 
3593     /* we will assume that everyone has IPPROTO_UDP and thus avoid an
3594        issue with Windows using an enum */
3595     if ((protocol == IPPROTO_UDP) && (send_size > UDP_LENGTH_MAX))
3596       send_size = UDP_LENGTH_MAX;
3597 
3598   }
3599   else {
3600     send_size = 4096;
3601   }
3602   return send_size;
3603 }
3604 
3605 /* brain dead simple way to get netperf to emit a uuid. sadly, by this
3606    point we will have already established the control connection but
3607    those are the breaks. we do _NOT_ include a trailing newline
3608    because we want to be able to use this in a script */
3609 
3610 void
print_uuid(char remote_host[])3611 print_uuid(char remote_host[])
3612 {
3613   printf("%s",test_uuid);
3614 }
3615 #if defined(__linux)
3616 /*
3617  * Linux has this odd behavior where if the socket buffers are larger
3618  * than a device's txqueuelen, the kernel will silently drop transmits
3619  * which would not fit into the tx queue, and not pass an ENOBUFS
3620  * error back to the application.  As a result, a UDP stream test can
3621  * report absurd transmit bandwidths (like 20Gb/s on a 1GbE NIC).
3622  * This behavior can be avoided if you request extended error
3623  * reporting on the socket.  This is done by setting the IP_RECVERR
3624  * socket option at the IP level.
3625  */
3626 static void
enable_enobufs(int s)3627 enable_enobufs(int s)
3628 {
3629   struct protoent *pr;
3630   int on = 1;
3631 
3632   if ((pr = getprotobyname("ip")) == NULL) {
3633     fprintf(where, "%s failed: getprotobyname\n",__FUNCTION__);
3634     fflush(where);
3635     return;
3636   }
3637   if (setsockopt(s, pr->p_proto, IP_RECVERR, (char *)&on, sizeof(on)) < 0) {
3638     fprintf(where, "%s failed: setsockopt (errno %d)\n",__FUNCTION__,errno);
3639     fflush(where);
3640     return;
3641   }
3642 }
3643 #endif
3644 
3645 void
set_omni_request_flags(struct omni_request_struct * omni_request)3646 set_omni_request_flags(struct omni_request_struct *omni_request) {
3647 
3648       /* we have no else clauses here because we previously set flags
3649 	 to zero above raj 20090803 */
3650       if (rem_nodelay)
3651 	omni_request->flags |= OMNI_NO_DELAY;
3652 
3653       if (remote_use_sendfile)
3654 	omni_request->flags |= OMNI_USE_SENDFILE;
3655 
3656       if (connection_test)
3657 	omni_request->flags |= OMNI_CONNECT_TEST;
3658 
3659       if (remote_checksum_off)
3660 	omni_request->flags |= OMNI_CHECKSUM_OFF;
3661 
3662       if (remote_cpu_usage)
3663 	omni_request->flags |= OMNI_MEASURE_CPU;
3664 
3665       if (routing_allowed)
3666 	omni_request->flags |= OMNI_ROUTING_ALLOWED;
3667 
3668       if (desired_output_groups & OMNI_WANT_REM_IFNAME)
3669 	omni_request->flags |= OMNI_WANT_IFNAME;
3670 
3671       if (desired_output_groups & OMNI_WANT_REM_IFSLOT)
3672 	omni_request->flags |= OMNI_WANT_IFSLOT;
3673 
3674       if (desired_output_groups & OMNI_WANT_REM_IFIDS)
3675 	omni_request->flags |= OMNI_WANT_IFIDS;
3676 
3677       if (desired_output_groups & OMNI_WANT_REM_DRVINFO)
3678 	omni_request->flags |= OMNI_WANT_DRVINFO;
3679 
3680       if (desired_output_groups & OMNI_WANT_REM_CONG)
3681 	omni_request->flags |= OMNI_WANT_REM_CONG;
3682 
3683       if (use_fastopen)
3684 	omni_request->flags |= OMNI_FASTOPEN;
3685 
3686       if (want_use_pktinfo)
3687 	omni_request->flags |= OMNI_USE_PKTINFO;
3688 
3689       if (want_defer_accept)
3690 	omni_request->flags |= OMNI_WANT_DEFER_ACCEPT;
3691 
3692 }
3693 
3694 
3695 /* this code is intended to be "the two routines to run them all" for
3696    BSDish sockets.  it comes about as part of a desire to shrink the
3697    code footprint of netperf and to avoid having so many blessed
3698    routines to alter as time goes by.  the downside is there will be
3699    more "ifs" than there were before. raj 2008-01-07 */
3700 
3701 void
send_omni_inner(char remote_host[],unsigned int legacy_caller,char header_str[])3702 send_omni_inner(char remote_host[], unsigned int legacy_caller, char header_str[])
3703 {
3704 
3705   int ret,rret;
3706   int connected = 0;
3707   int timed_out = 0;
3708   int pad_time = 0;
3709 
3710   struct ring_elt *send_ring;
3711   struct ring_elt *recv_ring;
3712 
3713   struct sockaddr_storage remote_addr;
3714   struct sockaddr_storage my_addr;
3715   int                     remote_addr_len = sizeof(remote_addr);
3716   netperf_socklen_t       my_addr_len = sizeof(my_addr);
3717 
3718   SOCKET	data_socket;
3719   int           need_socket;
3720 
3721   uint32_t   temp_recvs;
3722   char  tmpfmt;
3723 
3724   struct addrinfo *local_res;
3725   struct addrinfo *remote_res;
3726 
3727   struct	omni_request_struct	*omni_request;
3728   struct	omni_response_struct	*omni_response;
3729   struct	omni_results_struct	*omni_result;
3730 
3731 #ifdef WANT_FIRST_BURST
3732   int requests_outstanding = 0;
3733 #endif
3734 
3735   omni_request =
3736     (struct omni_request_struct *)netperf_request.content.test_specific_data;
3737   omni_response =
3738     (struct omni_response_struct *)netperf_response.content.test_specific_data;
3739   omni_result =
3740     (struct omni_results_struct *)netperf_response.content.test_specific_data;
3741 
3742 
3743   if (keep_histogram) {
3744     if (first_burst_size > 0)
3745       time_hist = HIST_new_n(first_burst_size + 1);
3746     else
3747       time_hist = HIST_new_n(1);
3748   }
3749 
3750   /* since we are now disconnected from the code that established the
3751      control socket, and since we want to be able to use different
3752      protocols and such, we are passed the name of the remote host and
3753      must turn that into the test specific addressing information. */
3754 
3755   complete_addrinfos(&remote_res,
3756 		     &local_res,
3757 		     remote_host,
3758 		     socket_type,
3759 		     protocol,
3760 		     0);
3761 
3762   if ( print_headers ) {
3763     print_top_test_header(header_str,local_res,remote_res);
3764   }
3765 
3766   /* initialize a few counters */
3767 
3768   need_socket   = 1;
3769 
3770   if (connection_test)
3771     pick_next_port_number(local_res,remote_res);
3772 
3773 
3774   /* If the user has requested cpu utilization measurements, we must
3775      calibrate the cpu(s). We will perform this task within the tests
3776      themselves. If the user has specified the cpu rate, then
3777      calibrate_local_cpu will return rather quickly as it will have
3778      nothing to do. If local_cpu_rate is zero, then we will go through
3779      all the "normal" calibration stuff and return the rate back.*/
3780 
3781   if (local_cpu_usage) {
3782     local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3783   }
3784 
3785   confidence_iteration = 1;
3786   init_stat();
3787 
3788   send_ring = NULL;
3789   recv_ring = NULL;
3790 
3791   /* you will keep running the test until you get it right! :) */
3792   while (((confidence < 0) && (confidence_iteration <= iteration_max)) ||
3793 	 (confidence_iteration <= iteration_min)) {
3794 
3795     trans_completed = 0;
3796     bytes_xferd	= 0.0;
3797     remote_bytes_xferd = 0.0;
3798     times_up 	= 0;
3799     bytes_sent = 0;
3800     bytes_received = 0;
3801     local_send_calls = 0;
3802     local_receive_calls = 0;
3803 
3804     /* since we are tracking the number of outstanding requests for
3805        timestamping purposes, and since the previous iteration of
3806        using confidence intervals may not have completed all of them,
3807        we now need to forget about them or we will mistakenly fill our
3808        tracking array. raj 2011-03-14 */
3809     if (keep_histogram) {
3810       HIST_purge(time_hist);
3811     }
3812 
3813 #ifdef WANT_FIRST_BURST
3814     /* we have to remember to reset the number of transactions
3815        outstanding and the "congestion window for each new
3816        iteration. raj 2006-01-31. */
3817     requests_outstanding = 0;
3818 #endif
3819 
3820     /* if the command-line included requests to randomize the IP
3821        addresses, then honor it.  of course, this may not work all that
3822        well for some tests... raj 20101129 */
3823     if (local_mask_len)
3824       random_ip_address(local_res, local_mask_len);
3825     if (remote_mask_len)
3826       random_ip_address(remote_res, remote_mask_len);
3827 
3828     data_socket = omni_create_data_socket(local_res);
3829 
3830     if (data_socket == INVALID_SOCKET) {
3831       perror("netperf: send_omni: unable to create data socket");
3832       exit(1);
3833     }
3834 #if defined(__linux)
3835     /* we really only need this for a UDP_STREAM test. we particularly
3836        do not want it for a CC or CRR test. raj 2012-08-06 */
3837     if ((protocol == IPPROTO_UDP) &&
3838 	NETPERF_XMIT_ONLY(direction)) {
3839       enable_enobufs(data_socket);
3840     }
3841 #endif
3842     need_socket = 0;
3843 
3844     /* we need to consider if this is a request/response test, if we
3845        are receiving, if we are sending, etc, when setting-up our recv
3846        and send buffer rings. we should only need to do this once, and
3847        that would be when the relevant _ring variable is NULL. raj
3848        2008-01-18 */
3849     if (direction & NETPERF_XMIT) {
3850       if (is_multicast_addr(remote_res)) {
3851 	set_multicast_ttl(data_socket);
3852       }
3853 
3854       if (NULL == send_ring) {
3855 	if (req_size > 0) {
3856 	  /* request/response test */
3857 	  if (send_width == 0) send_width = 1;
3858 	  bytes_to_send = req_size;
3859 	}
3860 	else {
3861 	  /* stream test */
3862 	  if (send_size == 0) {
3863 	    send_size = choose_send_size(lss_size,protocol);
3864 	  }
3865 	  if (send_width == 0)
3866 	    send_width = (lss_size/send_size) + 1;
3867 	  if (send_width == 1) send_width++;
3868 	  bytes_to_send = send_size;
3869 	}
3870 
3871 	send_ring = allocate_buffer_ring(send_width,
3872 					 bytes_to_send,
3873 					 local_send_align,
3874 					 local_send_offset);
3875 	if (debug) {
3876 	  fprintf(where,
3877 		  "%s: %d entry send_ring obtained...\n",
3878 		  __FUNCTION__,
3879 		  send_width);
3880 	}
3881       }
3882     }
3883 
3884     if (direction & NETPERF_RECV) {
3885       /* do we need to join a multicast group? */
3886       if (is_multicast_addr(local_res)) {
3887 	join_multicast_addr(data_socket, local_res);
3888       }
3889 
3890       /* do we need to allocate a recv_ring? */
3891       if (NULL == recv_ring) {
3892 	if (rsp_size > 0) {
3893 	  if (recv_width == 0) recv_width = 1;
3894 	  bytes_to_recv = rsp_size;
3895 	}
3896 	else {
3897 	  /* stream test */
3898 	  if (recv_size == 0) {
3899 	    if (lsr_size > 0) {
3900 	      recv_size = lsr_size;
3901 	    }
3902 	    else {
3903 	      recv_size = 4096;
3904 	    }
3905 	  }
3906 	  if (recv_width == 0) {
3907 	    recv_width = (lsr_size/recv_size) + 1;
3908 	    if (recv_width == 1) recv_width++;
3909 	  }
3910 	  bytes_to_recv = recv_size;
3911 	}
3912 
3913 	recv_ring = allocate_buffer_ring(recv_width,
3914 					 bytes_to_recv,
3915 					 local_recv_align,
3916 					 local_recv_offset);
3917 	if (debug) {
3918 	  fprintf(where,
3919 		  "%s: %d entry recv_ring obtained...\n",
3920 		  __FUNCTION__,
3921 		  recv_width);
3922 	}
3923       }
3924     }
3925 
3926     if (!no_control) {
3927 
3928       /* Tell the remote end to do a listen or otherwise prepare for
3929 	 what is to come. The server alters the socket paramters on the
3930 	 other side at this point, hence the reason for all the values
3931 	 being passed in the setup message. If the user did not specify
3932 	 any of the parameters, they will be passed as values which will
3933 	 indicate to the remote that no changes beyond the system's
3934 	 default should be used. Alignment is the exception, it will
3935 	 default to 8, which will probably be no alignment
3936 	 alterations. */
3937 
3938       netperf_request.content.request_type = DO_OMNI;
3939       omni_request->flags                  = 0;
3940       omni_request->send_buf_size	   = rss_size_req;
3941       omni_request->send_size              = remote_send_size_req;
3942       omni_request->send_alignment	   = remote_send_align;
3943       omni_request->send_offset	           = remote_send_offset;
3944       omni_request->send_width             = send_width;
3945       omni_request->request_size	   = req_size;
3946 
3947       omni_request->recv_buf_size	   = rsr_size_req;
3948       omni_request->receive_size           = remote_recv_size_req;
3949       omni_request->recv_alignment	   = remote_recv_align;
3950       omni_request->recv_offset	           = remote_recv_offset;
3951       omni_request->recv_width             = recv_width;
3952       omni_request->response_size	   = rsp_size;
3953       omni_request->socket_prio            = remote_socket_prio;
3954       omni_request->socket_tos             = remote_socket_tos;
3955 
3956       set_omni_request_flags(omni_request);
3957 
3958       /* perhaps this should be made conditional on
3959 	 remote_cong_control_req[0] not being NULL? */
3960       strncpy(omni_request->cong_control,
3961 	      remote_cong_control_req,
3962 	      sizeof(omni_request->cong_control));
3963       omni_request->cong_control[sizeof(omni_request->cong_control) - 1] =
3964 	'\0';
3965 
3966       if (want_keepalive)
3967 	omni_request->flags |= OMNI_WANT_KEEPALIVE;
3968 
3969       omni_request->cpu_rate	           = remote_cpu_rate;
3970       if (test_time)
3971 	omni_request->test_length	   = test_time;
3972       else
3973 	omni_request->test_length	   = test_trans * -1;
3974       omni_request->so_rcvavoid	           = rem_rcvavoid;
3975       omni_request->so_sndavoid	           = rem_sndavoid;
3976       omni_request->send_dirty_count       = rem_dirty_count;
3977       omni_request->recv_dirty_count       = rem_dirty_count;
3978       omni_request->recv_clean_count       = rem_clean_count;
3979 
3980       omni_request->data_port              = atoi(remote_data_port);
3981       omni_request->ipfamily               = af_to_nf(remote_res->ai_family);
3982       omni_request->socket_type            = hst_to_nst(socket_type);
3983       omni_request->protocol               = protocol;
3984 
3985       omni_request->interval_burst         = remote_interval_burst;
3986       omni_request->interval_usecs         = remote_interval_usecs;
3987 
3988       omni_request->direction              = 0;
3989       /* yes, the sense here is correct - if we are transmitting, they
3990 	 receive, if we are receiving, they are transmitting... */
3991       if (direction & NETPERF_XMIT)
3992 	omni_request->direction |= NETPERF_RECV;
3993       if (direction & NETPERF_RECV)
3994 	omni_request->direction |= NETPERF_XMIT;
3995 
3996       /* some tests may require knowledge of our local addressing. such
3997 	 tests will for the time being require that the user specify a
3998 	 local IP/name so we can extract them from the data_socket. */
3999       getsockname(data_socket, (struct sockaddr *)&my_addr, &my_addr_len);
4000 
4001       ret = get_sockaddr_family_addr_port(&my_addr,
4002 					  nf_to_af(omni_request->ipfamily),
4003 					  omni_request->netperf_ip,
4004 					  &(omni_request->netperf_port));
4005       ret = get_sockaddr_family_addr_port((struct sockaddr_storage *)remote_res->ai_addr,
4006 					  nf_to_af(omni_request->ipfamily),
4007 					  omni_request->netserver_ip,
4008 					  &(omni_request->data_port));
4009       /* if the user didn't explicitly set the remote data address we
4010 	 don't want to pass along the one we picked implicitly, or a
4011 	 netserver sitting behind a (BLETCH) NAT will be asked to try
4012 	 to bind to the "public" IP. */
4013       if (!explicit_data_address) {
4014 	omni_request->netserver_ip[0] = 0;
4015 	omni_request->netserver_ip[1] = 0;
4016 	omni_request->netserver_ip[2] = 0;
4017 	omni_request->netserver_ip[3] = 0;
4018       }
4019       if (debug > 1) {
4020 	fprintf(where,"netperf: %s: requesting OMNI test\n",__FUNCTION__);
4021       }
4022 
4023       strncpy(omni_request->fill_file,
4024 	      remote_fill_file,
4025 	      sizeof(omni_request->fill_file));
4026 
4027       send_request_n(OMNI_REQUEST_CONV_CUTOFF);
4028 
4029 
4030       /* the response from the remote should contain all the relevant
4031 	 socket and other parameters we need to know for this test.
4032 	 so, we can shove them back into the relevant variables here
4033 	 and be on our way. */
4034 
4035       recv_response_n(OMNI_RESPONSE_CONV_CUTOFF); /* brittle, but functional */
4036 
4037       if (!netperf_response.content.serv_errno) {
4038 	rsr_size	    = omni_response->recv_buf_size;
4039 	remote_recv_size    = omni_response->receive_size;
4040 	rss_size	    = omni_response->send_buf_size;
4041 	remote_send_size    = omni_response->send_size;
4042 	rem_nodelay         = omni_response->flags & OMNI_NO_DELAY;
4043 	remote_use_sendfile = omni_response->flags & OMNI_USE_SENDFILE;
4044 	remote_cpu_usage    = omni_response->flags & OMNI_MEASURE_CPU;
4045 	remote_cpu_rate     = omni_response->cpu_rate;
4046 	remote_send_width   = omni_response->send_width;
4047 	remote_recv_width   = omni_response->recv_width;
4048 	remote_socket_prio  = omni_response->socket_prio;
4049 	remote_socket_tos   = omni_response->socket_tos;
4050 
4051 	/* make sure that port numbers are in network order because
4052 	   recv_response will have put everything into host order */
4053 	set_port_number(remote_res,
4054 			(unsigned short)omni_response->data_port);
4055 
4056 	if (debug) {
4057 	  fprintf(where,"remote listen done.\n");
4058 	  fprintf(where,"remote port is %u\n",get_port_number(remote_res));
4059 	  fflush(where);
4060 	}
4061       }
4062       else {
4063 	Set_errno(netperf_response.content.serv_errno);
4064 	fprintf(where,
4065 		"netperf: remote error %d",
4066 		netperf_response.content.serv_errno);
4067 	perror("");
4068 	fflush(where);
4069 	exit(-1);
4070       }
4071 
4072     }
4073 
4074 #ifdef WANT_DEMO
4075     /* at some point we will have to be more clever about this, but
4076        for now we won't */
4077 
4078     demo_rr_setup(100);
4079 #endif
4080 
4081     /* if we are not a connectionless protocol, we need to connect. at
4082        some point even if we are a connectionless protocol, we may
4083        still want to "connect" for convenience raj 2008-01-14 */
4084     need_to_connect = (protocol != IPPROTO_UDP) || local_connected;
4085 
4086     /* possibly wait just a moment before actually starting - used
4087        mainly when one is doing many many many concurrent netperf
4088        tests */
4089     WAIT_BEFORE_DATA_TRAFFIC();
4090 
4091     /* Set-up the test end conditions. For tests over a
4092        "reliable/connection-oriented" transport (eg TCP, SCTP, etc)
4093        this can be either time or byte/transaction count based.  for
4094        unreliable transport or connection tests it can only be time
4095        based.  having said that, we rely entirely on other code to
4096        enforce this before we even get here. raj 2008-01-08 */
4097 
4098     /* enable a test_time of 0 to mean just keep running until
4099        something other than alarm() generates a signal. raj
4100        2012-02-01 */
4101     if ((test_time) || ((test_trans == 0) && (test_bytes == 0))) {
4102       /* The user wanted to end the test after a period of time.  if
4103 	 we are a recv-only test, we need to protect ourself against
4104 	 the remote going poof, but we want to make sure we don't
4105 	 give-up before they finish, so we will add a PAD_TIME to the
4106 	 timer.  if we are RR or XMIT, there should be no need for
4107 	 padding */
4108       times_up = 0;
4109       units_remaining = 0;
4110       if ((!no_control) &&
4111 	  (NETPERF_RECV_ONLY(direction)) &&
4112 	  ((test_trans == 0) && (test_bytes == 0)))
4113 	    pad_time = 0;
4114       start_timer(test_time + pad_time);
4115     }
4116     else {
4117       /* The tester wanted to send a number of bytes or exchange a
4118 	 number of transactions. */
4119       if (NETPERF_IS_RR(direction))
4120 	units_remaining = test_trans;
4121       else
4122 	units_remaining = test_bytes;
4123       times_up = 1;
4124     }
4125 
4126     /* grab the current time, and if necessary any starting information
4127        for the gathering of CPU utilization at this end. */
4128     cpu_start(local_cpu_usage);
4129 
4130 #if defined(WANT_INTERVALS)
4131     INTERVALS_INIT();
4132 #endif /* WANT_INTERVALS */
4133 
4134 #ifdef WANT_DEMO
4135     if (demo_mode) {
4136       demo_first_timestamp();
4137     }
4138 #endif
4139 
4140     /* the "OR" here allows us to control test length by either
4141        byte/transaction count or by timer.  when the test is
4142        byte/transaction count based the time test will always evaluate
4143        false. when the test is controlled by time, the byte/transaction
4144        count will always evaluate to false.  when the test is finished
4145        the whole expression will go false and we will stop sending
4146        data. at least that is the plan :)  raj 2008-01-08 */
4147 
4148     while ((!times_up) || (units_remaining > 0)) {
4149 
4150       /* we need to be careful about when we snap a timestamp
4151 	 depending on the test parameters. this one *should* cover
4152 	 everything but the burst request/response test - famous last
4153 	 words of course. raj 20110111 */
4154 
4155       if (keep_histogram) {
4156 	HIST_timestamp_start(time_hist);
4157       }
4158 
4159 
4160     again:
4161 
4162       if (need_socket) {
4163 	if (connection_test)
4164 	  pick_next_port_number(local_res,remote_res);
4165 
4166 	data_socket = omni_create_data_socket(local_res);
4167 
4168 	if (data_socket == INVALID_SOCKET) {
4169 	  perror("netperf: send_omni: unable to create data socket");
4170 	  exit(1);
4171 	}
4172 	need_socket = 0;
4173 #if defined(__linux)
4174 	if ((protocol == IPPROTO_UDP) &&
4175 	    (direction & NETPERF_XMIT)) {
4176 	  enable_enobufs(data_socket);
4177 	}
4178 #endif
4179       }
4180 
4181       /* only connect if and when we need to */
4182       if (need_to_connect && !use_fastopen) {
4183 	/* assign to data_socket since connect_data_socket returns
4184 	   SOCKET and not int thanks to Windows. */
4185 	ret = connect_data_socket(data_socket,remote_res,dont_give_up);
4186 	if (ret == 0) {
4187 	  connected = 1;
4188 	  need_to_connect = 0;
4189 	}
4190 	else if (ret == -1) {
4191 	  times_up = 1;
4192 	  timed_out = 1;
4193 	  break;
4194 	}
4195 	else if ((ret == -2) && connection_test) {
4196 	  /* transient error  on a connection test means go around and
4197 	     try again with another local port number */
4198 	  if (debug) {
4199 	    fprintf(where,"transient! transient! torpedo in the water!\n");
4200 	    fflush(where);
4201 	  }
4202 	  close(data_socket);
4203 	  connected = 0;  /* probably redundant but what the heck... */
4204 	  need_socket = 1;
4205 	  need_to_connect = 1;
4206 	  /* this will stuff the next local port number within bounds
4207 	     into our local res, and then when the goto has us
4208 	     allocating a new socket it will do the right thing with the
4209 	     bind() call */
4210 	  pick_next_port_number(local_res,remote_res);
4211 	  /* yes Virginia, a goto.  perhaps one day we will rewrite
4212 	     the code to avoid it but for now, a goto... raj */
4213 	  goto again;
4214 	}
4215 	else {
4216 	  /* either this was a hard failure (-3) or a soft failure on
4217 	     something other than a connection test */
4218 	  perror("netperf: send_omni: connect_data_socket failed");
4219 	  exit(1);
4220 	}
4221       }
4222 
4223 #ifdef WANT_FIRST_BURST
4224       /* Long ago and far away, on just about any *nix, one could
4225 	 avoid having multiple requests bundled into the same TCP
4226 	 segment simply by setting TCP_NODELAY and perhaps not trying
4227 	 to have more outstanding at one time than our guesstimate as
4228 	 to the TCP congestion window.  In that way one could use a
4229 	 burst mode TCP_RR test as part of trying to measure maximum
4230 	 packets per second (PPS) on a system or through a NIC (well,
4231 	 assuming there weren't many retransmissions anyway) These
4232 	 days with Linux the dominant *nix and with it having made it
4233 	 virtually impossible to do any longer, it is no longer worth
4234 	 it to try the application-layer backflips.  So, I am removing
4235 	 them.  At some point we'll simply have to enhance this code
4236 	 to deal with multiple connections at one time, each with just
4237 	 the one transaction in flight for our PPS testing.  Multiple
4238 	 netperfs, each with one connection and one transaction in
4239 	 flight rapidly becomes a context-switching benchmark rather
4240 	 than "networking".  raj 2015-04-20 */
4241 
4242       while ((first_burst_size > 0) &&
4243 	     (requests_outstanding < first_burst_size) &&
4244 	     (NETPERF_IS_RR(direction)) &&
4245 	     (!connection_test)) {
4246 	if (debug > 1) {
4247 	  fprintf(where,
4248 		  "injecting, req_outstanding %d burst %d\n",
4249 		  requests_outstanding,
4250 		  first_burst_size);
4251 	}
4252 
4253 	if ((ret = send_data(data_socket,
4254 			     send_ring,
4255 			     bytes_to_send,
4256 			     (connected) ? NULL : remote_res->ai_addr,
4257 			     remote_res->ai_addrlen,
4258 			     protocol)) != bytes_to_send) {
4259 	  /* in theory, we should never hit the end of the test in the
4260 	     first burst.  however, in practice I have indeed seen
4261 	     some ENOBUFS happen in some aggregate tests.  so we need
4262 	     to be a bit more sophisticated in how we handle it. raj
4263 	     20130516 */
4264 	  if (ret != -2) {
4265 	    perror("send_omni: initial burst data send error");
4266 	    exit(-1);
4267 	  }
4268 	  failed_sends++;
4269 	}
4270 	else {
4271 	  local_send_calls += 1;
4272 	  requests_outstanding += 1;
4273 	}
4274 
4275 	/* yes, it seems a trifle odd having this *after* the send()
4276 	   just above, but really this is for the next send() or
4277 	   recv() call below or in the iteration of this loop, and the
4278 	   first HIST_timestamp_start() call at the top of the
4279 	   outermost loop will be for the first send() call here in
4280 	   the burst code.  clear ain't it?-) raj 20110111 */
4281 
4282 	if (keep_histogram) {
4283 	  HIST_timestamp_start(time_hist);
4284 	}
4285       }
4286 
4287 #endif /* WANT_FIRST_BURST */
4288 
4289       /* if we should try to send something, then by all means, let us
4290 	 try to send something. */
4291       if (direction & NETPERF_XMIT) {
4292 
4293 	ret = send_data(data_socket,
4294 			send_ring,
4295 			bytes_to_send,
4296 			(connected) ? NULL : remote_res->ai_addr,
4297 			/* if the destination above is NULL, this is ignored */
4298 			remote_res->ai_addrlen,
4299 			protocol);
4300 	/* the order of these if's will seem a triffle strange, but they
4301 	   are my best guess as to order of probabilty and/or importance
4302 	   to the overhead raj 2008-01-09*/
4303 	if (ret == bytes_to_send) {
4304 	  /* if this is a send-only test controlled by byte count we
4305 	     decrement units_remaining by the bytes sent */
4306 	  if (!(direction & NETPERF_RECV) && (units_remaining > 0)) {
4307 	    units_remaining -= ret;
4308 	  }
4309 	  bytes_sent += ret;
4310 	  send_ring = send_ring->next;
4311 	  local_send_calls++;
4312 	}
4313 	else if (ret == -2) {
4314 	  /* what to do here -2 means a non-fatal error - probably
4315 	     ENOBUFS and so our send didn't happen.  in the old code for
4316 	     UDP_STREAM we would just continue in the while loop.  it
4317 	     isn't clear that is what to do here, so we will simply
4318 	     increment the failed_sends stat and fall-through. If this
4319 	     is a UDP_STREAM style of test, the net effect should be the
4320 	     same. if this is a UDP_RR with a really-big burst count, I
4321 	     don't think we were checking for ENOBUFS there anyway and
4322 	     so would have failed.  Here we can just let things
4323 	     slide. */
4324 	  failed_sends++;
4325 	}
4326 	else if (ret == 0) {
4327 	  /* was this a zero-byte send? if it was, then ostensibly we
4328 	     would hit the ret == bytes_to_send case which means we'd
4329 	     never get here as we are using blocking semantics */
4330 	  fprintf(where,"HOW DID I GET HERE?\n");
4331 	  fflush(where);
4332 	}
4333 	else if (ret == -1) {
4334 	  times_up = 1;
4335 	  timed_out = 1;
4336 	  break;
4337 	}
4338 	else {
4339 	  perror("netperf: send_omni: send_data failed");
4340 	  exit(1);
4341 	}
4342 
4343       }
4344 
4345 #ifdef WANT_FIRST_BURST
4346       /* it isn't clear we need to check the directions here.  the
4347 	 increment should be cheaper than the conditional, and it
4348 	 shouldn't hurt the other directions because they'll never
4349 	 look at them. famous last words of raj 2008-01-25 */
4350       requests_outstanding += 1;
4351 #endif
4352 
4353 #ifdef WIN32
4354       /* this is used so the timer thread can close the socket out
4355 	from under us, which to date is the easiest/cleanest/least
4356 	Windows-specific way I can find to force the winsock calls to
4357 	return WSAEINTR with the test is over. anything that will run
4358 	on 95 and NT and is closer to what netperf expects from Unix
4359 	signals and such would be appreciated raj 1/96 */
4360       win_kludge_socket = data_socket;
4361 #endif /* WIN32 */
4362 
4363       if (direction & NETPERF_RECV) {
4364 	rret = recv_data(data_socket,
4365 			recv_ring,
4366 			bytes_to_recv,
4367 			(connected) ? NULL : (struct sockaddr *)&remote_addr,
4368 			/* if remote_addr NULL this is ignored */
4369 			&remote_addr_len,
4370 			/* if XMIT also set this is RR so waitall */
4371 			(direction & NETPERF_XMIT) ? NETPERF_WAITALL: 0,
4372 			&temp_recvs);
4373 	if (rret > 0) {
4374 	  /* if this is a recv-only test controlled by byte count we
4375 	     decrement the units_remaining by the bytes received */
4376 	  if (!(direction & NETPERF_XMIT) && (units_remaining > 0)) {
4377 	    units_remaining -= rret;
4378 	  }
4379 	  bytes_received += rret;
4380 	  local_receive_calls += temp_recvs;
4381 	}
4382 	else if (rret == 0) {
4383 	  /* is this the end of a test, just a zero-byte recv, or
4384 	     something else? that is an exceedingly good question and
4385 	     one for which I don't presently have a good answer, but
4386 	     that won't stop me from guessing :) raj 2008-01-09 */
4387 	  if (!((connection_test) || (null_message_ok))) {
4388 	    /* if it is neither a connection_test nor null_message_ok it
4389 	       must be the end of the test */
4390 	    times_up = 1; /* ostensibly the signal handler did this */
4391 	    break;
4392 	  }
4393 	  local_receive_calls += temp_recvs;
4394 	}
4395 	else if (rret == -1) {
4396 	  /* test timed-out */
4397 	  times_up = 1;
4398 	  timed_out = 1;
4399 	  break;
4400 	}
4401 	else if (rret == -2) {
4402 	  /* we timed-out on a data receive.  this is only allowed for
4403 	     a UDP_RR test.  we want to set things up so we start
4404 	     ramping up again like we were at the beginning. if we
4405 	     actually timeout it means that all has been lost.  or at
4406 	     least we assume so */
4407 	  if (debug) {
4408 	    fprintf(where,"Timeout receiving resonse from remote\n");
4409 	    fflush(where);
4410 	  }
4411 #ifdef WANT_FIRST_BURST
4412 	  if (first_burst_size) {
4413 	    requests_outstanding = 0;
4414 	  }
4415 #endif
4416 	  if (keep_histogram) {
4417 	    HIST_purge(time_hist);
4418 	  }
4419 #ifdef WANT_DEMO
4420 	  /* "start over" on a demo interval. we will forget about
4421 	  everything that happened in the demo interval up to the
4422 	  timeout and begin fresh. */
4423 	  demo_reset();
4424 #endif /* WANT_DEMO */
4425 
4426 	  continue;
4427 	}
4428 	else {
4429 	  /* anything else is bad */
4430 	  perror("netperf: send_omni: recv_data failed");
4431 	  exit(1);
4432 	}
4433 	recv_ring = recv_ring->next;
4434 
4435 #ifdef WANT_FIRST_BURST
4436 	/* so, since we've gotten a response back, update the
4437 	   bookkeeping accordingly.  there is one less request
4438 	   outstanding and we can put one more out there than
4439 	   before. */
4440 	requests_outstanding -= 1;
4441 #endif
4442 
4443       }
4444 
4445       /* if this is a connection test, we want to do some stuff about
4446 	 connection close here in the test loop. raj 2008-01-08 */
4447       if (connection_test) {
4448 
4449 #ifdef __linux
4450 	/* so, "Linux" with autotuning likes to alter the socket buffer
4451 	   sizes over the life of the connection, but only does so when
4452 	   one takes the defaults at time of socket creation.  if we
4453 	   took those defaults, we should inquire as to what the values
4454 	   ultimately became. raj 2008-01-15 */
4455 	/* however annoying having to do this might be, it really
4456 	   shouldn't be done over and over again. instead we will
4457 	   assume it does not change, which is fine since we would
4458 	   have only reported one of them anyway. raj 20100917 */
4459 	if ((lsr_size_req < 0) && (-1 == lsr_size_end))
4460 	  get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end);
4461 	else
4462 	  lsr_size_end = lsr_size;
4463 	if ((lss_size_req < 0) && (-1 == lss_size_end))
4464 	  get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end);
4465 	else
4466 	  lss_size_end = lss_size;
4467 #else
4468 	lsr_size_end = lsr_size;
4469 	lss_size_end = lss_size;
4470 #endif
4471 
4472 	/* we will only make this call the one time - after the first
4473 	   call, the value will be real or -1. if this is a connection
4474 	   test we want to do this here because later we won't be
4475 	   connected and the data may no longer be available. */
4476 	if (transport_mss == -2)
4477 	  get_transport_info(data_socket,
4478 			     &transport_mss,
4479 			     local_res->ai_protocol);
4480 
4481 
4482 	ret = disconnect_data_socket(data_socket,
4483 				     (no_control) ? 1 : 0,
4484 				     1,
4485 				     NULL,
4486 				     0);
4487 	if (ret == 0) {
4488 	  /* we will need a new connection to be established next time
4489 	     around the loop.  However, the next time around the loop
4490 	     will already be picking the next port number */
4491 	  need_to_connect = 1;
4492 	  connected = 0;
4493 	  need_socket = 1;
4494 	}
4495 	else if (ret == -1) {
4496 	  times_up = 1;
4497 	  timed_out = 1;
4498 	  break;
4499 	}
4500 	else {
4501 	  perror("netperf: send_omni: disconnect_data_socket failed");
4502 	  exit(1);
4503 	}
4504       }
4505 
4506 
4507       if (keep_histogram) {
4508 	HIST_timestamp_stop_add(time_hist);
4509       }
4510 
4511 #ifdef WANT_DEMO
4512       if (NETPERF_IS_RR(direction)) {
4513 	if (libfmt == 'x') {
4514 	  demo_interval_tick(1);
4515 	}
4516 	else {
4517 	  demo_interval_tick(req_size + rsp_size);
4518 	}
4519       }
4520       else if (NETPERF_XMIT_ONLY(direction)) {
4521 	demo_interval_tick(bytes_to_send);
4522       }
4523       else {
4524 	demo_interval_tick(rret);
4525       }
4526 #endif
4527 
4528 #if defined(WANT_INTERVALS)
4529       INTERVALS_WAIT();
4530 #endif /* WANT_INTERVALS */
4531 
4532 
4533       /* was this a "transaction" test? */
4534       if (NETPERF_IS_RR(direction)) {
4535 	trans_completed++;
4536 	if (units_remaining) {
4537 	  units_remaining--;
4538 	}
4539       }
4540 
4541 
4542     }
4543 
4544     /* we are now, ostensibly, at the end of this iteration */
4545 
4546 #if defined(WANT_DEMO)
4547     /* if we were in demo mode this will ensure one final interim
4548        result, which, naturally might be a bit early :) */
4549     demo_interval_final();
4550 #endif
4551 
4552     if (transport_mss == -2)
4553       get_transport_info(data_socket,
4554 			 &transport_mss,
4555 			 local_res->ai_protocol);
4556     local_transport_retrans = get_transport_retrans(data_socket,
4557 						    local_res->ai_protocol);
4558 
4559 
4560     /* so, if we have/had a data connection, we will want to close it
4561        now, and this will be independent of whether there is a control
4562        connection. */
4563 
4564     if (connected) {
4565 
4566 #ifdef __linux
4567       /* so, "Linux" with autotuning likes to alter the socket buffer
4568 	 sizes over the life of the connection, but only does so when
4569 	 one takes the defaults at time of socket creation.  if we took
4570 	 those defaults, we should inquire as to what the values
4571 	 ultimately became. raj 2008-01-15 */
4572       if (lsr_size_req < 0)
4573 	get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end);
4574       else
4575 	lsr_size_end = lsr_size;
4576       if (lss_size_req < 0)
4577 	get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end);
4578       else
4579 	lss_size_end = lss_size;
4580 #else
4581       lsr_size_end = lsr_size;
4582       lss_size_end = lss_size;
4583 #endif
4584       if ((desired_output_groups & OMNI_WANT_LOC_CONG) &&
4585 	  (local_cong_control[0] == '\0')) {
4586 	get_transport_cong_control(data_socket,
4587 				   local_res->ai_protocol,
4588 				   local_cong_control,
4589 				   sizeof(local_cong_control));
4590       }
4591 
4592       /* CHECK PARMS HERE; */
4593       ret = disconnect_data_socket(data_socket,
4594 				   1,
4595 				   1,
4596 				   NULL,
4597 				   0);
4598       connected = 0;
4599       need_socket = 1;
4600 
4601     }
4602     else {
4603       /* this is the UDP case at present */
4604       ret = disconnect_data_socket(data_socket,
4605 				   1,
4606 				   1,
4607 				   remote_res->ai_addr,
4608 				   remote_res->ai_addrlen);
4609       need_socket = 1;
4610       lsr_size_end = lsr_size;
4611       lss_size_end = lss_size;
4612     }
4613 
4614     /* this call will always give us the elapsed time for the test, and
4615        will also store-away the necessaries for cpu utilization */
4616 
4617     cpu_stop(local_cpu_usage,&elapsed_time);
4618 
4619     /* if we timed-out, and had padded the timer, we need to subtract
4620        the pad_time from the elapsed time on the assumption that we
4621        were essentially idle for pad_time and just waiting for a timer
4622        to expire on something like a UDP test.  if we have not padded
4623        the timer, pad_time will be zero.  if we have not timed out
4624        then we want to make sure we stop the timer. */
4625     if (timed_out) {
4626       if (debug) {
4627 	fprintf(where,"Adjusting elapsed_time by %d seconds\n",pad_time);
4628 	fflush(where);
4629       }
4630       elapsed_time -= (float)pad_time;
4631     }
4632     else {
4633       stop_timer();
4634     }
4635 
4636     if (!no_control) {
4637       /* Get the statistics from the remote end. The remote will have
4638 	 calculated service demand and all those interesting things. If
4639 	 it wasn't supposed to care, it will return obvious values. */
4640 
4641       recv_response_n(OMNI_RESULTS_CONV_CUTOFF);
4642       if (!netperf_response.content.serv_errno) {
4643 	if (debug)
4644 	  fprintf(where,"remote results obtained\n");
4645 	remote_cpu_method = format_cpu_method(omni_result->cpu_method);
4646 	lib_num_rem_cpus = omni_result->num_cpus;
4647 	lib_remote_cpu_stats.cpu_util = omni_result->cpu_util;
4648 	lib_remote_cpu_stats.cpu_user = omni_result->cpu_percent_user;
4649 	lib_remote_cpu_stats.cpu_system = omni_result->cpu_percent_system;
4650 	lib_remote_cpu_stats.cpu_iowait = omni_result->cpu_percent_iowait;
4651 	lib_remote_cpu_stats.cpu_irq = omni_result->cpu_percent_irq;
4652 	lib_remote_cpu_stats.cpu_swintr = omni_result->cpu_percent_swintr;
4653 	lib_remote_cpu_stats.peak_cpu_util = omni_result->peak_cpu_util;
4654 	lib_remote_cpu_stats.peak_cpu_id = omni_result->peak_cpu_id;
4655 	/* why?  because some stacks want to be clever and autotune their
4656 	   socket buffer sizes, which means that if we accept the defaults,
4657 	   the size we get from getsockopt() at the beginning of a
4658 	   connection may not be what we would get at the end of the
4659 	   connection... */
4660 	rsr_size_end = omni_result->recv_buf_size;
4661 	rss_size_end = omni_result->send_buf_size;
4662 	remote_bytes_sent = (uint64_t)omni_result->bytes_sent_hi << 32;
4663 	remote_bytes_sent += omni_result->bytes_sent_lo;
4664 	remote_send_calls = omni_result->send_calls;
4665 	remote_bytes_received = (uint64_t)omni_result->bytes_received_hi << 32;
4666 	remote_bytes_received += omni_result->bytes_received_lo;
4667 	remote_receive_calls = omni_result->recv_calls;
4668 	remote_bytes_xferd = (double) remote_bytes_received +
4669 	                              remote_bytes_sent;
4670 	if (omni_result->recv_calls > 0)
4671 	  remote_bytes_per_recv = (double) remote_bytes_received /
4672 	    (double) omni_result->recv_calls;
4673 	else
4674 	  remote_bytes_per_recv = 0.0;
4675 	if (omni_result->send_calls > 0)
4676 	  remote_bytes_per_send = (double) remote_bytes_sent /
4677 	    (double) omni_result->send_calls;
4678 	else
4679 	  remote_bytes_per_send = 0.0;
4680 
4681 	remote_transport_retrans = omni_result->transport_retrans;
4682 	/* what was the congestion control? */
4683 	if (desired_output_groups & OMNI_WANT_REM_CONG) {
4684 	  strncpy(remote_cong_control,
4685 		  omni_result->cong_control,
4686 		  sizeof(remote_cong_control));
4687 	  remote_cong_control[sizeof(remote_cong_control) - 1] = '\0';
4688 	}
4689       }
4690       else {
4691 	Set_errno(netperf_response.content.serv_errno);
4692 	fprintf(where,
4693 		"netperf: remote error %d",
4694 		netperf_response.content.serv_errno);
4695 	perror("");
4696 	fflush(where);
4697 
4698 	exit(-1);
4699       }
4700     }
4701     else {
4702       /* when we are sending, in a no_control test, we have to
4703 	 ass-u-me that everything we sent was received, otherwise, we
4704 	 will report a transfer rate of zero. */
4705       remote_bytes_xferd = (double) bytes_sent;
4706     }
4707 
4708     /* so, what was the end result? */
4709     local_cpu_method = format_cpu_method(cpu_method);
4710 
4711     if (local_send_calls > 0)
4712       bytes_per_send = (double) bytes_sent / (double) local_send_calls;
4713     else bytes_per_send = 0.0;
4714 
4715     if (local_receive_calls > 0)
4716       bytes_per_recv = (double) bytes_received / (double) local_receive_calls;
4717     else
4718       bytes_per_recv = 0.0;
4719 
4720     bytes_xferd  = (double) bytes_sent + bytes_received;
4721 
4722     /* if the output format is 'x' we know the test was
4723        request/response.  if the libfmt is something else, it could be
4724        xmit, recv or bidirectional. if we were the receiver then we
4725        can use our byte totals even if it is
4726        UDP/unreliable. otherwise, we use the remote totals - they
4727        should be the same if the protocol is reliable, and if it is
4728        unreliable then we want what was actually received */
4729     if ('x' == libfmt)
4730       /* it was a request/response test */
4731       thruput = calc_thruput((double)trans_completed);
4732     else if (NETPERF_RECV_ONLY(direction))
4733       thruput      = calc_thruput(bytes_xferd);
4734     else
4735       thruput = calc_thruput(remote_bytes_xferd);
4736 
4737     if (NETPERF_IS_RR(direction)) {
4738       float rtt_elapsed_time = elapsed_time;
4739 
4740 #ifdef WANT_INTERVALS
4741       /* if the test was paced, we need to subtract the time we were
4742 	 sitting paced from the time we use to calculate the average
4743 	 rtt_latency. Of course, won't really know how long we were
4744 	 sitting unless we bracket the sit with timing calls, which
4745 	 will be additional overhead affecting CPU utilization.  but,
4746 	 there is no such thing as a free lunch is there :) raj
4747 	 20110121 */
4748       if (interval_burst) {
4749 	rtt_elapsed_time -= (float)(interval_wait_microseconds / 1000000.0);
4750       }
4751 #endif /* WANT_INTERVALS */
4752 
4753       if (!connection_test) {
4754       /* calculate the round trip latency, using the transaction rate
4755 	 whether or not the user was asking for thruput to be in 'x'
4756 	 units please... however... a connection_test only ever has
4757 	 one transaction in flight at one time */
4758       rtt_latency =
4759 	(((double)1.0/(trans_completed/rtt_elapsed_time)) *
4760 	 (double)1000000.0) *
4761 	(double) (1 + ((first_burst_size > 0) ? first_burst_size : 0));
4762       }
4763       else {
4764 	rtt_latency = ((double)1.0/(trans_completed/rtt_elapsed_time)) *
4765 	  (double)1000000.0;
4766       }
4767       tmpfmt = libfmt;
4768       libfmt = 'x';
4769       transaction_rate = calc_thruput((double)trans_completed);
4770       libfmt = tmpfmt;
4771     }
4772 
4773     /* ok, time to possibly calculate cpu util and/or service demand */
4774     if (local_cpu_usage) {
4775 
4776       local_cpu_utilization = calc_cpu_util(elapsed_time);
4777 
4778       /* we need to decide what to feed the service demand beast,
4779 	 which will, ultimately, depend on what sort of test it is and
4780 	 whether or not the user asked for something specific - as in
4781 	 per KB even on a TCP_RR test if it is being (ab)used as a
4782 	 bidirectional bulk-transfer test. raj 2008-01-14 */
4783       local_service_demand  =
4784 	calc_service_demand_fmt(('x' == libfmt) ? (double)trans_completed: bytes_xferd,
4785 				0.0,
4786 				0.0,
4787 				0);
4788     }
4789     else {
4790       local_cpu_utilization	= (float) -1.0;
4791       local_service_demand	= (float) -1.0;
4792     }
4793 
4794     if (remote_cpu_usage) {
4795 
4796       remote_cpu_utilization = omni_result->cpu_util;
4797 
4798       remote_service_demand =
4799 	calc_service_demand_fmt(('x' == libfmt) ? (double) trans_completed: bytes_xferd,
4800 				0.0,
4801 				remote_cpu_utilization,
4802 				omni_result->num_cpus);
4803     }
4804     else {
4805       remote_cpu_utilization = (float) -1.0;
4806       remote_service_demand  = (float) -1.0;
4807     }
4808 
4809     /* time to calculate our confidence */
4810     calculate_confidence(confidence_iteration,
4811 			 elapsed_time,
4812 			 thruput,
4813 			 local_cpu_utilization,
4814 			 remote_cpu_utilization,
4815 			 local_service_demand,
4816 			 remote_service_demand);
4817 
4818     /* this this is the end of the confidence while loop? */
4819     confidence_iteration++;
4820   }
4821 
4822   /* we end with confidence_iteration one larger than the number of
4823      iterations.  if we weren't doing confidence intervals this will
4824      still be reported as one */
4825   confidence_iteration--;
4826 
4827 #if defined(WANT_INTERVALS)
4828 #ifdef WIN32
4829   stop_itimer();
4830 #endif
4831 #endif /* WANT_INTERVALS */
4832 
4833 /* at some point we may want to actually display some results :) */
4834 
4835   retrieve_confident_values(&elapsed_time,
4836 			    &thruput,
4837 			    &local_cpu_utilization,
4838 			    &remote_cpu_utilization,
4839 			    &local_service_demand,
4840 			    &remote_service_demand);
4841 
4842   /* a kludge for omni printing because I don't know how to tell that
4843      something is a float vs a double in my_snprintf() given what it
4844      is passed and I'm not ready to force all the netlib.c stuff to
4845      use doubles rather than floats. help there would be
4846      appreciated. raj 2008-01-28 */
4847   elapsed_time_double = (double) elapsed_time;
4848   local_service_demand_double = (double)local_service_demand;
4849   remote_service_demand_double = (double)remote_service_demand;
4850 
4851   if ('x' == libfmt) sd_str = "usec/Tran";
4852   else sd_str = "usec/KB";
4853 
4854   if (iteration_max > 1) {
4855     result_confid_pct = get_result_confid();
4856     loc_cpu_confid_pct = get_loc_cpu_confid();
4857     rem_cpu_confid_pct = get_rem_cpu_confid();
4858     interval_pct = interval * 100.0;
4859   }
4860 
4861   /* at some point we need to average these during a confidence
4862      interval run, and when we do do that, we need to make sure we
4863      restore the value of libfmt correctly */
4864   tmpfmt = libfmt;
4865   if ('x' == libfmt) {
4866     libfmt = 'm';
4867   }
4868   local_send_thruput = calc_thruput((double)bytes_sent);
4869   local_recv_thruput = calc_thruput((double)bytes_received);
4870   remote_send_thruput = calc_thruput((double)remote_bytes_sent);
4871   remote_recv_thruput = calc_thruput((double)remote_bytes_received);
4872 
4873   libfmt = tmpfmt;
4874 
4875   /* were we tracking possibly expensive statistics? */
4876   if (keep_statistics) {
4877     HIST_get_stats(time_hist,
4878 		   &min_latency,
4879 		   &max_latency,
4880 		   &mean_latency,
4881 		   &stddev_latency);
4882     p50_latency = HIST_get_percentile(time_hist, 0.50);
4883     p90_latency = HIST_get_percentile(time_hist, 0.90);
4884     p99_latency = HIST_get_percentile(time_hist, 0.99);
4885 
4886   }
4887 
4888   /* if we are running a legacy test we do not do the nifty new omni
4889      output stuff */
4890   if (!legacy) {
4891     print_omni();
4892   }
4893 
4894 #if defined(DEBUG_OMNI_OUTPUT)
4895  {
4896    /* just something quick to sanity check the output selectors. this
4897       should be gone for "production" :) */
4898    int i;
4899    print_omni_init();
4900    output_list[0][1] = OUTPUT_END;
4901    for (i = OUTPUT_NONE; i < NETPERF_OUTPUT_MAX; i++) {
4902      output_list[0][0] = i;
4903      print_omni_csv();
4904    }
4905  }
4906 #endif
4907 
4908   /* likely as not we are going to do something slightly different here */
4909   if ((verbosity > 1) && (!legacy)) {
4910 
4911 #ifdef WANT_HISTOGRAM
4912     fprintf(where,"\nHistogram of ");
4913     if (NETPERF_RECV_ONLY(direction))
4914       fprintf(where,"recv");
4915     if (NETPERF_XMIT_ONLY(direction))
4916       fprintf(where,"send");
4917     if (NETPERF_IS_RR(direction)) {
4918       if (connection_test) {
4919 	if (NETPERF_CC(direction)) {
4920 	  fprintf(where,"connect/close");
4921 	}
4922 	else {
4923 	  fprintf(where,"connect/request/response/close");
4924 	}
4925       }
4926       else {
4927 	fprintf(where,"request/response");
4928       }
4929     }
4930     fprintf(where," times\n");
4931     HIST_report(time_hist);
4932     fflush(where);
4933 #endif /* WANT_HISTOGRAM */
4934 
4935   }
4936 
4937 }
4938 
4939 
4940 void
send_omni(char remote_host[])4941 send_omni(char remote_host[])
4942 {
4943   char name_buf[32];
4944   snprintf(name_buf,sizeof(name_buf),"OMNI %s TEST",direction_str);
4945   name_buf[31] = '\0';
4946   send_omni_inner(remote_host, 0, name_buf);
4947 }
4948 
4949 #if defined(WIN32)
4950 #if !defined(InetNtop)
4951 /* +*+ Why isn't this in the winsock headers yet? */
4952 const char *
4953 inet_ntop(int af, const void *src, char *dst, size_t size);
4954 #endif
4955 #endif
4956 
4957 static void
set_hostname_and_port_2(void * addr,char * hostname,char * portstr,int family,int port)4958 set_hostname_and_port_2(void *addr, char *hostname, char *portstr, int family, int port)
4959 {
4960 
4961   inet_ntop(family, addr, hostname, BUFSIZ);
4962 
4963   sprintf(portstr, "%u", port);
4964 
4965 }
4966 
4967 
4968 
4969 /* the name is something of a misnomer since this test could send, or
4970    receive, or both, but it matches the historical netperf routine
4971    naming convention for what runs in the netserver context. */
4972 void
recv_omni()4973 recv_omni()
4974 {
4975 
4976   struct addrinfo *local_res;
4977   char local_name[BUFSIZ];
4978   char port_buffer[PORTBUFSIZE];
4979 
4980   struct sockaddr_storage myaddr_in, peeraddr_in;
4981   int peeraddr_set = 0;
4982   SOCKET s_listen, data_socket;
4983   netperf_socklen_t 	addrlen;
4984 
4985   struct ring_elt *send_ring;
4986   struct ring_elt *recv_ring;
4987 
4988   int	timed_out = 0;
4989   int   pad_time = 0;
4990   int   need_to_connect = 0;
4991   int   need_to_accept;
4992   int   connected;
4993   int   ret;
4994   uint32_t   temp_recvs;
4995 
4996   struct	omni_request_struct	*omni_request;
4997   struct	omni_response_struct	*omni_response;
4998   struct	omni_results_struct	*omni_results;
4999 
5000   omni_request =
5001     (struct omni_request_struct *)netperf_request.content.test_specific_data;
5002   omni_response =
5003     (struct omni_response_struct *)netperf_response.content.test_specific_data;
5004   omni_results =
5005     (struct omni_results_struct *)netperf_response.content.test_specific_data;
5006 
5007   if (debug) {
5008     fprintf(where,"netserver: %s: entered...\n",__FUNCTION__);
5009     fflush(where);
5010   }
5011 
5012   /* netserver has no good way of knowing where the conversion cutoff
5013      point is, so we have to fix it after the fact */
5014   fixup_request_n(OMNI_REQUEST_CONV_CUTOFF);
5015 
5016   /* thus fixed-up, we can extract the requested congestion control
5017      algorithm */
5018   strncpy(local_cong_control_req,
5019 	  omni_request->cong_control,
5020 	  sizeof(local_cong_control_req));
5021 
5022   /* based on what we have been told by the remote netperf, we want to
5023      setup our endpoint for the "data connection" and let the remote
5024      netperf know the situation. */
5025 
5026   if (debug) {
5027     fprintf(where,"%s: setting the response type...\n",__FUNCTION__);
5028     fflush(where);
5029   }
5030 
5031   netperf_response.content.response_type = OMNI_RESPONSE;
5032 
5033   if (debug) {
5034     fprintf(where,"%s: the response type is set...\n",__FUNCTION__);
5035     fflush(where);
5036   }
5037 
5038   /* Grab a socket to listen on, and then listen on it. */
5039 
5040   if (debug) {
5041     fprintf(where,"%s: grabbing a socket...\n",__FUNCTION__);
5042     fflush(where);
5043   }
5044 
5045   /* create_data_socket expects to find some things in the global
5046      variables, so set the globals based on the values in the request.
5047      once the socket has been created, we will set the response values
5048      based on the updated value of those globals. raj 7/94 */
5049   lss_size_req    = omni_request->send_buf_size;
5050   lsr_size_req    = omni_request->recv_buf_size;
5051   loc_nodelay     = (omni_request->flags) & OMNI_NO_DELAY;
5052   loc_rcvavoid    = omni_request->so_rcvavoid;
5053   loc_sndavoid    = omni_request->so_sndavoid;
5054   routing_allowed = (omni_request->flags) & OMNI_ROUTING_ALLOWED;
5055   want_keepalive  = (omni_request->flags) & OMNI_WANT_KEEPALIVE;
5056   local_socket_prio = omni_request->socket_prio;
5057   local_socket_tos  = omni_request->socket_tos;
5058   want_defer_accept = omni_request->flags & OMNI_WANT_DEFER_ACCEPT;
5059 
5060 #ifdef WANT_INTERVALS
5061   interval_usecs = omni_request->interval_usecs;
5062   interval_wate  = interval_usecs / 1000;
5063   interval_burst = omni_request->interval_burst;
5064 #else
5065   interval_usecs = 0;
5066   interval_wate  = 1;
5067   interval_burst = 0;
5068 #endif
5069 
5070   connection_test = omni_request->flags & OMNI_CONNECT_TEST;
5071 #ifdef TCP_FASTOPEN
5072   use_fastopen = omni_request->flags & OMNI_FASTOPEN;
5073 #endif
5074   direction       = omni_request->direction;
5075   use_pktinfo = (omni_request->flags) & OMNI_USE_PKTINFO;
5076 
5077   /* let's be quite certain the fill file string is null terminated */
5078   omni_request->fill_file[sizeof(omni_request->fill_file) - 1] = '\0';
5079   strncpy(local_fill_file,
5080 	  omni_request->fill_file,
5081 	  sizeof(local_fill_file));
5082 
5083   /* kludgy, because I have no way at present to say how many bytes
5084      needed to be swapped around for the request from which this is
5085      pulled, and it is probably all wrong for IPv6 :( */
5086   switch (nf_to_af(omni_request->ipfamily)) {
5087   case AF_INET6:
5088     /* yes indeed it is, do nothing, bz */
5089     break;
5090   case AF_INET:
5091   default:
5092     for (ret=0; ret < 4; ret++) {
5093       omni_request->netserver_ip[ret] = htonl(omni_request->netserver_ip[ret]);
5094       omni_request->netperf_ip[ret] = htonl(omni_request->netperf_ip[ret]);
5095     }
5096     break;
5097   }
5098 
5099   set_hostname_and_port_2(omni_request->netserver_ip,
5100 			  local_name,
5101 			  port_buffer,
5102 			  nf_to_af(omni_request->ipfamily),
5103 			  omni_request->data_port);
5104 
5105   local_res = complete_addrinfo(local_name,
5106 				local_name,
5107 				port_buffer,
5108 				nf_to_af(omni_request->ipfamily),
5109 				nst_to_hst(omni_request->socket_type),
5110 				omni_request->protocol,
5111 				0);
5112 
5113   s_listen = omni_create_data_socket(local_res);
5114 
5115   if (s_listen == INVALID_SOCKET) {
5116     netperf_response.content.serv_errno = errno;
5117     send_response();
5118     if (debug) {
5119       fprintf(where,"could not create data socket\n");
5120       fflush(where);
5121     }
5122     exit(-1);
5123   }
5124 
5125   /* We now alter the message_ptr variables to be at the desired */
5126   /* alignments with the desired offsets. */
5127 
5128   if (debug) {
5129     fprintf(where,
5130 	    "recv_omni: requested recv alignment of %d offset %d\n"
5131 	    "recv_omni: requested send alignment of %d offset %d\n",
5132 	    omni_request->recv_alignment,
5133 	    omni_request->recv_offset,
5134 	    omni_request->send_alignment,
5135 	    omni_request->send_offset);
5136     fflush(where);
5137   }
5138 
5139   omni_response->send_size = omni_request->send_size;
5140   omni_response->send_width = omni_request->send_width;
5141   omni_response->socket_prio = local_socket_prio;
5142   omni_response->socket_tos = local_socket_tos;
5143 
5144   if (omni_request->direction & NETPERF_XMIT) {
5145 #ifdef fo
5146     /* do we need to set multicast ttl? */
5147     if (is_multicast_addr(remote_res)) {
5148       /* yes, s_listen - for a UDP test we will be copying it to
5149 	 data_socket but that hasn't happened yet. raj 20100315 */
5150       set_multicast_ttl(s_listen);
5151     }
5152 #endif
5153 
5154     if (omni_request->response_size > 0) {
5155       /* request/response_test */
5156       bytes_to_send = omni_request->response_size;
5157       if (omni_request->send_width == 0) send_width = 1;
5158       else send_width = omni_request->send_width;
5159     }
5160     else {
5161       if (omni_request->send_size == -1) {
5162 	bytes_to_send = choose_send_size(lss_size,omni_request->protocol);
5163       }
5164       else bytes_to_send = omni_request->send_size;
5165       /* set the send_width */
5166       if (omni_request->send_width == 0) {
5167 	send_width = (lss_size/bytes_to_send) + 1;
5168 	if (send_width == 1) send_width++;
5169       }
5170       else
5171 	send_width = omni_request->send_width;
5172     }
5173     send_ring = allocate_buffer_ring(send_width,
5174 				     bytes_to_send,
5175 				     omni_request->send_alignment,
5176 				     omni_request->send_offset);
5177 
5178     omni_response->send_width = send_width;
5179     omni_response->send_size = bytes_to_send;
5180   }
5181 
5182   omni_response->receive_size = omni_request->receive_size;
5183   omni_response->recv_width = omni_request->recv_width;
5184   if (omni_request->direction & NETPERF_RECV) {
5185 
5186     /* do we need to join a multicast group? */
5187     if (is_multicast_addr(local_res)) {
5188       /* yes, s_listen - for a UDP test we will be copying it to
5189 	 data_socket but that hasn't happened yet. raj 20100315 */
5190       join_multicast_addr(s_listen, local_res);
5191     }
5192 
5193     if (omni_request->request_size > 0) {
5194       /* request/response test */
5195       bytes_to_recv = omni_request->request_size;
5196       if (omni_request->recv_width == 0) recv_width = 1;
5197       else recv_width = omni_request->recv_width;
5198     }
5199     else {
5200       if (omni_request->receive_size == -1) {
5201 	if (lsr_size > 0) bytes_to_recv = lsr_size;
5202 	else  bytes_to_recv = 4096;
5203       }
5204       else {
5205 	bytes_to_recv = omni_request->receive_size;
5206       }
5207       /* set the recv_width */
5208       if (omni_request->recv_width == 0) {
5209 	recv_width = (lsr_size/bytes_to_recv) + 1;
5210 	if (recv_width == 1) recv_width++;
5211       }
5212       else
5213 	recv_width = omni_request->recv_width;
5214     }
5215     recv_ring = allocate_buffer_ring(recv_width,
5216 				     bytes_to_recv,
5217 				     omni_request->recv_alignment,
5218 				     omni_request->recv_offset);
5219 
5220     omni_response->receive_size = bytes_to_recv;
5221     omni_response->recv_width = recv_width;
5222   }
5223 
5224 #ifdef WIN32
5225   /* The test timer can fire during operations on the listening socket,
5226      so to make the start_timer below work we have to move
5227      it to close s_listen while we are blocked on accept. */
5228   win_kludge_socket2 = s_listen;
5229 #endif
5230 
5231   need_to_accept = (omni_request->protocol != IPPROTO_UDP);
5232 
5233   /* we need to hang a listen for everything that needs at least one
5234      accept. the age-old constant of 5 is probably OK for our purposes
5235      but does not necessarily represent best practice */
5236   if (need_to_accept) {
5237     int backlog = 5;
5238 #ifdef TCP_FASTOPEN
5239     /* one of these days I will have to go find-out what the backlog
5240        is supposed to be here.  until then, I'll just set it to five
5241        like the listen() call does - it is classic, and was what was
5242        used in the online example I found */
5243     if (use_fastopen &&
5244 	(setsockopt(s_listen,IPPROTO_TCP, TCP_FASTOPEN, &backlog, sizeof(backlog)) ==
5245 	 SOCKET_ERROR)) {
5246       netperf_response.content.serv_errno = errno;
5247       close(s_listen);
5248       send_response();
5249       if (debug) {
5250 	fprintf(where,"netperfserver: %s could not fastopen\n",__FUNCTION__);
5251 	fflush(where);
5252       }
5253       exit(1);
5254     }
5255 #endif /* TCP_FASTOPEN */
5256 #ifdef TCP_DEFER_ACCEPT
5257     if (want_defer_accept &&
5258 	(setsockopt(s_listen, IPPROTO_TCP, TCP_DEFER_ACCEPT, &backlog, sizeof(backlog)) == SOCKET_ERROR)) {
5259       netperf_response.content.serv_errno = errno;
5260       close(s_listen);
5261       send_response();
5262       if (debug) {
5263 	fprintf(where,
5264 		"netperfserver: %s could not defer accept\n",__FUNCTION__);
5265 	fflush(where);
5266       }
5267       exit(1);
5268     }
5269 #endif /* TCP_DEFER_ACCEPT */
5270     if (listen(s_listen, backlog) == SOCKET_ERROR) {
5271       netperf_response.content.serv_errno = errno;
5272       close(s_listen);
5273       send_response();
5274       if (debug) {
5275 	fprintf(where,"netperfserver: %s could not listen\n",__FUNCTION__);
5276 	fflush(where);
5277       }
5278       exit(1);
5279     }
5280   }
5281 
5282   /* now get the port number assigned by the system  */
5283   addrlen = sizeof(myaddr_in);
5284   if (getsockname(s_listen,
5285 		  (struct sockaddr *)&myaddr_in,
5286 		  &addrlen) == SOCKET_ERROR){
5287     netperf_response.content.serv_errno = errno;
5288     close(s_listen);
5289     send_response();
5290     if (debug) {
5291       fprintf(where,"could not getsockname\n");
5292       fflush(where);
5293     }
5294     exit(-1);
5295   }
5296 
5297   /* Now myaddr_in contains the port and the internet address this is
5298      returned to the sender also implicitly telling the sender that
5299      the socket buffer sizing has been done. likely as not, the IP
5300      address will be the wildcard - so we only really need to extract
5301      the port number. since send_response is going to call htonl on
5302      all the fields, we want to initially put the port number in there
5303      in host order. */
5304 
5305   omni_response->data_port =
5306     (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
5307   if (debug) {
5308     fprintf(where,"telling the remote to call me at %d\n",
5309 	    omni_response->data_port);
5310     fflush(where);
5311   }
5312   netperf_response.content.serv_errno   = 0;
5313 
5314   /* But wait, there's more. If the initiator wanted cpu measurements, */
5315   /* then we must call the calibrate routine, which will return the max */
5316   /* rate back to the initiator. If the CPU was not to be measured, or */
5317   /* something went wrong with the calibration, we will return a 0.0 to */
5318   /* the initiator. */
5319 
5320   omni_response->cpu_rate = (float)0.0; 	/* assume no cpu */
5321   omni_response->flags &= ~OMNI_MEASURE_CPU;
5322   if (omni_request->flags & OMNI_MEASURE_CPU) {
5323     omni_response->flags |= OMNI_MEASURE_CPU;
5324     omni_response->cpu_rate =
5325       calibrate_local_cpu(omni_request->cpu_rate);
5326   }
5327 
5328   /* before we send the response back to the initiator, pull some of */
5329   /* the socket parms from the globals */
5330   omni_response->send_buf_size = lss_size;
5331   omni_response->recv_buf_size = lsr_size;
5332   if (loc_nodelay)
5333     omni_response->flags |= OMNI_NO_DELAY;
5334   else
5335     omni_response->flags &= ~OMNI_NO_DELAY;
5336 
5337   omni_response->so_rcvavoid = loc_rcvavoid;
5338   omni_response->so_sndavoid = loc_sndavoid;
5339   omni_response->interval_usecs = interval_usecs;
5340   omni_response->interval_burst = interval_burst;
5341 
5342   send_response_n(OMNI_RESPONSE_CONV_CUTOFF); /* brittle, but functional */
5343 
5344   local_send_calls = 0;
5345   local_receive_calls = 0;
5346 
5347   addrlen = sizeof(peeraddr_in);
5348   memset(&peeraddr_in,0,sizeof(peeraddr_in));
5349 
5350   /* Now it's time to start receiving data on the connection. We will */
5351   /* first grab the apropriate counters and then start grabbing. */
5352 
5353   cpu_start(omni_request->flags & OMNI_MEASURE_CPU);
5354 
5355   /* if the test is timed, set a timer of suitable length.  if the
5356      test is by byte/transaction count, we don't need a timer - or
5357      rather we rely on the netperf to only ask us to do transaction
5358      counts over "reliable" protocols.  perhaps at some point we
5359      should add a check herebouts to verify that... */
5360 
5361   if (omni_request->test_length >= 0) {
5362     times_up = 0;
5363     units_remaining = 0;
5364 	test_time=omni_request->test_length;
5365     /* if we are the sender and only sending, then we don't need/want
5366        the padding, otherwise, we need the padding */
5367     if (!(NETPERF_XMIT_ONLY(omni_request->direction)) &&
5368 	(omni_request->test_length > 0))
5369       pad_time = PAD_TIME;
5370     start_timer(omni_request->test_length + pad_time);
5371   }
5372   else {
5373     times_up = 1;
5374     units_remaining = omni_request->test_length * -1;
5375   }
5376 
5377 #if defined(WANT_INTERVALS)
5378   INTERVALS_INIT();
5379 #endif /* WANT_INTERVALS */
5380 
5381 
5382   trans_completed = 0;
5383   bytes_sent = 0;
5384   bytes_received = 0;
5385   connected = 0;
5386 
5387   while ((!times_up) || (units_remaining > 0)) {
5388 
5389     if (need_to_accept) {
5390       /* accept a connection from the remote */
5391 #ifdef WIN32
5392       /* The test timer will probably fire during this accept,
5393 	 so to make the start_timer above work we have to move
5394 	 it to close s_listen while we are blocked on accept. */
5395       win_kludge_socket = s_listen;
5396 #endif
5397       if ((data_socket=accept(s_listen,
5398 			      (struct sockaddr *)&peeraddr_in,
5399 			      &addrlen)) == INVALID_SOCKET) {
5400 	if (errno == EINTR) {
5401 	  /* the timer popped */
5402 	  times_up = 1; /* ostensibly the signal hander dealt with this?*/
5403 	  timed_out = 1;
5404 	  break;
5405 	}
5406 	netperf_response.content.serv_errno = errno;
5407 	send_response();
5408 	fprintf(where,"%s: accept: errno = %d\n",__FUNCTION__,errno);
5409 	fflush(where);
5410 	close(s_listen);
5411 
5412 	exit(-1);
5413       }
5414 
5415       if (debug) {
5416 	fprintf(where,"%s: accepted data connection.\n",__FUNCTION__);
5417 	fflush(where);
5418       }
5419       need_to_accept = 0;
5420       connected = 1;
5421 
5422 #ifdef KLUDGE_SOCKET_OPTIONS
5423       /* this is for those systems which *INCORRECTLY* fail to pass
5424 	 attributes across an accept() call. Including this goes
5425 	 against my better judgement :( raj 11/95 */
5426 
5427       kludge_socket_options(data_socket);
5428 
5429 #endif /* KLUDGE_SOCKET_OPTIONS */
5430 
5431     }
5432     else {
5433       /* I wonder if duping would be better here? we also need to set
5434 	 peeraddr_in so we can send to netperf if this isn't a
5435 	 request/response test or if we are going to connect() the
5436 	 socket, but we only need to do it once. */
5437       if ((omni_request->protocol == IPPROTO_UDP) &&
5438 	  (!peeraddr_set)) {
5439 	peeraddr_set = 1;
5440 	data_socket = s_listen;
5441 	set_sockaddr_family_addr_port(&peeraddr_in,
5442 				      nf_to_af(omni_request->ipfamily),
5443 				      omni_request->netperf_ip,
5444 				      omni_request->netperf_port);
5445       }
5446     }
5447 
5448 #ifdef WIN32
5449   /* this is used so the timer thread can close the socket out from
5450      under us, which to date is the easiest/cleanest/least
5451      Windows-specific way I can find to force the winsock calls to
5452      return WSAEINTR with the test is over. anything that will run on
5453      95 and NT and is closer to what netperf expects from Unix signals
5454      and such would be appreciated raj 1/96 */
5455   win_kludge_socket = data_socket;
5456 #endif /* WIN32 */
5457 
5458     /* in recv_omni, we check recv first, and _then_ send, otherwise,
5459        a request/response test will be all messed-up :) and that then
5460        is why there are two routines to rule them all rather than just
5461        one :) */
5462     if ((omni_request->direction & NETPERF_RECV) &&
5463 	((!times_up) || (units_remaining > 0))) {
5464       ret = recv_data(data_socket,
5465 		      recv_ring,
5466 		      bytes_to_recv,
5467 		      (connected) ? NULL : (struct sockaddr *)&peeraddr_in,
5468 		      &addrlen,
5469 		      /* if XMIT also, then this is RR test so waitall */
5470 		      (direction & NETPERF_XMIT) ? NETPERF_WAITALL: 0,
5471 		      &temp_recvs);
5472       if (ret > 0) {
5473 	/* if this is a recv-only test controlled by byte count we
5474 	   decrement the units_remaining by the bytes received */
5475 	if (!(direction & NETPERF_XMIT) && (units_remaining > 0)) {
5476 	  units_remaining -= ret;
5477 	}
5478 	bytes_received += ret;
5479 	local_receive_calls += temp_recvs;
5480       }
5481       else if (ret == 0) {
5482 	/* is this the end of a test, just a zero-byte recv, or
5483 	   something else? that is an exceedingly good question and
5484 	   one for which I don't presently have a good answer, but
5485 	   that won't stop me from guessing :) raj 2008-01-09 */
5486 	if (!((connection_test) || (null_message_ok))) {
5487 	  /* if it is neither a connection_test nor null_message_ok it
5488 	     must be the end of the test */
5489 	  times_up = 1;
5490 	  break;
5491 	}
5492 	local_receive_calls += temp_recvs;
5493       }
5494       else if (ret == -1) {
5495 	/* test timed-out */
5496 	times_up = 1;
5497 	timed_out = 1;
5498 	break;
5499       }
5500       else {
5501 	/* presently at least, -2 and -3 are equally bad on recv */
5502 	/* we need a response message here for the control connection
5503 	   before we exit! */
5504 	netperf_response.content.serv_errno = errno;
5505 	send_response();
5506 	exit(-1);
5507       }
5508       recv_ring = recv_ring->next;
5509     }
5510 
5511     /* if we should try to send something, then by all means, let us
5512        try to send something. */
5513     if ((omni_request->direction & NETPERF_XMIT) &&
5514 	((!times_up) || (units_remaining > 0))) {
5515 
5516       /* there used to be some code here looking sched_yield() until
5517 	 there was no more queued, unsent data on the socket but
5518 	 frankly, I've no idea what that was all about so I have
5519 	 removed it. It may have been part of a kludge to try to avoid
5520 	 coalescing requests and responses */
5521 
5522       if (omni_request->protocol == IPPROTO_UDP && need_to_connect &&
5523           !connected) {
5524         if (connect(data_socket,
5525                     (struct sockaddr*)&peeraddr_in,
5526                     addrlen) == INVALID_SOCKET) {
5527 	  netperf_response.content.serv_errno = errno;
5528 	  send_response();
5529 	  close(data_socket);
5530 	  exit(-1);
5531         }
5532         connected = 1;
5533       }
5534 
5535       ret = send_data(data_socket,
5536 		      send_ring,
5537 		      bytes_to_send,
5538 		      (connected) ? NULL : (struct sockaddr *)&peeraddr_in,
5539 		      addrlen,
5540 		      omni_request->protocol);
5541 
5542       /* the order of these if's will seem a triffle strange, but they
5543 	 are my best guess as to order of probabilty and/or importance
5544 	 to the overhead raj 2008-01-09*/
5545       if (ret == bytes_to_send) {
5546 	/* if this is a send-only test controlled by byte count we
5547 	   decrement units_remaining by the bytes sent */
5548 	if (!(direction & NETPERF_RECV) && (units_remaining > 0)) {
5549 	  units_remaining -= ret;
5550 	}
5551 	bytes_sent += ret;
5552 	send_ring = send_ring->next;
5553 	local_send_calls++;
5554       }
5555       else if (ret == -2) {
5556 	/* what to do here -2 means a non-fatal error - probably
5557 	   ENOBUFS and so our send didn't happen.  in the old code for
5558 	   UDP_STREAM we would just continue in the while loop.  it
5559 	   isn't clear that is what to do here, so we will simply
5560 	   increment the failed_sends stat and fall-through. If this
5561 	   is a UDP_STREAM style of test, the net effect should be the
5562 	   same. if this is a UDP_RR with a really-big burst count, I
5563 	   don't think we were checking for ENOBUFS there anyway and
5564 	   so would have failed.  Here we can just let things
5565 	   slide. */
5566 	failed_sends++;
5567       }
5568       else if (ret == 0) {
5569 	/* was this a zero-byte send? if it was, then ostensibly we
5570 	   would hit the ret == bytes_to_send case which means we'd
5571 	   never get here as we are using blocking semantics */
5572       }
5573       else if (ret == -1) {
5574 	times_up = 1;
5575 	timed_out = 1;
5576 	break;
5577       }
5578       else {
5579 	/* we need a response message back to netperf here before we
5580 	   exit */
5581 	/* NEED RESPONSE; */
5582 	netperf_response.content.serv_errno = errno;
5583 	send_response();
5584 	exit(-1);
5585       }
5586 
5587     }
5588 
5589     if (connection_test) {
5590 #ifdef __linux
5591       /* so, "Linux" with autotuning likes to alter the socket buffer
5592 	 sizes over the life of the connection, but only does so when
5593 	 one takes the defaults at time of socket creation.  if we
5594 	 took those defaults, we should inquire as to what the values
5595 	 ultimately became. raj 2008-01-15 */
5596       /* but as annoying as it is to have to make these calls, don't
5597 	 penalize linux by calling them over and over again. instead
5598 	 we will simply ass-u-me that it will become the same value
5599 	 over and over again. raj 20100917 */
5600       if ((lsr_size_req < 0) && (-1 == lsr_size_end))
5601 	get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end);
5602       else
5603 	lsr_size_end = lsr_size;
5604       if ((lss_size_req < 0) && (-1 == lss_size_end))
5605 	get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end);
5606       else
5607 	lss_size_end = lss_size;
5608 #else
5609       lsr_size_end = lsr_size;
5610       lss_size_end = lss_size;
5611 #endif
5612       ret = close_data_socket(data_socket,NULL,0,omni_request->protocol);
5613       if (ret == -1) {
5614 	times_up = 1;
5615 	timed_out = 1;
5616 	break;
5617       }
5618       else if (ret < 0) {
5619 	netperf_response.content.serv_errno = errno;
5620 	send_response();
5621 	perror("netperf: recv_omni: close_data_socket failed");
5622 	fflush(where);
5623 	exit(-1);
5624       }
5625       /* we will need a new connection to be established */
5626       need_to_accept = 1;
5627       connected = 0;
5628     }
5629 
5630 #if defined(WANT_INTERVALS)
5631     INTERVALS_WAIT();
5632 #endif /* WANT_INTERVALS */
5633 
5634     /* was this a "transaction" test? don't for get that a TCP_CC
5635        style test will have no xmit or recv :) so, we check for either
5636        both XMIT and RECV set, or neither XMIT nor RECV set */
5637     if (NETPERF_IS_RR(omni_request->direction)) {
5638       trans_completed++;
5639       if (units_remaining) {
5640 	units_remaining--;
5641       }
5642     }
5643   }
5644 
5645   /* The current iteration loop now exits due to timeout or unit count
5646      being  reached */
5647   stop_timer();
5648   cpu_stop(omni_request->flags & OMNI_MEASURE_CPU,&elapsed_time);
5649   close(s_listen);
5650 
5651 #if defined(WANT_INTERVALS)
5652 #ifdef WIN32
5653   stop_itimer();
5654 #endif
5655 #endif /* WANT_INTERVALS */
5656 
5657  if (timed_out) {
5658     /* we ended the test by time, which may have been PAD_TIME seconds
5659        longer than we wanted to run. so, we want to subtract pad_time
5660        from the elapsed_time. if we didn't pad the timer pad_time will
5661        be 0 so we can just subtract it anyway :) */
5662     if (debug) {
5663       fprintf(where,"Adjusting elapsed time by %d seconds\n",pad_time);
5664       fflush(where);
5665     }
5666     elapsed_time -= pad_time;
5667   }
5668 
5669   remote_transport_retrans = get_transport_retrans(data_socket,
5670 						   omni_request->protocol);
5671 
5672   if (connected) {
5673 #ifdef __linux
5674     /* so, "Linux" with autotuning likes to alter the socket buffer
5675        sizes over the life of the connection, but only does so when
5676        one takes the defaults at time of socket creation.  if we took
5677        those defaults, we should inquire as to what the values
5678        ultimately became. raj 2008-01-15 */
5679     if (lsr_size_req < 0)
5680       get_sock_buffer(data_socket, RECV_BUFFER, &lsr_size_end);
5681     else
5682       lsr_size_end = lsr_size;
5683     if (lss_size_req < 0)
5684       get_sock_buffer(data_socket, SEND_BUFFER, &lss_size_end);
5685     else
5686       lss_size_end = lss_size;
5687 #else
5688     lsr_size_end = lsr_size;
5689     lss_size_end = lss_size;
5690 #endif
5691     if (omni_request->flags & OMNI_WANT_REM_CONG) {
5692       get_transport_cong_control(data_socket,
5693 				 local_res->ai_protocol,
5694 				 omni_results->cong_control,
5695 				 sizeof(omni_results->cong_control));
5696     }
5697     else {
5698       strncpy(omni_results->cong_control,"",sizeof(omni_results->cong_control));
5699     }
5700 
5701 
5702     close_data_socket(data_socket,NULL,0,omni_request->protocol);
5703   }
5704   else {
5705     close_data_socket(data_socket,(struct sockaddr *)&peeraddr_in,addrlen,omni_request->protocol);
5706     lsr_size_end = lsr_size;
5707     lss_size_end = lss_size;
5708   }
5709 
5710   /* send the results to the sender  */
5711 
5712   omni_results->send_calls      = (uint32_t) local_send_calls;
5713   omni_results->bytes_received_lo = bytes_received & 0x00000000FFFFFFFFULL;
5714   omni_results->bytes_received_hi = (bytes_received & 0xFFFFFFFF00000000ULL) >> 32;
5715   omni_results->recv_buf_size   = lsr_size_end;
5716   omni_results->recv_calls      = (uint32_t) local_receive_calls;
5717   omni_results->bytes_sent_lo   = bytes_sent & 0x00000000FFFFFFFFULL;
5718   omni_results->bytes_sent_hi   = (bytes_sent & 0xFFFFFFFF00000000ULL) >> 32;
5719   omni_results->send_buf_size   = lss_size_end;
5720   omni_results->trans_received	= (uint32_t) trans_completed;
5721   omni_results->elapsed_time	= elapsed_time;
5722   omni_results->transport_retrans = remote_transport_retrans;
5723   omni_results->cpu_method      = cpu_method;
5724   omni_results->num_cpus        = lib_num_loc_cpus;
5725   if (omni_request->flags & OMNI_MEASURE_CPU) {
5726     omni_results->cpu_util            = calc_cpu_util(elapsed_time);
5727     omni_results->cpu_percent_user    = lib_local_cpu_stats.cpu_user;
5728     omni_results->cpu_percent_system  = lib_local_cpu_stats.cpu_system;
5729     omni_results->cpu_percent_iowait  = lib_local_cpu_stats.cpu_iowait;
5730     omni_results->cpu_percent_irq     = lib_local_cpu_stats.cpu_irq;
5731     omni_results->cpu_percent_swintr  = lib_local_cpu_stats.cpu_swintr;
5732     omni_results->peak_cpu_util       = lib_local_cpu_stats.peak_cpu_util;
5733     omni_results->peak_cpu_id         = lib_local_cpu_stats.peak_cpu_id;
5734   }
5735 
5736 #if defined(WANT_INTERVALS)
5737 #ifdef WIN32
5738   stop_itimer();
5739 #endif
5740 #endif /* WANT_INTERVALS */
5741 
5742   if (debug) {
5743     fprintf(where,
5744 	    "%s: test complete, sending results.\n",
5745 	    __FUNCTION__);
5746     fflush(where);
5747   }
5748 
5749   send_response_n(OMNI_RESULTS_CONV_CUTOFF);
5750 
5751 }
5752 
5753 
5754 #ifdef WANT_MIGRATION
5755 void
send_tcp_stream(char remote_host[])5756 send_tcp_stream(char remote_host[])
5757 {
5758 
5759   char *tput_title = "\
5760 Recv   Send    Send                          \n\
5761 Socket Socket  Message  Elapsed              \n\
5762 Size   Size    Size     Time     Throughput  \n\
5763 bytes  bytes   bytes    secs.    %s/sec  \n\n";
5764 
5765   char *tput_fmt_0 =
5766     "%7.2f %s\n";
5767 
5768   char *tput_fmt_1 =
5769     "%6d %6d %6d    %-6.2f   %7.2f   %s\n";
5770 
5771   char *cpu_title = "\
5772 Recv   Send    Send                          Utilization       Service Demand\n\
5773 Socket Socket  Message  Elapsed              Send     Recv     Send    Recv\n\
5774 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
5775 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
5776 
5777   char *cpu_fmt_0 =
5778     "%6.3f %c %s\n";
5779 
5780   char *cpu_fmt_1 =
5781     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %s\n";
5782 
5783   char *ksink_fmt = "\n\
5784 Alignment      Offset         %-8.8s %-8.8s    Sends   %-8.8s Recvs\n\
5785 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
5786 Send   Recv    Send   Recv             Send (avg)          Recv (avg)\n\
5787 %5d   %5d  %5d   %5d %6"PRId64"  %6.2f    %6"PRId64"   %6.2f %6"PRId64"\n";
5788 
5789   char *ksink_fmt2 = "\n\
5790 Maximum\n\
5791 Segment\n\
5792 Size (bytes)\n\
5793 %6d\n";
5794 
5795   send_omni_inner(remote_host, legacy, "MIGRATED TCP STREAM TEST");
5796 
5797 
5798   if (legacy) {
5799 
5800     /* We are now ready to print all the information, but only if we
5801        are truly acting as a legacy test. If the user has specified
5802        zero-level verbosity, we will just print the local service
5803        demand, or the remote service demand. If the user has requested
5804        verbosity level 1, he will get the basic "streamperf"
5805        numbers. If the user has specified a verbosity of greater than
5806        1, we will display a veritable plethora of background
5807        information from outside of this block as it it not
5808        cpu_measurement specific...  */
5809 
5810     if (confidence < 0) {
5811       /* we did not hit confidence, but were we asked to look for it? */
5812       if (iteration_max > 1) {
5813 	display_confidence();
5814       }
5815     }
5816 
5817     if (local_cpu_usage || remote_cpu_usage) {
5818 
5819       switch (verbosity) {
5820       case 0:
5821 	if (local_cpu_usage) {
5822 	  fprintf(where,
5823 		  cpu_fmt_0,
5824 		  local_service_demand,
5825 		  local_cpu_method,
5826 		  ((print_headers) ||
5827 		   (result_brand == NULL)) ? "" : result_brand);
5828 	}
5829 	else {
5830 	  fprintf(where,
5831 		  cpu_fmt_0,
5832 		  remote_service_demand,
5833 		  remote_cpu_method,
5834 		  ((print_headers) ||
5835 		   (result_brand == NULL)) ? "" : result_brand);
5836 	}
5837 	break;
5838       case 1:
5839       case 2:
5840 	if (print_headers) {
5841 	  fprintf(where,
5842 		  cpu_title,
5843 		  format_units(),
5844 		  local_cpu_method,
5845 		  remote_cpu_method);
5846 	}
5847 
5848 	fprintf(where,
5849 		cpu_fmt_1,		/* the format string */
5850 		rsr_size,		/* remote recvbuf size */
5851 		lss_size,		/* local sendbuf size */
5852 		send_size,	        /* how large were the sends */
5853 		elapsed_time,		/* how long was the test */
5854 		thruput, 		/* what was the xfer rate */
5855 		local_cpu_utilization,	/* local cpu */
5856 		remote_cpu_utilization,	/* remote cpu */
5857 		local_service_demand,	/* local service demand */
5858 		remote_service_demand,	/* remote service demand */
5859 		((print_headers) ||
5860 		 (result_brand == NULL)) ? "" : result_brand);
5861 	break;
5862       }
5863     }
5864     else {
5865       /* The tester did not wish to measure service demand. */
5866 
5867       switch (verbosity) {
5868       case 0:
5869 	fprintf(where,
5870 		tput_fmt_0,
5871 		thruput,
5872 		((print_headers) ||
5873 		 (result_brand == NULL)) ? "" : result_brand);
5874 	break;
5875       case 1:
5876       case 2:
5877 	if (print_headers) {
5878 	  fprintf(where,tput_title,format_units());
5879 	}
5880 	fprintf(where,
5881 		tput_fmt_1,		/* the format string */
5882 		rsr_size, 		/* remote recvbuf size */
5883 		lss_size, 		/* local sendbuf size */
5884 		send_size,	        /* how large were the sends */
5885 		elapsed_time, 		/* how long did it take */
5886 		thruput,                /* how fast did it go */
5887 		((print_headers) ||
5888 		 (result_brand == NULL)) ? "" : result_brand);
5889 	break;
5890       }
5891     }
5892 
5893     /* it would be a good thing to include information about some of the */
5894     /* other parameters that may have been set for this test, but at the */
5895     /* moment, I do not wish to figure-out all the  formatting, so I will */
5896     /* just put this comment here to help remind me that it is something */
5897     /* that should be done at a later time. */
5898 
5899     if (verbosity > 1) {
5900       /* The user wanted to know it all, so we will give it to him. */
5901       /* This information will include as much as we can find about */
5902       /* TCP statistics, the alignments of the sends and receives */
5903       /* and all that sort of rot... */
5904 
5905       /* this stuff needs to be worked-out in the presence of confidence */
5906       /* intervals and multiple iterations of the test... raj 11/94 */
5907 
5908       fprintf(where,
5909 	      ksink_fmt,
5910 	      "Bytes",
5911 	      "Bytes",
5912 	      "Bytes",
5913 	      local_send_align,
5914 	      remote_recv_align,
5915 	      local_send_offset,
5916 	      remote_recv_offset,
5917 	      bytes_sent,
5918 	      bytes_sent / (double)local_send_calls,
5919 	      local_send_calls,
5920 	      bytes_sent / (double)remote_receive_calls,
5921 	      remote_receive_calls);
5922       fprintf(where,
5923 	      ksink_fmt2,
5924 	      transport_mss);
5925 #ifdef WANT_HISTOGRAM
5926       fprintf(where,"\n\nHistogram of time spent in send() call.\n");
5927       HIST_report(time_hist);
5928 #endif /* WANT_HISTOGRAM */
5929       fflush(where);
5930     }
5931 
5932   }
5933 }
5934 
5935 void
send_tcp_maerts(char remote_host[])5936 send_tcp_maerts(char remote_host[])
5937 {
5938 
5939   char *tput_title = "\
5940 Recv   Send    Send                          \n\
5941 Socket Socket  Message  Elapsed              \n\
5942 Size   Size    Size     Time     Throughput  \n\
5943 bytes  bytes   bytes    secs.    %s/sec  \n\n";
5944 
5945   char *tput_fmt_0 =
5946     "%7.2f %s\n";
5947 
5948   char *tput_fmt_1 =
5949     "%6d %6d %6d    %-6.2f   %7.2f   %s\n";
5950 
5951   char *cpu_title = "\
5952 Recv   Send    Send                          Utilization       Service Demand\n\
5953 Socket Socket  Message  Elapsed              Recv     Send     Recv    Send\n\
5954 Size   Size    Size     Time     Throughput  local    remote   local   remote\n\
5955 bytes  bytes   bytes    secs.    %-8.8s/s  %% %c      %% %c      us/KB   us/KB\n\n";
5956 
5957   char *cpu_fmt_0 =
5958     "%6.3f %c %s\n";
5959 
5960   char *cpu_fmt_1 =
5961     "%6d %6d %6d    %-6.2f     %7.2f   %-6.2f   %-6.2f   %-6.3f  %-6.3f %s\n";
5962 
5963   char *ksink_fmt = "\n\
5964 Alignment      Offset         %-8.8s %-8.8s    Recvs   %-8.8s Sends\n\
5965 Local  Remote  Local  Remote  Xfered   Per                 Per\n\
5966 Recv   Send    Recv   Send             Recv (avg)          Send (avg)\n\
5967 %5d   %5d  %5d   %5d %6"PRId64"  %6.2f    %6d   %6.2f %6d\n";
5968 
5969   char *ksink_fmt2 = "\n\
5970 Maximum\n\
5971 Segment\n\
5972 Size (bytes)\n\
5973 %6d\n";
5974 
5975   send_omni_inner(remote_host, legacy, "MIGRATED TCP MAERTS TEST");
5976 
5977 
5978   /* We are now ready to print all the information, but only if we are
5979      truly acting as a leacy test.  If the user has specified
5980      zero-level verbosity, we will just print the local service
5981      demand, or the remote service demand. If the user has requested
5982      verbosity level 1, he will get the basic "streamperf" numbers. If
5983      the user has specified a verbosity of greater than 1, we will
5984      display a veritable plethora of background information from
5985      outside of this block as it it not cpu_measurement
5986      specific...  */
5987 
5988   if (legacy) {
5989 
5990     if (confidence < 0) {
5991       /* we did not hit confidence, but were we asked to look for it? */
5992       if (iteration_max > 1) {
5993 	display_confidence();
5994       }
5995     }
5996 
5997     if (local_cpu_usage || remote_cpu_usage) {
5998 
5999       switch (verbosity) {
6000       case 0:
6001 	if (local_cpu_usage) {
6002 	  fprintf(where,
6003 		  cpu_fmt_0,
6004 		  local_service_demand,
6005 		  local_cpu_method,
6006 		  ((print_headers) ||
6007 		   (result_brand == NULL)) ? "" : result_brand);
6008 	}
6009 	else {
6010 	  fprintf(where,
6011 		  cpu_fmt_0,
6012 		  remote_service_demand,
6013 		  remote_cpu_method,
6014 		  ((print_headers) ||
6015 		   (result_brand == NULL)) ? "" : result_brand);
6016 	}
6017 	break;
6018       case 1:
6019       case 2:
6020 	if (print_headers) {
6021 	  fprintf(where,
6022 		  cpu_title,
6023 		  format_units(),
6024 		  local_cpu_method,
6025 		  remote_cpu_method);
6026 	}
6027 
6028 	fprintf(where,
6029 		cpu_fmt_1,		/* the format string */
6030 		rsr_size,		/* remote recvbuf size */
6031 		lss_size,		/* local sendbuf size */
6032 		remote_send_size,	/* how large were the recvs */
6033 		elapsed_time,		/* how long was the test */
6034 		thruput, 		/* what was the xfer rate */
6035 		local_cpu_utilization,	/* local cpu */
6036 		remote_cpu_utilization,	/* remote cpu */
6037 		local_service_demand,	/* local service demand */
6038 		remote_service_demand,	/* remote service demand */
6039 		((print_headers) ||
6040 		 (result_brand == NULL)) ? "" : result_brand);
6041 	break;
6042       }
6043     }
6044     else {
6045       /* The tester did not wish to measure service demand. */
6046 
6047       switch (verbosity) {
6048       case 0:
6049 	fprintf(where,
6050 		tput_fmt_0,
6051 		thruput,
6052 		((print_headers) ||
6053 		 (result_brand == NULL)) ? "" : result_brand);
6054 	break;
6055       case 1:
6056       case 2:
6057 	if (print_headers) {
6058 	  fprintf(where,tput_title,format_units());
6059 	}
6060 	fprintf(where,
6061 		tput_fmt_1,		/* the format string */
6062 		lsr_size, 		/* local recvbuf size */
6063 		rss_size, 		/* remot sendbuf size */
6064 		remote_send_size,	/* how large were the recvs */
6065 		elapsed_time, 		/* how long did it take */
6066 		thruput,                /* how fast did it go */
6067 		((print_headers) ||
6068 		 (result_brand == NULL)) ? "" : result_brand);
6069 	break;
6070       }
6071     }
6072 
6073     /* it would be a good thing to include information about some of the */
6074     /* other parameters that may have been set for this test, but at the */
6075     /* moment, I do not wish to figure-out all the  formatting, so I will */
6076     /* just put this comment here to help remind me that it is something */
6077     /* that should be done at a later time. */
6078 
6079     if (verbosity > 1) {
6080       /* The user wanted to know it all, so we will give it to him. */
6081       /* This information will include as much as we can find about */
6082       /* TCP statistics, the alignments of the sends and receives */
6083       /* and all that sort of rot... */
6084 
6085       /* this stuff needs to be worked-out in the presence of confidence */
6086       /* intervals and multiple iterations of the test... raj 11/94 */
6087 
6088       fprintf(where,
6089 	      ksink_fmt,
6090 	      "Bytes",
6091 	      "Bytes",
6092 	      "Bytes",
6093 	      local_recv_align,
6094 	      remote_recv_align,
6095 	      local_recv_offset,
6096 	      remote_recv_offset,
6097 	      bytes_received,
6098 	      bytes_received / (double)local_receive_calls,
6099 	      local_receive_calls,
6100 	      remote_bytes_sent / (double)remote_send_calls,
6101 	      remote_send_calls);
6102       fprintf(where,
6103 	      ksink_fmt2,
6104 	      transport_mss);
6105 
6106 #ifdef WANT_HISTOGRAM
6107       fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
6108       HIST_report(time_hist);
6109 #endif /* WANT_HISTOGRAM */
6110       fflush(where);
6111     }
6112   }
6113 }
6114 
6115 
6116 void
send_tcp_rr(char remote_host[])6117 send_tcp_rr(char remote_host[]) {
6118 
6119   char *tput_title = "\
6120 Local /Remote\n\
6121 Socket Size   Request  Resp.   Elapsed  Trans.\n\
6122 Send   Recv   Size     Size    Time     Rate         \n\
6123 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
6124 
6125   char *tput_title_band = "\
6126 Local /Remote\n\
6127 Socket Size   Request  Resp.   Elapsed  \n\
6128 Send   Recv   Size     Size    Time     Throughput \n\
6129 bytes  Bytes  bytes    bytes   secs.    %s/sec   \n\n";
6130 
6131   char *tput_fmt_0 =
6132     "%7.2f %s\n";
6133 
6134   char *tput_fmt_1_line_1 = "\
6135 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   %s\n";
6136   char *tput_fmt_1_line_2 = "\
6137 %-6d %-6d\n";
6138 
6139   char *cpu_title = "\
6140 Local /Remote\n\
6141 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
6142 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
6143 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
6144 
6145   char *cpu_title_tput = "\
6146 Local /Remote\n\
6147 Socket Size   Request Resp.  Elapsed Tput     CPU    CPU    S.dem   S.dem\n\
6148 Send   Recv   Size    Size   Time    %-8.8s local  remote local   remote\n\
6149 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/KB   us/KB\n\n";
6150 
6151   char *cpu_title_latency = "\
6152 Local /Remote\n\
6153 Socket Size   Request Resp.  Elapsed Latency  CPU    CPU    S.dem   S.dem\n\
6154 Send   Recv   Size    Size   Time    usecs    local  remote local   remote\n\
6155 bytes  bytes  bytes   bytes  secs.   per tran %% %c    %% %c    us/Tr   us/Tr\n\n";
6156 
6157   char *cpu_fmt_0 =
6158     "%6.3f %c %s\n";
6159 
6160   char *cpu_fmt_1_line_1 = "\
6161 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f  %-6.2f %-6.2f %-6.3f  %-6.3f %s\n";
6162 
6163   char *cpu_fmt_1_line_2 = "\
6164 %-6d %-6d\n";
6165 
6166   char *ksink_fmt = "\
6167 Alignment      Offset         RoundTrip  Trans    Throughput\n\
6168 Local  Remote  Local  Remote  Latency    Rate     %-8.8s/s\n\
6169 Send   Recv    Send   Recv    usec/Tran  per sec  Outbound   Inbound\n\
6170 %5d  %5d   %5d  %5d   %-6.3f   %-6.3f %-6.3f    %-6.3f\n";
6171 
6172   send_omni_inner(remote_host, legacy, "MIGRATED TCP REQUEST/RESPONSE TEST");
6173 
6174   if (legacy) {
6175     /* We are now ready to print all the information. If the user has
6176        specified zero-level verbosity, we will just print the local
6177        service demand, or the remote service demand. If the user has
6178        requested verbosity level 1, he will get the basic "streamperf"
6179        numbers. If the user has specified a verbosity of greater than 1,
6180        we will display a veritable plethora of background information
6181        from outside of this block as it it not cpu_measurement
6182        specific...  */
6183 
6184     if (confidence < 0) {
6185       /* we did not hit confidence, but were we asked to look for it? */
6186       if (iteration_max > 1) {
6187 	display_confidence();
6188       }
6189     }
6190 
6191     if (local_cpu_usage || remote_cpu_usage) {
6192 
6193       switch (verbosity) {
6194       case 0:
6195 	if (local_cpu_usage) {
6196 	  fprintf(where,
6197 		  cpu_fmt_0,
6198 		  local_service_demand,
6199 		  local_cpu_method,
6200 		  ((print_headers) ||
6201 		   (result_brand == NULL)) ? "" : result_brand);
6202 	}
6203 	else {
6204 	  fprintf(where,
6205 		  cpu_fmt_0,
6206 		  remote_service_demand,
6207 		  remote_cpu_method,
6208 		  ((print_headers) ||
6209 		   (result_brand == NULL)) ? "" : result_brand);
6210 	}
6211 	break;
6212       case 1:
6213       case 2:
6214 	if (print_headers) {
6215 	  if ('x' == libfmt) {
6216 	    fprintf(where,
6217 		    cpu_title,
6218 		    local_cpu_method,
6219 		    remote_cpu_method);
6220 	  }
6221 	  else {
6222 	    fprintf(where,
6223 		    cpu_title_tput,
6224 		    format_units(),
6225 		    local_cpu_method,
6226 		    remote_cpu_method);
6227 	  }
6228 	}
6229 
6230 	fprintf(where,
6231 		cpu_fmt_1_line_1,		/* the format string */
6232 		lss_size,		/* local sendbuf size */
6233 		lsr_size,
6234 		req_size,		/* how large were the requests */
6235 		rsp_size,		/* guess */
6236 		elapsed_time,		/* how long was the test */
6237 		thruput,
6238 		local_cpu_utilization,	/* local cpu */
6239 		remote_cpu_utilization,	/* remote cpu */
6240 		local_service_demand,	/* local service demand */
6241 		remote_service_demand,	/* remote service demand */
6242 		((print_headers) ||
6243 		 (result_brand == NULL)) ? "" : result_brand);
6244 	fprintf(where,
6245 		cpu_fmt_1_line_2,
6246 		rss_size,
6247 		rsr_size);
6248 	break;
6249       }
6250     }
6251     else {
6252       /* The tester did not wish to measure service demand. */
6253 
6254       switch (verbosity) {
6255       case 0:
6256 	fprintf(where,
6257 		tput_fmt_0,
6258 		thruput,
6259 		((print_headers) ||
6260 		 (result_brand == NULL)) ? "" : result_brand);
6261 	break;
6262       case 1:
6263       case 2:
6264 	if (print_headers) {
6265 	  fprintf(where,
6266 		  ('x' == libfmt) ? tput_title : tput_title_band,
6267 		  format_units());
6268 	}
6269 
6270 	fprintf(where,
6271 		tput_fmt_1_line_1,	/* the format string */
6272 		lss_size,
6273 		lsr_size,
6274 		req_size,		/* how large were the requests */
6275 		rsp_size,		/* how large were the responses */
6276 		elapsed_time, 		/* how long did it take */
6277 		/* are we trans or do we need to convert to bytes then
6278 		   bits? at this point, thruput is in our "confident"
6279 		   transactions per second. we can convert to a
6280 		   bidirectional bitrate by multiplying that by the sum
6281 		   of the req_size and rsp_size.  we pass that to
6282 		   calc_thruput_interval_omni with an elapsed time of
6283 		   1.0 s to get it converted to [kmg]bits/s or
6284 		   [KMG]Bytes/s */
6285 		thruput,
6286 		((print_headers) ||
6287 		 (result_brand == NULL)) ? "" : result_brand);
6288 	fprintf(where,
6289 		tput_fmt_1_line_2,
6290 		rss_size, 		/* remote recvbuf size */
6291 		rsr_size);
6292 
6293 	break;
6294       }
6295     }
6296 
6297     /* it would be a good thing to include information about some of the */
6298     /* other parameters that may have been set for this test, but at the */
6299     /* moment, I do not wish to figure-out all the  formatting, so I will */
6300     /* just put this comment here to help remind me that it is something */
6301     /* that should be done at a later time. */
6302 
6303     /* how to handle the verbose information in the presence of */
6304     /* confidence intervals is yet to be determined... raj 11/94 */
6305     if (verbosity > 1) {
6306       /* The user wanted to know it all, so we will give it to him. */
6307       /* This information will include as much as we can find about */
6308       /* TCP statistics, the alignments of the sends and receives */
6309       /* and all that sort of rot... */
6310 
6311       /* normally, you might think that if we were messing about with
6312 	 the value of libfmt we would need to put it back again, but
6313 	 since this is basically the last thing we are going to do with
6314 	 it, it does not matter.  so there :) raj 2007-06-08 */
6315       /* if the user was asking for transactions, then we report
6316 	 megabits per second for the unidirectional throughput,
6317 	 otherwise we use the desired units. */
6318       if ('x' == libfmt) {
6319 	libfmt = 'm';
6320       }
6321 
6322       fprintf(where,
6323 	      ksink_fmt,
6324 	      format_units(),
6325 	      local_send_align,
6326 	      remote_recv_offset,
6327 	      local_send_offset,
6328 	      remote_recv_offset,
6329 	      /* if the user has enable burst mode, we have to remember
6330 		 to account for that in the number of transactions
6331 		 outstanding at any one time. otherwise we will
6332 		 underreport the latency of individual
6333 		 transactions. learned from saf by raj 2007-06-08  */
6334 	      (((double)1.0/transaction_rate)*(double)1000000.0) *
6335 	      (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)),
6336 	      transaction_rate,
6337 	      calc_thruput_interval_omni(transaction_rate * (double)req_size,
6338 					 1.0),
6339 	      calc_thruput_interval_omni(transaction_rate * (double)rsp_size,
6340 					 1.0));
6341 
6342 #ifdef WANT_HISTOGRAM
6343       fprintf(where,"\nHistogram of request/response times\n");
6344       HIST_report(time_hist);
6345 #endif /* WANT_HISTOGRAM */
6346       fflush(where);
6347     }
6348   }
6349 }
6350 
6351 
6352 void
send_tcp_conn_rr(char remote_host[])6353 send_tcp_conn_rr(char remote_host[])
6354 {
6355 
6356   char *tput_title = "\
6357 Local /Remote\n\
6358 Socket Size   Request  Resp.   Elapsed  Trans.\n\
6359 Send   Recv   Size     Size    Time     Rate         \n\
6360 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
6361 
6362   char *tput_fmt_0 =
6363     "%7.2f\n";
6364 
6365   char *tput_fmt_1_line_1 = "\
6366 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   \n";
6367   char *tput_fmt_1_line_2 = "\
6368 %-6d %-6d\n";
6369 
6370   char *cpu_title = "\
6371 Local /Remote\n\
6372 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
6373 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
6374 bytes  bytes  bytes   bytes  secs.   per sec  %%      %%      us/Tr   us/Tr\n\n";
6375 
6376   char *cpu_fmt_0 =
6377     "%6.3f\n";
6378 
6379   char *cpu_fmt_1_line_1 = "\
6380 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f\n";
6381 
6382   char *cpu_fmt_1_line_2 = "\
6383 %-6d %-6d\n";
6384 
6385   char *ksink_fmt = "\n\
6386 Alignment      Offset\n\
6387 Local  Remote  Local  Remote\n\
6388 Send   Recv    Send   Recv\n\
6389 %5d  %5d   %5d  %5d\n";
6390 
6391   send_omni_inner(remote_host,
6392 		  legacy,
6393 		  "MIGRATED TCP Connect/Request/Response TEST");
6394 
6395   /* We are now ready to print all the information. If the user */
6396   /* has specified zero-level verbosity, we will just print the */
6397   /* local service demand, or the remote service demand. If the */
6398   /* user has requested verbosity level 1, he will get the basic */
6399   /* "streamperf" numbers. If the user has specified a verbosity */
6400   /* of greater than 1, we will display a veritable plethora of */
6401   /* background information from outside of this block as it it */
6402   /* not cpu_measurement specific...  */
6403 
6404   if (legacy) {
6405     if (confidence < 0) {
6406       /* we did not hit confidence, but were we asked to look for it? */
6407       if (iteration_max > 1) {
6408 	display_confidence();
6409       }
6410     }
6411 
6412     if (local_cpu_usage || remote_cpu_usage) {
6413 
6414       switch (verbosity) {
6415       case 0:
6416 	if (local_cpu_usage) {
6417 	  fprintf(where,
6418 		  cpu_fmt_0,
6419 		  local_service_demand,
6420 		  local_cpu_method);
6421 	}
6422 	else {
6423 	  fprintf(where,
6424 		  cpu_fmt_0,
6425 		  remote_service_demand,
6426 		  remote_cpu_method);
6427 	}
6428 	break;
6429       case 1:
6430       case 2:
6431 	if (print_headers) {
6432 	  fprintf(where,
6433 		  cpu_title,
6434 		  local_cpu_method,
6435 		  remote_cpu_method);
6436 	}
6437 
6438 	fprintf(where,
6439 		cpu_fmt_1_line_1,	/* the format string */
6440 		lss_size,		/* local sendbuf size */
6441 		lsr_size,
6442 		req_size,		/* how large were the requests */
6443 		rsp_size,		/* guess */
6444 		elapsed_time,		/* how long was the test */
6445 		thruput,
6446 		local_cpu_utilization,	/* local cpu */
6447 		remote_cpu_utilization,	/* remote cpu */
6448 		local_service_demand,	/* local service demand */
6449 		remote_service_demand);	/* remote service demand */
6450 	fprintf(where,
6451 		cpu_fmt_1_line_2,
6452 		rss_size,
6453 		rsr_size);
6454 	break;
6455       }
6456     }
6457     else {
6458       /* The tester did not wish to measure service demand. */
6459 
6460       switch (verbosity) {
6461       case 0:
6462 	fprintf(where,
6463 		tput_fmt_0,
6464 		thruput);
6465 	break;
6466       case 1:
6467       case 2:
6468 	if (print_headers) {
6469 	  fprintf(where,tput_title,format_units());
6470 	}
6471 
6472 	fprintf(where,
6473 		tput_fmt_1_line_1,	/* the format string */
6474 		lss_size,
6475 		lsr_size,
6476 		req_size,		/* how large were the requests */
6477 		rsp_size,		/* how large were the responses */
6478 		elapsed_time, 		/* how long did it take */
6479 		thruput);
6480 	fprintf(where,
6481 		tput_fmt_1_line_2,
6482 		rss_size, 		/* remote recvbuf size */
6483 		rsr_size);
6484 
6485 	break;
6486       }
6487     }
6488 
6489     /* it would be a good thing to include information about some of the */
6490     /* other parameters that may have been set for this test, but at the */
6491     /* moment, I do not wish to figure-out all the  formatting, so I will */
6492     /* just put this comment here to help remind me that it is something */
6493     /* that should be done at a later time. */
6494 
6495     /* how to handle the verbose information in the presence of */
6496     /* confidence intervals is yet to be determined... raj 11/94 */
6497     if (verbosity > 1) {
6498       /* The user wanted to know it all, so we will give it to him. */
6499       /* This information will include as much as we can find about */
6500       /* TCP statistics, the alignments of the sends and receives */
6501       /* and all that sort of rot... */
6502 
6503       fprintf(where,
6504 	      ksink_fmt,
6505 	      local_send_align,
6506 	      remote_recv_align,
6507 	      local_send_offset,
6508 	      remote_recv_offset);
6509 
6510 #ifdef WANT_HISTOGRAM
6511       fprintf(where,"\nHistogram of request/response times\n");
6512       HIST_report(time_hist);
6513 #endif /* WANT_HISTOGRAM */
6514       fflush(where);
6515     }
6516   }
6517 }
6518 
6519 void
send_udp_stream(char remote_host[])6520 send_udp_stream(char remote_host[])
6521 {
6522   /**********************************************************************/
6523   /*									*/
6524   /*               	UDP Unidirectional Send Test                    */
6525   /*									*/
6526   /**********************************************************************/
6527 
6528   char *tput_title = "\
6529 Socket  Message  Elapsed      Messages                \n\
6530 Size    Size     Time         Okay Errors   Throughput\n\
6531 bytes   bytes    secs            #      #   %s/sec\n\n";
6532 
6533   char *tput_fmt_0 =
6534     "%7.2f\n";
6535 
6536   char *tput_fmt_1 = "\
6537 %6d  %6d   %-7.2f   %7"PRIu64" %6d    %7.2f\n\
6538 %6d           %-7.2f   %7"PRIu64"           %7.2f\n\n";
6539 
6540 
6541   char *cpu_title = "\
6542 Socket  Message  Elapsed      Messages                   CPU      Service\n\
6543 Size    Size     Time         Okay Errors   Throughput   Util     Demand\n\
6544 bytes   bytes    secs            #      #   %s/sec %% %c%c     us/KB\n\n";
6545 
6546   char *cpu_fmt_0 =
6547     "%6.2f %c\n";
6548 
6549   char *cpu_fmt_1 = "\
6550 %6d  %6d   %-7.2f   %7"PRIu64" %6d    %7.1f     %-6.2f   %-6.3f\n\
6551 %6d           %-7.2f   %7"PRIu64"           %7.1f     %-6.2f   %-6.3f\n\n";
6552 
6553 
6554   send_omni_inner(remote_host, legacy, "MIGRATED UDP STREAM TEST");
6555 
6556   if (legacy) {
6557     /* We are now ready to print all the information. If the user has
6558        specified zero-level verbosity, we will just print the local
6559        service demand, or the remote service demand. If the user has
6560        requested verbosity level 1, he will get the basic "streamperf"
6561        numbers. If the user has specified a verbosity of greater than
6562        1, we will display a veritable plethora of background
6563        information from outside of this block as it it not
6564        cpu_measurement specific...  */
6565 
6566 
6567     if (confidence < 0) {
6568       /* we did not hit confidence, but were we asked to look for it? */
6569       if (iteration_max > 1) {
6570 	display_confidence();
6571       }
6572     }
6573 
6574     if (local_cpu_usage || remote_cpu_usage) {
6575 
6576       switch (verbosity) {
6577       case 0:
6578 	if (local_cpu_usage) {
6579 	  fprintf(where,
6580 		  cpu_fmt_0,
6581 		  local_service_demand,
6582 		  local_cpu_method);
6583 	}
6584 	else {
6585 	  fprintf(where,
6586 		  cpu_fmt_0,
6587 		  remote_service_demand,
6588 		  local_cpu_method);
6589 	}
6590 	break;
6591       case 1:
6592       case 2:
6593 	if (print_headers) {
6594 	  fprintf(where,
6595 		  cpu_title,
6596 		  format_units(),
6597 		  local_cpu_method,
6598 		  remote_cpu_method);
6599 	}
6600 
6601 	fprintf(where,
6602 		cpu_fmt_1,		/* the format string */
6603 		lss_size,		/* local sendbuf size */
6604 		send_size,		/* how large were the sends */
6605 		elapsed_time,		/* how long was the test */
6606 		local_send_calls,
6607 		failed_sends,
6608 		local_send_thruput, 	/* what was the xfer rate */
6609 		local_cpu_utilization,	/* local cpu */
6610 		local_service_demand,	/* local service demand */
6611 		rsr_size,
6612 		elapsed_time,
6613 		remote_receive_calls,
6614 		remote_recv_thruput,
6615 		remote_cpu_utilization,	/* remote cpu */
6616 		remote_service_demand);	/* remote service demand */
6617 	break;
6618       }
6619     }
6620     else {
6621       /* The tester did not wish to measure service demand. */
6622       switch (verbosity) {
6623       case 0:
6624 	fprintf(where,
6625 		tput_fmt_0,
6626 		local_send_thruput);
6627 	break;
6628       case 1:
6629       case 2:
6630 	if (print_headers) {
6631 	  fprintf(where,tput_title,format_units());
6632 	}
6633 	fprintf(where,
6634 		tput_fmt_1,		/* the format string */
6635 		lss_size, 		/* local sendbuf size */
6636 		send_size,		/* how large were the sends */
6637 		elapsed_time, 		/* how long did it take */
6638 		local_send_calls,
6639 		failed_sends,
6640 		local_send_thruput,
6641 		rsr_size, 		/* remote recvbuf size */
6642 		elapsed_time,
6643 		remote_receive_calls,
6644 		remote_recv_thruput);
6645 	break;
6646       }
6647     }
6648 
6649 #ifdef WANT_HISTOGRAM
6650     if (verbosity > 1) {
6651       fprintf(where,"\nHistogram of time spent in send() call\n");
6652       HIST_report(time_hist);
6653     }
6654 #endif /* WANT_HISTOGRAM */
6655     fflush(where);
6656   }
6657 }
6658 
6659 void
send_udp_rr(char remote_host[])6660 send_udp_rr(char remote_host[])
6661 {
6662 
6663   char *tput_title = "\
6664 Local /Remote\n\
6665 Socket Size   Request  Resp.   Elapsed  Trans.\n\
6666 Send   Recv   Size     Size    Time     Rate         \n\
6667 bytes  Bytes  bytes    bytes   secs.    per sec   \n\n";
6668 
6669   char *tput_title_band = "\
6670 Local /Remote\n\
6671 Socket Size   Request  Resp.   Elapsed  \n\
6672 Send   Recv   Size     Size    Time     Throughput \n\
6673 bytes  Bytes  bytes    bytes   secs.    %s/sec   \n\n";
6674 
6675   char *tput_fmt_0 =
6676     "%7.2f %s\n";
6677 
6678   char *tput_fmt_1_line_1 = "\
6679 %-6d %-6d %-6d   %-6d  %-6.2f   %7.2f   %s\n";
6680 
6681   char *tput_fmt_1_line_2 = "\
6682 %-6d %-6d\n";
6683 
6684   char *cpu_title = "\
6685 Local /Remote\n\
6686 Socket Size   Request Resp.  Elapsed Trans.   CPU    CPU    S.dem   S.dem\n\
6687 Send   Recv   Size    Size   Time    Rate     local  remote local   remote\n\
6688 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/Tr   us/Tr\n\n";
6689 
6690   char *cpu_title_tput = "\
6691 Local /Remote\n\
6692 Socket Size   Request Resp.  Elapsed Tput     CPU    CPU    S.dem   S.dem\n\
6693 Send   Recv   Size    Size   Time    %-8.8s local  remote local   remote\n\
6694 bytes  bytes  bytes   bytes  secs.   per sec  %% %c    %% %c    us/KB   us/KB\n\n";
6695 
6696   char *cpu_fmt_0 =
6697     "%6.3f %c %s\n";
6698 
6699   char *cpu_fmt_1_line_1 = "\
6700 %-6d %-6d %-6d  %-6d %-6.2f  %-6.2f   %-6.2f %-6.2f %-6.3f  %-6.3f %s\n";
6701 
6702   char *cpu_fmt_1_line_2 = "\
6703 %-6d %-6d\n";
6704 
6705   send_omni_inner(remote_host, legacy, "MIGRATED UDP REQUEST/RESPONSE TEST");
6706 
6707   if (legacy) {
6708     /* We are now ready to print all the information. If the user has
6709        specified zero-level verbosity, we will just print the local
6710        service demand, or the remote service demand. If the user has
6711        requested verbosity level 1, he will get the basic "streamperf"
6712        numbers. If the user has specified a verbosity of greater than
6713        1, we will display a veritable plethora of background
6714        information from outside of this block as it it not
6715        cpu_measurement specific...  */
6716 
6717     if (confidence < 0) {
6718       /* we did not hit confidence, but were we asked to look for it? */
6719       if (iteration_max > 1) {
6720 	display_confidence();
6721       }
6722     }
6723 
6724     if (local_cpu_usage || remote_cpu_usage) {
6725 
6726       switch (verbosity) {
6727       case 0:
6728 	if (local_cpu_usage) {
6729 	  fprintf(where,
6730 		  cpu_fmt_0,
6731 		  local_service_demand,
6732 		  local_cpu_method,
6733 		  ((print_headers) ||
6734 		   (result_brand == NULL)) ? "" : result_brand);
6735 
6736 	}
6737 	else {
6738 	  fprintf(where,
6739 		  cpu_fmt_0,
6740 		  remote_service_demand,
6741 		  remote_cpu_method,
6742 		  ((print_headers) ||
6743 		   (result_brand == NULL)) ? "" : result_brand);
6744 
6745 	}
6746 	break;
6747       case 1:
6748       case 2:
6749 	if (print_headers) {
6750 	  if ('x' == libfmt) {
6751 	    fprintf(where,
6752 		    cpu_title,
6753 		    local_cpu_method,
6754 		    remote_cpu_method);
6755 	  }
6756 	  else {
6757 	    fprintf(where,
6758 		    cpu_title_tput,
6759 		    format_units(),
6760 		    local_cpu_method,
6761 		    remote_cpu_method);
6762 	  }
6763 	}
6764 
6765 	fprintf(where,
6766 		cpu_fmt_1_line_1,		/* the format string */
6767 		lss_size,		/* local sendbuf size */
6768 		lsr_size,
6769 		req_size,		/* how large were the requests */
6770 		rsp_size,		/* guess */
6771 		elapsed_time,		/* how long was the test */
6772 		thruput,
6773 		local_cpu_utilization,	/* local cpu */
6774 		remote_cpu_utilization,	/* remote cpu */
6775 		local_service_demand,	/* local service demand */
6776 		remote_service_demand,	/* remote service demand */
6777 		((print_headers) ||
6778 		 (result_brand == NULL)) ? "" : result_brand);
6779 	fprintf(where,
6780 		cpu_fmt_1_line_2,
6781 		rss_size,
6782 		rsr_size);
6783 	break;
6784       }
6785     }
6786     else {
6787       /* The tester did not wish to measure service demand. */
6788       switch (verbosity) {
6789       case 0:
6790 	fprintf(where,
6791 		tput_fmt_0,
6792 		thruput,
6793 		((print_headers) ||
6794 		 (result_brand == NULL)) ? "" : result_brand);
6795 	break;
6796       case 1:
6797       case 2:
6798 	if (print_headers) {
6799 	  fprintf(where,
6800 		  ('x' == libfmt) ? tput_title : tput_title_band,
6801 		  format_units());
6802 	}
6803 
6804 	fprintf(where,
6805 		tput_fmt_1_line_1,	/* the format string */
6806 		lss_size,
6807 		lsr_size,
6808 		req_size,		/* how large were the requests */
6809 		rsp_size,		/* how large were the responses */
6810 		elapsed_time, 		/* how long did it take */
6811 		thruput,
6812 		((print_headers) ||
6813 		 (result_brand == NULL)) ? "" : result_brand);
6814 	fprintf(where,
6815 		tput_fmt_1_line_2,
6816 		rss_size, 		/* remote recvbuf size */
6817 		rsr_size);
6818 
6819 	break;
6820       }
6821     }
6822 
6823     /* it would be a good thing to include information about some of the */
6824     /* other parameters that may have been set for this test, but at the */
6825     /* moment, I do not wish to figure-out all the  formatting, so I will */
6826     /* just put this comment here to help remind me that it is something */
6827     /* that should be done at a later time. */
6828 
6829     /* how to handle the verbose information in the presence of */
6830     /* confidence intervals is yet to be determined... raj 11/94 */
6831 
6832     if (verbosity > 1) {
6833       /* The user wanted to know it all, so we will give it to him. */
6834       /* This information will include as much as we can find about */
6835       /* UDP statistics, the alignments of the sends and receives */
6836       /* and all that sort of rot... */
6837 
6838 #ifdef WANT_HISTOGRAM
6839       fprintf(where,"\nHistogram of request/reponse times.\n");
6840       HIST_report(time_hist);
6841 #endif /* WANT_HISTOGRAM */
6842     }
6843     fflush(where);
6844   }
6845 }
6846 
6847 
6848 #endif /* WANT_MIGRATION */
6849 
6850 
6851 /* using legacy test names will cause certain default settings to be
6852    made before we scan the test-specific arguments.  raj 2010-07-20 */
6853 static void
set_omni_defaults_by_legacy_testname()6854 set_omni_defaults_by_legacy_testname() {
6855 
6856   /* the uber defaults are for a unidirectional test using TCP */
6857   protocol = IPPROTO_TCP;
6858   socket_type = SOCK_STREAM;
6859   connection_test = 0;
6860   req_size = rsp_size = -1;
6861   was_legacy = 1;
6862   legacy = 1;
6863   implicit_direction = 0;  /* do we allow certain options to
6864 			      implicitly affect the test direction? */
6865   if (strcasecmp(test_name,"TCP_STREAM") == 0) {
6866     direction = NETPERF_XMIT;
6867   }
6868   else if (strcasecmp(test_name,"TCP_MAERTS") == 0) {
6869     direction = NETPERF_RECV;
6870   }
6871   else if (strcasecmp(test_name,"TCP_RR") == 0) {
6872     req_size = rsp_size = 1;
6873     direction = 0;
6874     direction |= NETPERF_XMIT;
6875     direction |= NETPERF_RECV;
6876   }
6877   else if (strcasecmp(test_name,"UDP_STREAM") == 0) {
6878      protocol = IPPROTO_UDP;
6879     socket_type = SOCK_DGRAM;
6880   }
6881   else if (strcasecmp(test_name,"UDP_RR") == 0) {
6882      protocol = IPPROTO_UDP;
6883     socket_type = SOCK_DGRAM;
6884     direction = 0;
6885     direction |= NETPERF_XMIT;
6886     direction |= NETPERF_RECV;
6887     req_size = rsp_size = 1;
6888   }
6889   else if (strcasecmp(test_name,"TCP_CC") == 0) {
6890     direction = 0;
6891     connection_test = 1;
6892   }
6893   else if (strcasecmp(test_name,"TCP_CRR") == 0) {
6894     direction = 0;
6895     direction |= NETPERF_XMIT;
6896     direction |= NETPERF_RECV;
6897     req_size = rsp_size = 1;
6898     connection_test = 1;
6899   }
6900   else if (strcasecmp(test_name,"omni") == 0) {
6901     /* there is not much to do here but clear the legacy flag */
6902     was_legacy = 0;
6903     legacy = 0;
6904     implicit_direction = 1;
6905   }
6906   socket_type_str = hst_to_str(socket_type);
6907 }
6908 
6909 char omni_usage[] = "\n\
6910 Usage: netperf [global options] -- [test options] \n\
6911 \n\
6912 OMNI and Migrated BSD Sockets Test Options:\n\
6913     -b number         Send number requests at start of _RR tests\n\
6914     -c                Explicitly declare this a connection test such as\n\
6915                       TCP_CRR or TCP_CC\n\
6916     -C                Set TCP_CORK when available\n\
6917     -d direction      Explicitly set test direction based on bitwise OR\n\
6918                       of 0x2 for transmit and 0x4 for receive. Default:\n\
6919                       based on test type\n\
6920     -D [L][,R]        Set TCP_NODELAY locally and/or remotely (TCP_*)\n\
6921     -h                Display this text\n\
6922     -H name[/mask],fam  Use name (or IP) and family as target of data connection\n\
6923                       A mask value will cause randomization of the IP used\n\
6924     -k [file]         Generate keyval output optionally based on file\n\
6925                       Use filename of '?' to get the list of choices\n\
6926     -K loc[,rem]      Set the local and/or remote congestion control\n\
6927                       algorithm to use on those platforms where it can\n\
6928                       be set.\n\
6929     -L name[/mask],fam  Use name (or IP) and family as source of data connection\n\
6930                       A mask value will cause randomization of the IP used\n\
6931     -m local,remote   Set the send size for _STREAM/_MAERTS tests\n\
6932     -M local,remote   Set the recv size for _STREAM/_MAERTS tests\n\
6933     -n                Use the connected socket for UDP locally\n\
6934     -N                Use the connected socket for UDP remotely\n\
6935     -o [file]         Generate CSV output optionally based on file\n\
6936                       Use filename of '?' to get the list of choices\n\
6937     -O [file]         Generate classic-style output based on file\n\
6938                       Use filename of '?' to get the list of choices\n\
6939     -p min[,max]      Set the min/max port numbers for TCP_CRR, TCP_TRR\n\
6940     -P local[,remote] Set the local/remote port for the data socket\n\
6941     -r req,[rsp]      Set request/response sizes (TCP_RR, UDP_RR)\n\
6942     -R 0/1            Allow routing of traffic on data connection.\n\
6943                       Default: 0 (off) for UDP_STREAM, 1 (on) otherwise\n\
6944     -s send[,recv]    Set local socket send/recv buffer sizes\n\
6945     -S send[,recv]    Set remote socket send/recv buffer sizes\n\
6946     -t type           Explicitly set socket type. Default is implicit\n\
6947                       based on other settings\n\
6948     -T protocol       Explicitly set data connection protocol. Default is\n\
6949                       implicit based on other settings\n\
6950     -u uuid           Use the supplied string as the UUID for this test.\n\
6951     -4                Use AF_INET (eg IPv4) on both ends of the data conn\n\
6952     -6                Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
6953 \n\
6954 For those options taking two parms, at least one must be specified;\n\
6955 specifying one value without a comma will set both parms to that\n\
6956 value, specifying a value with a leading comma will set just the second\n\
6957 parm, a value with a trailing comma will set just the first. To set\n\
6958 each parm to unique values, specify both and separate them with a\n\
6959 comma.\n";
6960 
6961 void
print_omni_usage()6962 print_omni_usage()
6963 {
6964 
6965   fwrite(omni_usage, sizeof(char), strlen(omni_usage), stdout);
6966   exit(1);
6967 
6968 }
6969 
6970 
6971 void
scan_omni_args(int argc,char * argv[])6972 scan_omni_args(int argc, char *argv[])
6973 
6974 {
6975 
6976 #define OMNI_ARGS "aBb:cCd:De:FgG:hH:i:Ij:kK:l:L:m:M:nNoOp:P:r:R:s:S:t:T:u:UVw:W:46"
6977 
6978   extern char	*optarg;	  /* pointer to option string	*/
6979 
6980   int		c;
6981   int           have_uuid = 0;
6982   int           have_R_option = 0;
6983 
6984   char
6985     arg1[BUFSIZ],  /* argument holders		*/
6986     arg2[BUFSIZ],
6987     arg3[BUFSIZ];
6988 
6989   if (debug) {
6990     int i;
6991     printf("%s called with the following argument vector\n",
6992 	   __FUNCTION__);
6993     for (i = 0; i< argc; i++) {
6994       printf("%s ",argv[i]);
6995     }
6996     printf("\n");
6997   }
6998 
6999   /* double-check struct sizes */
7000   {
7001     const union netperf_request_struct * u = (const union netperf_request_struct *)0;
7002     if (debug) {
7003       fprintf(where, "sizeof(omni_request_struct)=%d/%d\n",
7004               (int)sizeof(struct omni_request_struct),
7005               (int)sizeof(u->content.test_specific_data));
7006       fprintf(where, "sizeof(omni_response_struct)=%d/%d\n",
7007               (int)sizeof(struct omni_response_struct),
7008               (int)sizeof(u->content.test_specific_data));
7009       fprintf(where, "sizeof(omni_results_struct)=%d/%d\n",
7010               (int)sizeof(struct omni_results_struct),
7011               (int)sizeof(u->content.test_specific_data));
7012     }
7013     assert(sizeof(struct omni_request_struct)
7014            <= sizeof(u->content.test_specific_data));
7015     assert(sizeof(struct omni_response_struct)
7016            <= sizeof(u->content.test_specific_data));
7017     assert(sizeof(struct omni_results_struct)
7018            <= sizeof(u->content.test_specific_data));
7019   }
7020 
7021   strncpy(local_data_port,"0",sizeof(local_data_port));
7022   strncpy(remote_data_port,"0",sizeof(remote_data_port));
7023 
7024   /* this will handle setting default settings based on test name */
7025   set_omni_defaults_by_legacy_testname();
7026 
7027   /* Go through all the command line arguments and break them out. For
7028      those options that take two parms, specifying only the first will
7029      set both to that value. Specifying only the second will leave the
7030      first untouched. To change only the first, use the form "first,"
7031      (see the routine break_args.. */
7032 
7033   while ((c= getopt(argc, argv, OMNI_ARGS)) != EOF) {
7034     switch (c) {
7035     case '?':
7036     case '4':
7037       remote_data_family = AF_INET;
7038       local_data_family = AF_INET;
7039       break;
7040     case '6':
7041 #if defined(AF_INET6)
7042       remote_data_family = AF_INET6;
7043       local_data_family = AF_INET6;
7044 #else
7045       fprintf(stderr,
7046 	      "This netperf was not compiled on an IPv6 capable host!\n");
7047       fflush(stderr);
7048       exit(-1);
7049 #endif
7050       break;
7051     case 'h':
7052       print_omni_usage();
7053       exit(1);
7054     case 'a':
7055       want_defer_accept = 1;
7056       break;
7057     case 'B':
7058       want_use_pktinfo = 1;
7059       break;
7060     case 'b':
7061 #ifdef WANT_FIRST_BURST
7062       first_burst_size = atoi(optarg);
7063 #else /* WANT_FIRST_BURST */
7064       printf("Initial request burst functionality not compiled-in!\n");
7065 #endif /* WANT_FIRST_BURST */
7066       break;
7067     case 'c':
7068       /* this is a connection test */
7069       connection_test = 1;
7070       break;
7071     case 'C':
7072 #ifdef TCP_CORK
7073       /* set TCP_CORK */
7074       loc_tcpcork = 1;
7075       rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */
7076 #else
7077       printf("WARNING: TCP_CORK not available on this platform!\n");
7078 #endif /* TCP_CORK */
7079       break;
7080     case 'd':
7081       /* arbitrarily set the direction variable, but only for an
7082 	 actual omni test and then disable implicit setting of
7083 	 direction */
7084       if (!was_legacy) {
7085 	direction = parse_direction(optarg);
7086 	implicit_direction = 0;
7087       }
7088       break;
7089     case 'D':
7090       /* set the TCP nodelay flag */
7091       loc_nodelay = 1;
7092       rem_nodelay = 1;
7093       break;
7094     case 'F':
7095 #if defined(MSG_FASTOPEN)
7096       use_fastopen = 1;
7097 #else
7098       printf("WARNING: TCP FASTOPEN not available on this platform!\n");
7099 #endif
7100       break;
7101     case 'e':
7102       /* set the rEceive timeout */
7103       receive_timeout = atoi(optarg);
7104       break;
7105     case 'g':
7106       /* enable SO_DEBUG, or at least make the attempt, on the data socket */
7107       socket_debug = 1;
7108       break;
7109     case 'G':
7110       /* set the value for a tcp_maxseG call*/
7111       transport_mss_req = atoi(optarg);
7112       break;
7113     case 'H':
7114       break_args_explicit_sep(optarg,',',arg1,arg2);
7115       if (arg1[0]) {
7116 	/* check to see if there was a width, which we would want to
7117 	   be arg3. for simplicities sake, we will assume the width
7118 	   must follow the address and not the address family - ie
7119 	   1.2.3.4/24,inet.  This means we can just pass optarg again
7120 	   as the source rather than have to shuffle arg values. */
7121 	break_args_explicit_sep(optarg,'/',arg1,arg3);
7122 	if (arg1[0]) {
7123 	  remote_data_address = malloc(strlen(arg1)+1);
7124 	  strcpy(remote_data_address,arg1);
7125 	  explicit_data_address = 1;
7126 	}
7127 	if (arg3[0]) {
7128 	  remote_mask_len = convert(arg3);
7129 	}
7130       }
7131       if (arg2[0]) {
7132 	remote_data_family = parse_address_family(arg2);
7133       }
7134       break;
7135     case 'i':
7136       fprintf(stderr,"The support for check_interval has been removed because the contributing editor no longer knew what it was for\n");
7137       fflush(stderr);
7138       break;
7139     case 'I':
7140       use_write = 1;
7141       break;
7142     case 'j':
7143       parallel_connections = atoi(optarg);
7144       break;
7145     case 'k':
7146       netperf_output_mode = KEYVAL;
7147       legacy = 0;
7148       /* obliterate any previous file name */
7149       if (output_selection_spec) {
7150 	free(output_selection_spec);
7151 	output_selection_spec = NULL;
7152       }
7153       if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) {
7154 	/* we assume that what follows is the name of a file with the
7155 	   list of desired output values. */
7156 	output_selection_spec = strdup(argv[optind]);
7157 	optind++;
7158 	/* special case - if the file name is "?" then we will emit a
7159 	   list of the available outputs */
7160 	if (strcmp(output_selection_spec,"?") == 0) {
7161 	  dump_netperf_output_choices(stdout,1);
7162 	  exit(1);
7163 	}
7164       }
7165       break;
7166     case 'K':
7167       /* "Kongestion Kontrol */
7168       break_args(optarg,arg1,arg2);
7169       if (arg1[0])
7170 	strncpy(local_cong_control_req,arg1,sizeof(local_cong_control_req));
7171       if (arg2[2])
7172 	strncpy(remote_cong_control_req,arg2,sizeof(remote_cong_control_req));
7173       break;
7174     case 'l':
7175       multicast_ttl = atoi(optarg);
7176       break;
7177     case 'L':
7178       break_args_explicit_sep(optarg,',',arg1,arg2);
7179       if (arg1[0]) {
7180 	/* check to see if there was a width, which we would want to
7181 	   be arg3. for simplicities sake, we will assume the width
7182 	   must follow the address and not the address family - ie
7183 	   1.2.3.4/24,inet.  This means we can just pass optarg again
7184 	   as the source rather than have to shuffle arg values. */
7185 	break_args_explicit_sep(optarg,'/',arg1,arg3);
7186 	if (arg1[0]) {
7187 	  local_data_address = malloc(strlen(arg1)+1);
7188 	  strcpy(local_data_address,arg1);
7189 	}
7190 	if (arg3[0]) {
7191 	  local_mask_len = convert(arg3);
7192 	}
7193       }
7194       if (arg2[0]) {
7195 	local_data_family = parse_address_family(arg2);
7196       }
7197       break;
7198     case 'm':
7199       /* set the send size. if we set the local send size it will add
7200 	 XMIT to direction.  if we set the remote send size it will
7201 	 add RECV to the direction.  likely as not this will need some
7202 	 additional throught */
7203       break_args_explicit(optarg,arg1,arg2);
7204       if (arg1[0]) {
7205 	send_size = convert(arg1);
7206 	if (implicit_direction)
7207 	  direction |= NETPERF_XMIT;
7208       }
7209       if (arg2[0]) {
7210 	remote_send_size_req = convert(arg2);
7211 	if (implicit_direction)
7212 	  direction |= NETPERF_RECV;
7213       }
7214       break;
7215     case 'M':
7216       /* set the recv sizes.  if we set the local recv size it will
7217 	 add RECV to direction.  if we set the remote recv size it
7218 	 will add XMIT to direction  */
7219       break_args_explicit(optarg,arg1,arg2);
7220       if (arg1[0]) {
7221 	remote_recv_size_req = convert(arg1);
7222 	if (implicit_direction)
7223 	  direction |= NETPERF_XMIT;
7224       }
7225       if (arg2[0]) {
7226 	recv_size = convert(arg2);
7227 	if (implicit_direction)
7228 	  direction |= NETPERF_RECV;
7229       }
7230       break;
7231     case 'n':
7232       /* set the local socket type */
7233       local_connected = 1;
7234       break;
7235     case 'N':
7236       /* set the remote socket type */
7237       remote_connected = 1;
7238       break;
7239     case 'o':
7240       netperf_output_mode = CSV;
7241       legacy = 0;
7242       /* obliterate any previous file name */
7243       if (output_selection_spec) {
7244 	free(output_selection_spec);
7245 	output_selection_spec = NULL;
7246       }
7247       if (output_selection_spec) {
7248 	free(output_selection_spec);
7249 	output_selection_spec = NULL;
7250       }
7251       if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) {
7252 	/* we assume that what follows is the name of a file with the
7253 	   list of desired output values. */
7254 	output_selection_spec = strdup(argv[optind]);
7255 	optind++;
7256 	/* special case - if the file name is "?" then we will emit a
7257 	   list of the available outputs */
7258 	if (strcmp(output_selection_spec,"?") == 0) {
7259 	  dump_netperf_output_choices(stdout,1);
7260 	  exit(1);
7261 	}
7262       }
7263       break;
7264     case 'O':
7265       netperf_output_mode = HUMAN;
7266       legacy = 0;
7267       /* obliterate any previous file name */
7268       if (output_selection_spec) {
7269 	free(output_selection_spec);
7270 	output_selection_spec = NULL;
7271       }
7272       if (argv[optind] && ((unsigned char)argv[optind][0] != '-')) {
7273 	/* we assume that what follows is the name of a file with the
7274 	   list of desired output values */
7275 	output_selection_spec = strdup(argv[optind]);
7276 	optind++;
7277 	if (strcmp(output_selection_spec,"?") == 0) {
7278 	  dump_netperf_output_choices(stdout,0);
7279 	  exit(1);
7280 	}
7281       }
7282       break;
7283     case 'p':
7284       /* set the min and max port numbers for the TCP_CRR and TCP_TRR */
7285       /* tests. */
7286       break_args(optarg,arg1,arg2);
7287       if (arg1[0])
7288 	client_port_min = atoi(arg1);
7289       if (arg2[0])
7290 	client_port_max = atoi(arg2);
7291       break;
7292     case 'P':
7293       /* set the local and remote data port numbers for the tests to
7294 	 allow them to run through those blankety blank end-to-end
7295 	 breaking firewalls. raj 2004-06-15 */
7296       break_args(optarg,arg1,arg2);
7297       if (arg1[0])
7298 	strncpy(local_data_port,arg1,sizeof(local_data_port));
7299       if (arg2[0])
7300 	strncpy(remote_data_port,arg2,sizeof(remote_data_port));
7301       break;
7302     case 'r':
7303       /* set the request/response sizes. setting request/response
7304 	 sizes implicitly sets direction to XMIT and RECV */
7305       if (implicit_direction) {
7306 	direction |= NETPERF_XMIT;
7307 	direction |= NETPERF_RECV;
7308       }
7309       break_args(optarg,arg1,arg2);
7310       if (arg1[0])
7311 	req_size = convert(arg1);
7312       if (arg2[0])
7313 	rsp_size = convert(arg2);
7314       break;
7315     case 'R':
7316       routing_allowed = atoi(optarg);
7317       have_R_option = 1;
7318       break;
7319     case 's':
7320       /* set local socket sizes */
7321       break_args(optarg,arg1,arg2);
7322       if (arg1[0])
7323 	lss_size_req = convert(arg1);
7324       if (arg2[0])
7325 	lsr_size_req = convert(arg2);
7326       break;
7327     case 'S':
7328       /* set remote socket sizes */
7329       break_args(optarg,arg1,arg2);
7330       if (arg1[0])
7331 	rss_size_req = convert(arg1);
7332       if (arg2[0])
7333 	rsr_size_req = convert(arg2);
7334       break;
7335     case 't':
7336       /* set the socket type */
7337       socket_type = parse_socket_type(optarg);
7338       break;
7339     case 'T':
7340       /* set the protocol - aka "Transport" */
7341       protocol = parse_protocol(optarg);
7342       break;
7343     case 'u':
7344       /* use the supplied string as the UUID for this test. at some
7345 	 point we may want to sanity check the string we are given but
7346 	 for now we won't worry about it */
7347       strncpy(test_uuid,optarg,sizeof(test_uuid));
7348       /* strncpy may leave us with a string without a null at the end */
7349       test_uuid[sizeof(test_uuid) - 1] = 0;
7350       have_uuid = 1;
7351       break;
7352     case 'U':
7353       /* we don't want to give-up on the failure of a connect() call */
7354       dont_give_up = 1;
7355       break;
7356     case 'W':
7357       /* set the "width" of the user space data */
7358       /* buffer. This will be the number of */
7359       /* send_size buffers malloc'd in the */
7360       /* *_STREAM test. It may be enhanced to set */
7361       /* both send and receive "widths" but for now */
7362       /* it is just the sending *_STREAM. */
7363       send_width = convert(optarg);
7364       break;
7365     case 'V' :
7366       /* we want to do copy avoidance and will set */
7367       /* it for everything, everywhere, if we really */
7368       /* can. of course, we don't know anything */
7369       /* about the remote... */
7370       loc_sndavoid = 1;
7371       loc_rcvavoid = 1;
7372       rem_sndavoid = 1;
7373       rem_rcvavoid = 1;
7374       break;
7375     };
7376   }
7377 
7378   /* generate the UUID for this test if the user has not supplied it */
7379   if (!have_uuid)
7380     get_uuid_string(test_uuid,sizeof(test_uuid));
7381 
7382   protocol_str = protocol_to_str(protocol);
7383   /* ok, if we have gone through all that, and direction is still
7384      zero, let us see if it needs to be set to something else. */
7385   if ((0 == direction) && (!connection_test)) direction = NETPERF_XMIT;
7386   direction_str = direction_to_str(direction);
7387 
7388   /* to cover the backside of blithering idiots who run unidirectional
7389      UDP tests on test setups where they might trash their corporate
7390      WAN, we grudgingly provide a safety latch. unless explicitly
7391      enabled, UDP_STREAM/UDP_MAERTS sockets will not allow themselves
7392      to be routed via a gateway. raj 20091026 */
7393 
7394   if ((!have_R_option) &&
7395       (protocol == IPPROTO_UDP) &&
7396       (!NETPERF_IS_RR(direction))) {
7397     routing_allowed = 0;
7398   }
7399 
7400   /* some other sanity checks we need to make would include stuff when
7401      the user has set -m and -M such that both XMIT and RECV are set
7402      and has not set -r. initially we will not allow that.  at some
7403      point we might allow that if the user has also set -r, but until
7404      then the code will simply ignore the values from -m and -M when
7405      -r is set. */
7406 
7407 #if defined(WANT_HISTOGRAM)
7408   if (verbosity > 1) keep_histogram = 1;
7409 #endif
7410 
7411   /* did the user use -d 6 but not set -r? */
7412   if (NETPERF_IS_RR(direction) && !NETPERF_CC(direction)) {
7413     if (req_size == -1)
7414       req_size = 1;
7415     if (rsp_size == -1)
7416       rsp_size = 1;
7417   }
7418 
7419   /* ok, time to sanity check the output units */
7420   if ('?' == libfmt) {
7421     /* if this is a RR test then set it to 'x' for transactions */
7422     if (NETPERF_IS_RR(direction)) {
7423       libfmt = 'x';
7424     }
7425     else {
7426       libfmt = 'm';
7427     }
7428   }
7429   else if ('x' == libfmt) {
7430     /* now, a format of 'x' makes no sense for anything other than
7431        an RR test. if someone has been silly enough to try to set
7432        that, we will reset it silently to default - namely 'm' */
7433     if (!NETPERF_IS_RR(direction)) {
7434       libfmt = 'm';
7435     }
7436   }
7437 
7438   /* this needs to be strdup :) */
7439   thruput_format_str = strdup(format_units());
7440 
7441   /* so, if there is to be no control connection, we want to have some
7442      different settings for a few things */
7443 
7444   if (no_control) {
7445     if (strcmp(remote_data_port,"0") == 0) {
7446       /* we need to select either the discard port, echo port or
7447 	 chargen port dedepending on the test direction. raj
7448 	 20101220 */
7449       if (NETPERF_XMIT_ONLY(direction)) {
7450 	strncpy(remote_data_port,"discard",sizeof(remote_data_port));
7451 	recv_size = -1;
7452       }
7453       else if (NETPERF_RECV_ONLY(direction)) {
7454 	strncpy(remote_data_port,"chargen",sizeof(remote_data_port));
7455 	send_size = -1;
7456       }
7457       else if (NETPERF_IS_RR(direction) || NETPERF_CC(direction)) {
7458 	strncpy(remote_data_port,"echo",sizeof(remote_data_port));
7459 	rsp_size = req_size;
7460       }
7461       else {
7462 	printf("No default port known for the %s test, please set one yourself\n",test_name);
7463 	exit(-1);
7464       }
7465     }
7466     remote_data_port[sizeof(remote_data_port) - 1] = '\0';
7467 
7468     /* I go back and forth on whether these should become -1 or if
7469        they should become 0 for a no_control test. what do you think?
7470        raj 2006-02-08 */
7471 
7472     rem_rcvavoid = -1;
7473     rem_sndavoid = -1;
7474     rss_size_req = -1;
7475     rsr_size_req = -1;
7476     rem_nodelay = -1;
7477 
7478   }
7479   /* so, did the user request a few things implicitly via output selection? */
7480   if (!legacy)
7481     print_omni_init();
7482 
7483   if (desired_output_groups & OMNI_WANT_STATS) {
7484     keep_statistics = 1;
7485     keep_histogram = 1;
7486   }
7487 
7488 }
7489 
7490 #endif /* WANT_OMNI */
7491