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