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