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