1 #ifndef lint
2 char nettest_id[]="\
3 @(#)nettest_bsd.c (c) Copyright 1993-2012 Hewlett-Packard Co. Version 2.6.0";
4 #endif /* lint */
5
6
7 /****************************************************************/
8 /* */
9 /* nettest_bsd.c */
10 /* */
11 /* the BSD sockets parsing routine... */
12 /* ...with the addition of Windows NT, this is now also */
13 /* a Winsock test... sigh :) */
14 /* */
15 /* scan_sockets_args() */
16 /* */
17 /* the actual test routines... */
18 /* */
19 /* send_tcp_stream() perform a tcp stream test */
20 /* recv_tcp_stream() */
21 /* send_tcp_maerts() perform a tcp stream test */
22 /* recv_tcp_maerts() in the other direction */
23 /* send_tcp_rr() perform a tcp request/response */
24 /* recv_tcp_rr() */
25 /* send_tcp_conn_rr() an RR test including connect */
26 /* recv_tcp_conn_rr() */
27 /* send_tcp_cc() a connect/disconnect test with */
28 /* recv_tcp_cc() no RR */
29 /* send_tcp_mss() just report the mss */
30 /* send_udp_stream() perform a udp stream test */
31 /* recv_udp_stream() */
32 /* send_udp_rr() perform a udp request/response */
33 /* recv_udp_rr() */
34 /* loc_cpu_rate() determine the local cpu maxrate */
35 /* rem_cpu_rate() find the remote cpu maxrate */
36 /* */
37 /****************************************************************/
38
39 #ifdef HAVE_CONFIG_H
40 #include <config.h>
41 #endif
42
43 #include <stdio.h>
44 #if HAVE_SYS_TYPES_H
45 # include <sys/types.h>
46 #endif
47 #if HAVE_SYS_STAT_H
48 # include <sys/stat.h>
49 #endif
50 #if STDC_HEADERS
51 # include <stdlib.h>
52 # include <stddef.h>
53 #else
54 # if HAVE_STDLIB_H
55 # include <stdlib.h>
56 # endif
57 #endif
58 #if HAVE_STRING_H
59 # if !STDC_HEADERS && HAVE_MEMORY_H
60 # include <memory.h>
61 # endif
62 # include <string.h>
63 #endif
64 #if HAVE_STRINGS_H
65 # include <strings.h>
66 #endif
67 #if HAVE_INTTYPES_H
68 # include <inttypes.h>
69 #else
70 # if HAVE_STDINT_H
71 # include <stdint.h>
72 # endif
73 #endif
74 #if HAVE_UNISTD_H
75 # include <unistd.h>
76 #endif
77 #if HAVE_AIO
78 # include <assert.h> // XXX
79 # include <aio.h>
80 #endif
81
82 #include <fcntl.h>
83 #ifndef WIN32
84 #include <errno.h>
85 #include <signal.h>
86 #endif
87
88 #if TIME_WITH_SYS_TIME
89 # include <sys/time.h>
90 # include <time.h>
91 #else
92 # if HAVE_SYS_TIME_H
93 # include <sys/time.h>
94 # else
95 # include <time.h>
96 # endif
97 #endif
98
99 #ifdef NOSTDLIBH
100 #include <malloc.h>
101 #endif /* NOSTDLIBH */
102
103
104 #ifndef WIN32
105 #if !defined(__VMS)
106 #if defined(HAVE_SYS_IPC_H)
107 #include <sys/ipc.h>
108 #endif
109 #endif /* !__VMS */
110 #include <sys/socket.h>
111 #include <netinet/in.h>
112 #include <netinet/tcp.h>
113
114 #ifdef HAVE_NETINET_SCTP_H
115 #include <netinet/sctp.h>
116 #endif
117
118 #include <arpa/inet.h>
119 #include <netdb.h>
120 #else /* WIN32 */
121 #include <process.h>
122 #define netperf_socklen_t socklen_t
123 #include <winsock2.h>
124 #include "missing\stdint.h"
125 /* while it is unlikely that anyone running Windows 2000 or NT 4 is
126 going to be trying to compile this, if they are they will want to
127 define DONT_IPV6 in the sources file */
128 #ifndef DONT_IPV6
129 #include <ws2tcpip.h>
130 #endif
131
132 #define WIN32_LEAN_AND_MEAN 1
133 #include <windows.h>
134
135 #define sleep(x) Sleep((x)*1000)
136
137 #define __func__ __FUNCTION__
138 #endif /* WIN32 */
139
140 /* We don't want to use bare constants in the shutdown() call. In the
141 extremely unlikely event that SHUT_WR isn't defined, we will define
142 it to the value we used to be passing to shutdown() anyway. raj
143 2007-02-08 */
144 #if !defined(SHUT_WR)
145 #define SHUT_WR 1
146 #endif
147
148 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
149 # include "missing/getaddrinfo.h"
150 #endif
151
152 #include "netlib.h"
153 #include "netsh.h"
154 #include "nettest_bsd.h"
155
156 #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO)
157 #include "hist.h"
158 #endif /* WANT_HISTOGRAM */
159
160
161 /* make first_burst_size unconditional so we can use it easily enough
162 when calculating transaction latency for the TCP_RR test. raj
163 2007-06-08 however, change its default value so one can tell in
164 "omni" output whether or not WANT_BURST was enabled. raj
165 2008-01-28 */
166 #if defined(WANT_FIRST_BURST)
167 int first_burst_size=0;
168 #else
169 int first_burst_size=-1;
170 #endif
171
172 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun))
173 #include <sys/sendfile.h>
174 #endif /* HAVE_SENDFILE && (__linux || __sun) */
175
176
177
178 /* these variables are specific to the BSD sockets tests, but can
179 * be used elsewhere if needed. They are externed through nettest_bsd.h
180 */
181
182 int
183 socket_type, /* used initially by the "omni" tests */
184 rss_size_req = -1, /* requested remote socket send buffer size */
185 rsr_size_req = -1, /* requested remote socket recv buffer size */
186 rss_size, /* initial remote socket send buffer size */
187 rsr_size, /* initial remote socket recv buffer size */
188 rss_size_end = -1, /* final remote socket send buffer size */
189 rsr_size_end = -1, /* final remote socket recv buffer size */
190 lss_size_req = -1, /* requested local socket send buffer size */
191 lsr_size_req = -1, /* requested local socket recv buffer size */
192 lss_size, /* local socket send buffer size */
193 lsr_size, /* local socket recv buffer size */
194 lss_size_end = -1, /* final local socket send buffer size */
195 lsr_size_end = -1, /* final local socket recv buffer size */
196 req_size = 1, /* request size */
197 rsp_size = 1, /* response size */
198 send_size, /* how big are individual sends */
199 recv_size, /* how big are individual receives */
200 transport_mss_req = -1; /* what maximum segment size is wanted */
201
202 static int confidence_iteration;
203 static char local_cpu_method;
204 static char remote_cpu_method;
205
206 /* these will control the width of port numbers we try to use in the */
207 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
208 static int client_port_min = 5000;
209 static int client_port_max = 65535;
210
211 /* different options for the sockets */
212
213 int
214 loc_nodelay, /* don't/do use NODELAY locally */
215 rem_nodelay, /* don't/do use NODELAY remotely */
216 #ifdef TCP_CORK
217 loc_tcpcork=0, /* don't/do use TCP_CORK locally */
218 rem_tcpcork=0, /* don't/do use TCP_CORK remotely */
219 #else
220 loc_tcpcork=-1,
221 rem_tcpcork=-1,
222 #endif /* TCP_CORK */
223 #if HAVE_AIO
224 loc_rcvaio, /* don't/do use aio_read() locally */
225 rem_rcvaio, /* don't/do use aio_read() remotely */
226 loc_sndaio, /* don't/do use aio_write() locally */
227 rem_sndaio, /* don't/do use aio_write() remotely */
228 #else
229 loc_rcvaio=-1,
230 rem_rcvaio=-1,
231 loc_sndaio=-1,
232 rem_sndaio=-1,
233 #endif
234 loc_sndavoid, /* avoid send copies locally */
235 loc_rcvavoid, /* avoid recv copies locally */
236 rem_sndavoid, /* avoid send copies remotely */
237 rem_rcvavoid, /* avoid recv_copies remotely */
238 local_connected = 0, /* local socket type, connected/non-connected */
239 remote_connected = 0, /* remote socket type, connected/non-connected */
240 routing_allowed = 1, /* set/clear SO_DONTROUTE on data socket */
241 pacing_rate = 0; /* set a socket pacing rate? */
242
243 int multicast_ttl = -1; /* should we set the multicast TTL to a value? */
244
245 int want_keepalive = 0;
246
247 #ifdef WANT_HISTOGRAM
248 #ifdef HAVE_GETHRTIME
249 static hrtime_t time_one;
250 static hrtime_t time_two;
251 #elif HAVE_GET_HRT
252 #include "hrt.h"
253 static hrt_t time_one;
254 static hrt_t time_two;
255 #elif defined(WIN32)
256 static LARGE_INTEGER time_one;
257 static LARGE_INTEGER time_two;
258 #else
259 static struct timeval time_one;
260 static struct timeval time_two;
261 #endif /* HAVE_GETHRTIME */
262 static HIST time_hist;
263 #endif /* WANT_HISTOGRAM */
264
265 #ifdef WANT_INTERVALS
266 int interval_count;
267 #ifndef WANT_SPIN
268 #ifdef WIN32
269 #define INTERVALS_INIT() \
270 if (interval_burst) { \
271 /* zero means that we never pause, so we never should need the \
272 interval timer. we used to use it for demo mode, but we deal \
273 with that with a variant on watching the clock rather than \
274 waiting for a timer. raj 2006-02-06 */ \
275 start_itimer(interval_wate); \
276 } \
277 interval_count = interval_burst;
278 #else
279 sigset_t signal_set;
280 #define INTERVALS_INIT() \
281 if (interval_burst) { \
282 /* zero means that we never pause, so we never should need the \
283 interval timer. we used to use it for demo mode, but we deal \
284 with that with a variant on watching the clock rather than \
285 waiting for a timer. raj 2006-02-06 */ \
286 start_itimer(interval_wate); \
287 } \
288 interval_count = interval_burst; \
289 /* get the signal set for the call to sigsuspend */ \
290 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \
291 fprintf(where, \
292 "%s: unable to get sigmask errno %d\n", \
293 __func__, \
294 errno); \
295 fflush(where); \
296 exit(1); \
297 }
298 #endif /* WIN32 */
299
300 #ifdef WIN32
301 #define INTERVALS_WAIT() \
302 /* in this case, the interval count is the count-down counter \
303 to decide to sleep for a little bit */ \
304 if ((interval_burst) && (--interval_count == 0)) { \
305 /* call WaitForSingleObject and wait for the interval timer to get us \
306 out */ \
307 if (debug > 1) { \
308 fprintf(where,"about to suspend\n"); \
309 fflush(where); \
310 } \
311 if (WaitForSingleObject(WinTimer, INFINITE) != WAIT_OBJECT_0) { \
312 fprintf(where, "WaitForSingleObject failed (%d)\n", GetLastError()); \
313 fflush(where); \
314 exit(1); \
315 } \
316 interval_count = interval_burst; \
317 }
318 #else
319 #define INTERVALS_WAIT() \
320 /* in this case, the interval count is the count-down couter \
321 to decide to sleep for a little bit */ \
322 if ((interval_burst) && (--interval_count == 0)) { \
323 /* call sigsuspend and wait for the interval timer to get us \
324 out */ \
325 if (debug > 1) { \
326 fprintf(where,"about to suspend\n"); \
327 fflush(where); \
328 } \
329 if (sigsuspend(&signal_set) == EFAULT) { \
330 fprintf(where, \
331 "%s: fault with sigsuspend.\n", \
332 __func__); \
333 fflush(where); \
334 exit(1); \
335 } \
336 interval_count = interval_burst; \
337 }
338 #endif /* WIN32 */
339 #else
340 /* first out timestamp */
341 #ifdef HAVE_GETHRTIME
342 static hrtime_t intvl_one;
343 static hrtime_t intvl_two;
344 static hrtime_t *intvl_one_ptr = &intvl_one;
345 static hrtime_t *intvl_two_ptr = &intvl_two;
346 static hrtime_t *temp_intvl_ptr = &intvl_one;
347 #elif defined(WIN32)
348 static LARGE_INTEGER intvl_one;
349 static LARGE_INTEGER intvl_two;
350 static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
351 static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
352 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
353 #else
354 static struct timeval intvl_one;
355 static struct timeval intvl_two;
356 static struct timeval *intvl_one_ptr = &intvl_one;
357 static struct timeval *intvl_two_ptr = &intvl_two;
358 static struct timeval *temp_intvl_ptr = &intvl_one;
359 #endif
360
361 #define INTERVALS_INIT() \
362 if (interval_burst) { \
363 HIST_timestamp(intvl_one_ptr); \
364 } \
365 interval_count = interval_burst; \
366
367 #define INTERVALS_WAIT() \
368 /* in this case, the interval count is the count-down couter \
369 to decide to sleep for a little bit */ \
370 if ((interval_burst) && (--interval_count == 0)) { \
371 /* call sigsuspend and wait for the interval timer to get us \
372 out */ \
373 if (debug > 1) { \
374 fprintf(where,"about to spin suspend\n"); \
375 fflush(where); \
376 } \
377 HIST_timestamp(intvl_two_ptr); \
378 while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \
379 HIST_timestamp(intvl_two_ptr); \
380 } \
381 temp_intvl_ptr = intvl_one_ptr; \
382 intvl_one_ptr = intvl_two_ptr; \
383 intvl_two_ptr = temp_intvl_ptr; \
384 interval_count = interval_burst; \
385 }
386 #endif
387 #endif
388
389
390 char sockets_usage[] = "\n\
391 Usage: netperf [global options] -- [test options] \n\
392 \n\
393 TCP/UDP BSD Sockets Test Options:\n\
394 -a Use aio_write(2)\n\
395 -A Use aio_read(2)\n\
396 -b number Send number requests at start of _RR tests\n\
397 -C Set TCP_CORK when available\n\
398 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\
399 -h Display this text\n\
400 -H name,fam Use name (or IP) and family as target of data connection\n\
401 -L name,fam Use name (or IP) and family as source of data connection\n\
402 -m bytes Set the send size (TCP_STREAM, UDP_STREAM)\n\
403 -M bytes Set the recv size (TCP_STREAM, UDP_STREAM)\n\
404 -n Use the connected socket for UDP locally\n\
405 -N Use the connected socket for UDP remotely\n\
406 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\
407 -P local[,remote] Set the local/remote port for the data socket\n\
408 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\
409 -s send[,recv] Set local socket send/recv buffer sizes\n\
410 -S send[,recv] Set remote socket send/recv buffer sizes\n\
411 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
412 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
413 \n\
414 For those options taking two parms, at least one must be specified;\n\
415 specifying one value without a comma will set both parms to that\n\
416 value, specifying a value with a leading comma will set just the second\n\
417 parm, a value with a trailing comma will set just the first. To set\n\
418 each parm to unique values, specify both and separate them with a\n\
419 comma.\n";
420
421
422
423 /* these routines convert between the AF address space and the NF
424 address space since the numeric values of AF_mumble are not the
425 same across the platforms. raj 2005-02-08 */
426
427 int
nf_to_af(int nf)428 nf_to_af(int nf) {
429 switch(nf) {
430 case NF_INET:
431 return AF_INET;
432 case NF_UNSPEC:
433 return AF_UNSPEC;
434 case NF_INET6:
435 #if defined(AF_INET6)
436 return AF_INET6;
437 #else
438 return AF_UNSPEC;
439 #endif
440 case NF_RDS:
441 #if defined(AF_RDS)
442 return AF_RDS;
443 #else
444 return AF_UNSPEC;
445 #endif
446 default:
447 return AF_UNSPEC;
448 }
449 }
450
451 int
af_to_nf(int af)452 af_to_nf(int af) {
453
454 switch(af) {
455 case AF_INET:
456 return NF_INET;
457 case AF_UNSPEC:
458 return NF_UNSPEC;
459 #if defined(AF_INET6)
460 case AF_INET6:
461 return NF_INET6;
462 #endif
463 #if defined(AF_RDS)
464 case AF_RDS:
465 return NF_RDS;
466 #endif
467 default:
468 return NF_UNSPEC;
469 }
470 }
471
472
473 /* these routines will convert between the hosts' socket types and
474 those netperf uses. we need this because different platforms can
475 have different values for SOCK_STREAM, SOCK_DGRAM and the
476 like... */
477
478 int
nst_to_hst(int nst)479 nst_to_hst(int nst) {
480 switch(nst) {
481 #ifdef SOCK_STREAM
482 case NST_STREAM:
483 return SOCK_STREAM;
484 break; /* ok, this may not be necessary :) */
485 #endif
486 #ifdef SOCK_DGRAM
487 case NST_DGRAM:
488 return SOCK_DGRAM;
489 break;
490 #endif
491 #ifdef SOCK_DCCP
492 case NST_DCCP:
493 return SOCK_DCCP;
494 break;
495 #endif
496 #ifdef SOCK_SEQPACKET
497 case NST_SEQPACKET:
498 return NST_SEQPACKET;
499 #endif
500 default:
501 return -1;
502 }
503 }
504
505 int
hst_to_nst(int hst)506 hst_to_nst(int hst) {
507
508 switch(hst) {
509 #ifdef SOCK_STREAM
510 case SOCK_STREAM:
511 return NST_STREAM;
512 break;
513 #endif
514 #ifdef SOCK_DGRAM
515 case SOCK_DGRAM:
516 return NST_DGRAM;
517 break;
518 #endif
519 #ifdef SOCK_DCCP
520 case SOCK_DCCP:
521 return NST_DCCP;
522 break;
523 #endif
524 #ifdef SOCK_SEQPACKET
525 case SOCK_SEQPACKET:
526 return NST_SEQPACKET;
527 #endif
528 default:
529 return NST_UNKN;
530 }
531 }
532 char *
hst_to_str(int hst)533 hst_to_str(int hst) {
534
535 switch(hst) {
536 #ifdef SOCK_STREAM
537 case SOCK_STREAM:
538 return "Stream";
539 break;
540 #endif
541 #ifdef SOCK_DGRAM
542 case SOCK_DGRAM:
543 return "Datagram";
544 break;
545 #endif
546 #ifdef SOCK_DCCP
547 case SOCK_DCCP:
548 return "DCCP";
549 break;
550 #endif
551 #ifdef SOCK_SEQPACKET
552 case SOCK_SEQPACKET:
553 return "Seqpacket";
554 #endif
555 default:
556 return "Unknown";
557 }
558 }
559
560 char *
protocol_to_str(int protocol)561 protocol_to_str(int protocol) {
562 switch(protocol) {
563 /* ass-u-me that everyone has IPPROTO_TCP and IPPROTO_UDP */
564 case IPPROTO_TCP:
565 return "TCP";
566 case IPPROTO_UDP:
567 return "UDP";
568 /* but do not assume that everyone has the others */
569 #ifdef IPPROTO_UDPLITE
570 case IPPROTO_UDPLITE:
571 return "UDPLite";
572 #endif
573 #ifdef IPPROTO_SCTP
574 case IPPROTO_SCTP:
575 return "SCTP";
576 #endif
577 #ifdef IPPROTO_DCCP
578 case IPPROTO_DCCP:
579 return "DCCP";
580 #endif
581 #ifdef IPPROTO_SDP
582 case IPPROTO_SDP:
583 return "SDP";
584 #endif
585 #ifdef IPPROTO_IP
586 case IPPROTO_IP:
587 return "IP Default";
588 #endif
589 default:
590 return "Unknown Protocol";
591 }
592 }
593
594
595 /* This routine is intended to retrieve interesting aspects of tcp */
596 /* for the data connection. at first, it attempts to retrieve the */
597 /* maximum segment size. later, it might be modified to retrieve */
598 /* other information, but it must be information that can be */
599 /* retrieved quickly as it is called during the timing of the test. */
600 /* for that reason, a second routine may be created that can be */
601 /* called outside of the timing loop */
602 static
603 void
get_tcp_info(SOCKET socket,int * mss)604 get_tcp_info(SOCKET socket, int *mss)
605 {
606
607 #ifdef TCP_MAXSEG
608 netperf_socklen_t sock_opt_len;
609
610 sock_opt_len = sizeof(int);
611 if (getsockopt(socket,
612 getprotobyname("tcp")->p_proto,
613 TCP_MAXSEG,
614 (char *)mss,
615 &sock_opt_len) == SOCKET_ERROR) {
616 fprintf(where,
617 "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n",
618 errno);
619 fflush(where);
620 *mss = -1;
621 }
622 #else
623 *mss = -1;
624 #endif /* TCP_MAXSEG */
625 }
626
627 static
628 void
set_tcp_mss(SOCKET socket,int mss)629 set_tcp_mss(SOCKET socket, int mss) {
630 #ifdef TCP_MAXSEG
631 netperf_socklen_t sock_opt_len;
632
633 sock_opt_len = sizeof(int);
634 if ((setsockopt(socket,
635 getprotobyname("tcp")->p_proto,
636 TCP_MAXSEG,
637 (const char *)&mss,
638 sock_opt_len) == SOCKET_ERROR) && (debug)) {
639 fprintf(where,
640 "netperf: %s: setsockopt TCP_MAXSEG: %s (errno %d)\n",
641 __FUNCTION__,
642 strerror(errno),
643 errno);
644 fflush(where);
645 }
646 #else
647 if (debug) {
648 fprintf(where,
649 "netperf: %s platform does not know how to set TCP segment size\n",
650 __FUNCTION__);
651 fflush(where);
652 }
653
654 #endif /* TCP_MAXSEG */
655 }
656
657
658
659 /* return a pointer to a completed addrinfo chain - prefer
660 data_address to controlhost and utilize the specified address
661 family */
662
663 struct addrinfo *
complete_addrinfo(char * controlhost,char * data_address,char * port,int family,int type,int protocol,int flags)664 complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags)
665 {
666 struct addrinfo hints;
667 struct addrinfo *res;
668 struct addrinfo *temp_res;
669
670 #define CHANGED_SOCK_TYPE 0x1
671 #define CHANGED_PROTOCOL 0x2
672 #define CHANGED_SCTP 0x4
673 #define CHANGED_DCCP 0x8
674 #define CHANGED_DCCP_SOCK 0x10
675
676 int change_info = 0;
677 static int change_warning_displayed = 0;
678
679 int count = 0;
680 int error = 0;
681
682 char *hostname;
683
684 /* take data-address over controlhost */
685 if (data_address)
686 hostname = data_address;
687 else
688 hostname = controlhost;
689
690 if (debug) {
691 fprintf(where,
692 "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n",
693 hostname,
694 port,
695 inet_ftos(family),
696 inet_ttos(type),
697 inet_ptos(protocol),
698 flags);
699 fflush(where);
700 }
701
702 memset(&hints, 0, sizeof(hints));
703 hints.ai_family = family;
704 hints.ai_socktype = type;
705 hints.ai_protocol = protocol;
706 hints.ai_flags = flags|AI_CANONNAME|AI_ADDRCONFIG;
707
708 count = 0;
709 do {
710 error = getaddrinfo((char *)hostname,
711 (char *)port,
712 &hints,
713 &res);
714 count += 1;
715 if (error == EAI_AGAIN) {
716 if (debug) {
717 fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
718 fflush(where);
719 }
720 sleep(1);
721 }
722 /* while you see this kludge first, it is actually the second, the
723 first being the one for Solaris below. The need for this kludge
724 came after implementing the Solaris broken getaddrinfo kludge -
725 now we see a kludge in Linux getaddrinfo where if it is given
726 SOCK_STREAM and IPPROTO_SCTP it barfs with a -7
727 EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if
728 we were asking for IPPROTO_SCTP and if so, kludge, again... raj
729 200?-10-13 and of course, requiring the kludge for SCTP, it is
730 no surprise that linux needs a kludge for DCCP...actually not
731 only does it need the ai_protocol kludge, it needs an
732 ai_socktype kludge too... sigh raj 2008-02-01 */
733 #if defined(IPPROTO_SCTP) || defined (IPPROTO_DCCP)
734 if (EAI_SOCKTYPE == error
735 #ifdef EAI_BADHINTS
736 || EAI_BADHINTS == error
737 #endif
738 ) {
739 /* we ass-u-me this is the Linux getaddrinfo bug, clear the
740 hints.ai_protocol field, and set some state "remembering"
741 that we did this so the code for the Solaris kludge can do
742 the fix-up for us. also flip error over to EAI_AGAIN and
743 make sure we don't "count" this time around the loop. */
744 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
745 /* only tweak on this one the second time around, after we've
746 kludged the ai_protocol field */
747 if ((hints.ai_socktype == SOCK_DCCP) &&
748 (hints.ai_protocol == 0)) {
749 change_info |= CHANGED_DCCP_SOCK;
750 hints.ai_socktype = 0;
751 /* we need to give it some sort of IPPROTO or it gets unhappy,
752 so for now, pick one from deep within the colon and use
753 IPPROTO_TCP */
754 hints.ai_protocol = IPPROTO_TCP;
755 }
756
757 if (hints.ai_protocol == IPPROTO_DCCP) {
758 change_info |= CHANGED_DCCP;
759 hints.ai_protocol = 0;
760 }
761
762 #endif
763 #if defined(IPPROTO_SCTP)
764 if (hints.ai_protocol == IPPROTO_SCTP) {
765 change_info |= CHANGED_SCTP;
766 hints.ai_protocol = 0;
767 }
768 #endif
769
770 error = EAI_AGAIN;
771 count -= 1;
772 }
773 #endif
774 } while ((error == EAI_AGAIN) && (count <= 5));
775
776 if (error) {
777 fprintf(where,
778 "complete_addrinfo: could not resolve '%s' port '%s' af %d"
779 "\n\tgetaddrinfo returned %d %s\n",
780 hostname,
781 port,
782 family,
783 error,
784 gai_strerror(error));
785 fflush(where);
786 exit(-1);
787 }
788
789 /* there exists at least one platform - Solaris 10 - that does not
790 seem to completely honor the ai_protocol and/or ai_socktype one
791 sets in the hints parm to the getaddrinfo call. so, we need to
792 walk the list of entries returned and if either of those do not
793 match what we asked for, we need to go ahead and set them
794 "correctly" this is based in part on some earlier SCTP-only code
795 from previous revisions. raj 2006-10-09 */
796
797 temp_res = res;
798
799 while (temp_res) {
800
801 if ((type) &&
802 (temp_res->ai_socktype != type)) {
803 change_info |= CHANGED_SOCK_TYPE;
804 if (debug) {
805 fprintf(where,
806 "WARNING! Changed bogus getaddrinfo socket type %d to %d\n",
807 temp_res->ai_socktype,
808 type);
809 fflush(where);
810 }
811 temp_res->ai_socktype = type;
812 }
813
814 if ((protocol) &&
815 (temp_res->ai_protocol != protocol)) {
816 change_info |= CHANGED_PROTOCOL;
817 if (debug) {
818 fprintf(where,
819 "WARNING! Changed bogus getaddrinfo protocol %d to %d\n",
820 temp_res->ai_protocol,
821 protocol);
822 fflush(where);
823 }
824 temp_res->ai_protocol = protocol;
825 }
826 temp_res = temp_res->ai_next;
827 }
828
829 if ((change_info & CHANGED_SOCK_TYPE) &&
830 !(change_warning_displayed & CHANGED_SOCK_TYPE)) {
831 change_warning_displayed |= CHANGED_SOCK_TYPE;
832 fprintf(where,
833 "WARNING! getaddrinfo returned a socket type which did not\n"
834 "match the requested type. Please contact your vendor for\n"
835 "a fix to this bug in getaddrinfo()\n");
836 fflush(where);
837 }
838
839 /* if we dropped the protocol hint, it would be for a protocol that
840 getaddrinfo() wasn't supporting yet, not for the bug that it took
841 our hint and still returned zero. raj 2006-10-16 */
842 /* as there is now an open bug against (Open)Solaris (id 6847733) on
843 this behaviour we will only emit this warning if debug is set
844 under Solaris and will continue to emit it under any circumstance
845 on other platforms should it arise. raj 2009-06-03 */
846 /* since it has now been two years since that bug was filed, it
847 should be resolved by now, so the "out" given to Sun should no
848 longer be necessary. either folks are running with the fix or
849 they need to get the fix. raj 2011-07-06 */
850 if ((change_info & CHANGED_PROTOCOL) &&
851 !(change_warning_displayed & CHANGED_PROTOCOL) &&
852 (hints.ai_protocol != 0)) {
853 change_warning_displayed |= CHANGED_PROTOCOL;
854 fprintf(where,
855 "WARNING! getaddrinfo returned a protocol other than the\n"
856 "requested protocol. Please contact your vendor for\n"
857 "a fix to this bug in getaddrinfo()\n");
858 fflush(where);
859 }
860
861 if ((change_info & CHANGED_SCTP) &&
862 !(change_warning_displayed & CHANGED_SCTP)) {
863 change_warning_displayed |= CHANGED_SCTP;
864 fprintf(where,
865 "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n"
866 "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
867 fflush(where);
868 }
869
870 if ((change_info & CHANGED_DCCP) &&
871 !(change_warning_displayed & CHANGED_DCCP)) {
872 change_warning_displayed |= CHANGED_DCCP;
873 fprintf(where,
874 "WARNING! getaddrinfo on this platform does not accept IPPROTO_DCCP!\n"
875 "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
876 fflush(where);
877 }
878
879
880 if (debug) {
881 dump_addrinfo(where, res, hostname, port, family);
882 }
883
884 return(res);
885 }
886
887 void
complete_addrinfos(struct addrinfo ** remote,struct addrinfo ** local,char remote_host[],int type,int protocol,int flags)888 complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) {
889
890 if (remote_data_family == AF_UNSPEC) {
891 remote_data_family = control_family;
892 }
893
894 *remote = complete_addrinfo(remote_host,
895 remote_data_address,
896 remote_data_port,
897 remote_data_family,
898 type,
899 protocol,
900 flags);
901
902 /* OK, if the user has not specified a local data endpoint address
903 (test-specific -L), pick the local data endpoint address based on
904 the remote data family info (test-specific -H or -4 or -6
905 option). if the user has not specified remote data addressing
906 info (test-specific -H, -4 -6) pick something based on the local
907 control connection address (ie the global -L option). */
908
909 if (NULL == local_data_address) {
910 local_data_address = malloc(HOSTNAMESIZE);
911 if (NULL == remote_data_address) {
912 if (debug) {
913 fprintf(where,
914 "local_data_address not set, using local_host_name of '%s'\n",
915 local_host_name);
916 fflush(where);
917 }
918 strcpy(local_data_address,local_host_name);
919 }
920 else {
921 if (debug) {
922 fprintf(where,
923 "local_data_address not set, using address family info\n");
924 fflush(where);
925 }
926 /* by default, use 0.0.0.0 - assume IPv4 */
927 strcpy(local_data_address,"0.0.0.0");
928 #if defined(AF_INET6)
929 if ((AF_INET6 == local_data_family) ||
930 ((AF_UNSPEC == local_data_family) &&
931 (AF_INET6 == remote_data_family)) ||
932 ((AF_UNSPEC == local_data_family) &&
933 (AF_INET6 == (*remote)->ai_family))) {
934 strcpy(local_data_address,"::0");
935 }
936 #endif
937 }
938 }
939
940 *local = complete_addrinfo("what to put here?",
941 local_data_address,
942 local_data_port,
943 local_data_family,
944 type,
945 protocol,
946 flags|AI_PASSIVE);
947
948 /* OK, at this point, if remote_data_address is NULL, we know that
949 we used the value of remote_host (the control connection) for the
950 remote, which means we can/should set remote_data_address to
951 remote_host so the "omni" output routines can use that global
952 variable. at least i think I can get away with that :) I'm sure
953 that at some point I'll find-out that I need to allocate
954 something for it rather than mess with the pointers, but that can
955 wait. famous last words of raj 2008-01-25 */
956 if (remote_data_address == NULL)
957 remote_data_address = remote_host;
958 }
959
960 void
set_hostname_and_port(char * hostname,char * portstr,int family,int port)961 set_hostname_and_port(char *hostname, char *portstr, int family, int port)
962 {
963 strcpy(hostname,"0.0.0.0");
964 #if defined AF_INET6
965 if (AF_INET6 == family) {
966 strcpy(hostname,"::0");
967 }
968 #endif
969
970 sprintf(portstr, "%u", port);
971
972 }
973
974 static unsigned short
get_port_number(struct addrinfo * res)975 get_port_number(struct addrinfo *res)
976 {
977 switch(res->ai_family) {
978 case AF_INET: {
979 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
980 return(ntohs(foo->sin_port));
981 break;
982 }
983 #if defined(AF_INET6)
984 case AF_INET6: {
985 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
986 return(ntohs(foo->sin6_port));
987 break;
988 }
989 #endif
990 default:
991 fprintf(where,
992 "Given Unexpected Address Family of %u\n",res->ai_family);
993 fflush(where);
994 exit(-1);
995 }
996 }
997
998 static void
extract_inet_address_and_port(struct addrinfo * res,void * addr,int len,int * port)999 extract_inet_address_and_port(struct addrinfo *res, void *addr, int len, int *port)
1000 {
1001 switch(res->ai_family) {
1002 case AF_INET: {
1003 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
1004 *port = foo->sin_port;
1005 memcpy(addr,&(foo->sin_addr),min(len,sizeof(foo->sin_addr)));
1006 break;
1007 }
1008 #if defined(AF_INET6)
1009 case AF_INET6: {
1010 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
1011 *port = foo->sin6_port;
1012 memcpy(addr,&(foo->sin6_addr),min(len,sizeof(foo->sin6_addr)));
1013 break;
1014 }
1015 #endif
1016 default:
1017 *port = 0xDEADBEEF;
1018 strncpy(addr,"UNKN FAMILY",len);
1019 }
1020 }
1021
1022 /* this routine will set the port number of the sockaddr in the
1023 addrinfo to the specified value, based on the address family */
1024 void
set_port_number(struct addrinfo * res,unsigned short port)1025 set_port_number(struct addrinfo *res, unsigned short port)
1026 {
1027 switch(res->ai_family) {
1028 case AF_INET:
1029 #if defined(AF_RDS)
1030 case AF_RDS:
1031 #endif
1032 {
1033 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
1034 foo->sin_port = htons(port);
1035 break;
1036 }
1037 #if defined(AF_INET6)
1038 case AF_INET6: {
1039 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
1040 foo->sin6_port = htons(port);
1041 break;
1042 }
1043 #endif
1044 default:
1045 fprintf(where,
1046 "set_port_number Unexpected Address Family of %u\n",res->ai_family);
1047 fflush(where);
1048 exit(-1);
1049 }
1050 }
1051
1052 /* stuff the address family, port number and address into a
1053 sockaddr. for now, we will go ahead and zero-out the sockaddr
1054 first */
1055 void
set_sockaddr_family_addr_port(struct sockaddr_storage * sockaddr,int family,void * addr,int port)1056 set_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int port) {
1057
1058 memset(sockaddr,0,sizeof(struct sockaddr_storage));
1059
1060 switch (family) {
1061 #if defined(AF_RDS)
1062 case AF_RDS:
1063 #endif
1064 case AF_INET: {
1065 struct sockaddr_in *foo = (struct sockaddr_in *)sockaddr;
1066 foo->sin_port = htons((unsigned short) port);
1067 foo->sin_family = (unsigned short) family;
1068 memcpy(&(foo->sin_addr),addr,sizeof(foo->sin_addr));
1069 *(int *)addr = htonl(*(int *)addr);
1070 break;
1071 }
1072 #if defined(AF_INET6)
1073 case AF_INET6: {
1074 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)sockaddr;
1075 foo->sin6_port = htons((unsigned short) port);
1076 foo->sin6_family = (unsigned short) family;
1077 memcpy(&(foo->sin6_addr),addr,sizeof(foo->sin6_addr));
1078 break;
1079 }
1080 #endif
1081 default:
1082 fprintf(where,
1083 "set_sockaddr_family_addr_port Unexpected Address Family of %u\n",family);
1084 fflush(where);
1085 exit(-1);
1086 }
1087 }
1088
1089 /* pull the port and address out of the sockaddr in host format */
1090 int
get_sockaddr_family_addr_port(struct sockaddr_storage * sockaddr,int family,void * addr,int * port)1091 get_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int *port)
1092 {
1093 struct sockaddr_in *sin = (struct sockaddr_in *)sockaddr;
1094
1095 int ret = 0;
1096 if (sin->sin_family != family) {
1097 fprintf(where,
1098 "get_sockaddr_family_addr_port family mismatch %d vs %d\n",
1099 sin->sin_family,
1100 family);
1101 fflush(where);
1102 return -1;
1103 }
1104
1105 switch(family) {
1106 #if defined(AF_RDS)
1107 case AF_RDS:
1108 #endif
1109 case AF_INET: {
1110 *port = ntohs(sin->sin_port);
1111 memcpy(addr,&(sin->sin_addr),sizeof(sin->sin_addr));
1112 if (*(int *)addr == INADDR_ANY) ret = 1;
1113 *(int *)addr = ntohl(*(int *)addr);
1114 break;
1115 }
1116 #ifdef AF_INET6
1117 case AF_INET6: {
1118 int i;
1119 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sockaddr;
1120 *port = ntohs(sin6->sin6_port);
1121 ret = 1;
1122 for (i=0; i < sizeof(struct in6_addr); i++)
1123 if (sin6->sin6_addr.s6_addr[i] != 0) ret=0;
1124 memcpy(addr,&(sin6->sin6_addr), sizeof(sin6->sin6_addr));
1125 break;
1126 }
1127 #endif
1128 default:
1129 fprintf(where,
1130 "get_sockaddr_family_addr_port: Unexpected Address Family of %u\n",family);
1131 fflush(where);
1132 exit(-1);
1133 }
1134 return ret;
1135 }
1136
1137
1138 int
set_socket_tos(SOCKET sock,int family,int socket_tos)1139 set_socket_tos(SOCKET sock, int family, int socket_tos) {
1140
1141 int my_tos = -3;
1142 netperf_socklen_t sock_opt_len;
1143
1144 switch (family) {
1145 #if defined(IP_TOS)
1146 case AF_INET:
1147 /* should I mask-away anything above the byte? */
1148 my_tos = socket_tos;
1149 if (setsockopt(sock,
1150 IPPROTO_IP,
1151 IP_TOS,
1152 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) {
1153 fprintf(where,
1154 "%s ip_tos failed with %s (errno %d)\n",
1155 __FUNCTION__,
1156 strerror(errno),
1157 errno);
1158 fflush(where);
1159 my_tos = -2;
1160 }
1161 else {
1162 sock_opt_len = sizeof(my_tos);
1163 getsockopt(sock,
1164 IPPROTO_IP,
1165 IP_TOS,
1166 (char *)&my_tos,
1167 &sock_opt_len);
1168 }
1169 break;
1170 #endif
1171 #if defined(IPV6_TCLASS)
1172 case AF_INET6:
1173 /* should I mask-away anything above the byte? */
1174 my_tos = socket_tos;
1175 if (setsockopt(sock,
1176 IPPROTO_IPV6,
1177 IPV6_TCLASS,
1178 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) {
1179 fprintf(where,
1180 "%s ip_tos failed with %s (errno %d)\n",
1181 __FUNCTION__,
1182 strerror(errno),
1183 errno);
1184 fflush(where);
1185 my_tos = -2;
1186 }
1187 else {
1188 sock_opt_len = sizeof(my_tos);
1189 getsockopt(sock,
1190 IPPROTO_IPV6,
1191 IPV6_TCLASS,
1192 (char *)&my_tos,
1193 &sock_opt_len);
1194 }
1195 break;
1196 #endif
1197 }
1198 return my_tos;
1199 }
1200
1201
1202 /* This routine will create a data (listen) socket with the
1203 apropriate options set and return it to the caller. this replaces
1204 all the duplicate code in each of the test routines and should help
1205 make things a little easier to understand. since this routine can be
1206 called by either the netperf or netserver programs, all output
1207 should be directed towards "where." family is generally AF_INET and
1208 type will be either SOCK_STREAM or SOCK_DGRAM. This routine will
1209 also be used by the "SCTP" tests, hence the slightly strange-looking
1210 SCTP stuff in the classic bsd sockets test file... vlad/raj
1211 2005-03-15 */
1212
1213 SOCKET
create_data_socket(struct addrinfo * res)1214 create_data_socket(struct addrinfo *res)
1215 {
1216
1217 SOCKET temp_socket;
1218 int one = 1;
1219 int on = 1;
1220 netperf_socklen_t sock_opt_len;
1221
1222 /*set up the data socket */
1223 temp_socket = socket(res->ai_family,
1224 res->ai_socktype,
1225 res->ai_protocol);
1226
1227 if (temp_socket == INVALID_SOCKET){
1228 fprintf(where,
1229 "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n",
1230 errno,
1231 inet_ftos(res->ai_family),
1232 inet_ttos(res->ai_socktype),
1233 inet_ptos(res->ai_protocol),
1234 strerror(errno));
1235 fflush(where);
1236 exit(1);
1237 }
1238
1239 if (debug) {
1240 fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket);
1241 fflush(where);
1242 }
1243
1244 /* Modify the local socket size. The reason we alter the send buffer
1245 size here rather than when the connection is made is to take care
1246 of decreases in buffer size. Decreasing the window size after
1247 connection establishment is a TCP no-no. Also, by setting the
1248 buffer (window) size before the connection is established, we can
1249 control the TCP MSS (segment size). The MSS is never (well, should
1250 never be) more that 1/2 the minimum receive buffer size at each
1251 half of the connection. This is why we are altering the receive
1252 buffer size on the sending size of a unidirectional transfer. If
1253 the user has not requested that the socket buffers be altered, we
1254 will try to find-out what their values are. If we cannot touch the
1255 socket buffer in any way, we will set the values to -1 to indicate
1256 that. */
1257
1258 /* all the oogy nitty gritty stuff moved from here into the routine
1259 being called below, per patches from davidm to workaround the bug
1260 in Linux getsockopt(). raj 2004-06-15 */
1261 set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
1262 set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
1263
1264 /* now, we may wish to enable the copy avoidance features on the */
1265 /* local system. of course, this may not be possible... */
1266
1267 #ifdef SO_RCV_COPYAVOID
1268 /* this is ancient vestigial HP-UX code that should probably go away
1269 one day */
1270 if (loc_rcvavoid) {
1271 if (setsockopt(temp_socket,
1272 SOL_SOCKET,
1273 SO_RCV_COPYAVOID,
1274 (const char *)&loc_rcvavoid,
1275 sizeof(int)) == SOCKET_ERROR) {
1276 fprintf(where,
1277 "netperf: create_data_socket: Could not enable receive copy avoidance");
1278 fflush(where);
1279 loc_rcvavoid = 0;
1280 }
1281 }
1282 #endif
1283
1284 #ifdef SO_SND_COPYAVOID
1285 if (loc_sndavoid) {
1286 if (setsockopt(temp_socket,
1287 SOL_SOCKET,
1288 SO_SND_COPYAVOID,
1289 (const char *)&loc_sndavoid,
1290 sizeof(int)) == SOCKET_ERROR) {
1291 fprintf(where,
1292 "netperf: create_data_socket: Could not enable send copy avoidance");
1293 fflush(where);
1294 loc_sndavoid = 0;
1295 }
1296 }
1297 #endif
1298
1299 /* Now, we will see about setting the TCP_NODELAY flag on the local */
1300 /* socket. We will only do this for those systems that actually */
1301 /* support the option. If it fails, note the fact, but keep going. */
1302 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
1303 /* will cause an error to be displayed */
1304
1305 /* well..... long ago and far away that would have happened, in
1306 particular because we would always use IPPROTO_TCP here.
1307 however, now we are using res->ai_protocol, which will be
1308 IPPROT_UDP, and while HP-UX, and I suspect no-one else on the
1309 planet has a UDP_mumble option that overlaps with TCP_NODELAY,
1310 sure as knuth made little green programs, linux has a UDP_CORK
1311 option that is defined as a value of 1, which is the same a
1312 TCP_NODELAY under Linux. So, when asking for -D and
1313 "TCP_NODELAY" under Linux, we are actually setting UDP_CORK
1314 instead of getting an error like every other OS on the
1315 planet. joy and rupture. this stops a UDP_RR test cold sooo we
1316 have to make sure that res->ai_protocol actually makes sense for
1317 a _NODELAY setsockopt() or a UDP_RR test on Linux where someone
1318 mistakenly sets -D will hang. raj 2005-04-21 */
1319
1320 #if defined(TCP_NODELAY) || defined(SCTP_NODELAY)
1321 if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) {
1322
1323 /* strictly speaking, since the if defined above is an OR, we
1324 should probably check against TCP_NODELAY being defined here.
1325 however, the likelihood of SCTP_NODELAY being defined and
1326 TCP_NODELAY _NOT_ being defined is, probably :), epsilon. raj
1327 2005-03-15 */
1328
1329 int option = TCP_NODELAY;
1330
1331 /* I suspect that WANT_SCTP would suffice here since that is the
1332 only time we would have called getaddrinfo with a hints asking
1333 for SCTP, but just in case there is an SCTP implementation out
1334 there _without_ SCTP_NODELAY... raj 2005-03-15 */
1335 /* change this to IPPROTO_SCTP rather than WANT_SCTP to better fit
1336 with the modus operandi of the new "omni" tests. raj
1337 2008-02-04 */
1338 #if defined(IPPROTO_SCTP) && defined(SCTP_NODELAY)
1339 if (IPPROTO_SCTP == res->ai_protocol) {
1340 option = SCTP_NODELAY;
1341 }
1342 #endif
1343
1344 one = 1;
1345 if(setsockopt(temp_socket,
1346 res->ai_protocol,
1347 option,
1348 (char *)&one,
1349 sizeof(one)) == SOCKET_ERROR) {
1350 fprintf(where,
1351 "netperf: create_data_socket: nodelay: errno %d\n",
1352 errno);
1353 fflush(where);
1354 }
1355
1356 if (debug > 1) {
1357 fprintf(where,
1358 "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n");
1359 fflush(where);
1360 }
1361 }
1362 #else /* TCP_NODELAY */
1363
1364 loc_nodelay = 0;
1365
1366 #endif /* TCP_NODELAY */
1367
1368 if ((transport_mss_req != -1) && (IPPROTO_TCP == res->ai_protocol)) {
1369 set_tcp_mss(temp_socket,transport_mss_req);
1370 }
1371
1372 #if defined(TCP_CORK)
1373
1374 if (loc_tcpcork > 0) {
1375 /* the user wishes for us to set TCP_CORK on the socket */
1376 if (setsockopt(temp_socket,
1377 getprotobyname("tcp")->p_proto,
1378 TCP_CORK,
1379 (char *)&one,
1380 sizeof(one)) == SOCKET_ERROR) {
1381 perror("netperf: create_data_socket: tcp_cork");
1382 exit(1);
1383 }
1384 if (debug) {
1385 fprintf(where,"create_data_socket: tcp_cork...\n");
1386 }
1387 }
1388
1389 #endif /* TCP_CORK */
1390
1391 /* well, after Knuth only knows how many years, I have finally
1392 decided to enable setting SO_KEEPALIVE on the data socket. 99
1393 times out of 10 this should not be necessary, but that 100th time,
1394 perhaps when netperf is being (ab)used by functional testers, may
1395 benefit from it. And it may help clean-up some lingering
1396 netservers from time to time. raj 2011-06-29 */
1397
1398 #if defined(SO_KEEPALIVE)
1399
1400 if (want_keepalive) {
1401 if (setsockopt(temp_socket,
1402 SOL_SOCKET,
1403 SO_KEEPALIVE,
1404 (const char *)&on,
1405 sizeof(on)) < 0) {
1406 if (debug) {
1407 fprintf(where,
1408 "%s: unable to set SO_KEEPALIVE on data socket: %s (errno %d)\n",
1409 __FUNCTION__,
1410 strerror(errno),
1411 errno);
1412 fflush(where);
1413 }
1414 }
1415 }
1416
1417 #endif /* SO_KEEPALIVE */
1418
1419 /* since some of the UDP tests do not do anything to cause an
1420 implicit bind() call, we need to be rather explicit about our
1421 bind() call here. even if the address and/or the port are zero
1422 (INADDR_ANY etc). raj 2004-07-20 */
1423
1424 if (setsockopt(temp_socket,
1425 #ifdef IPPROTO_DCCP
1426 /* it is REALLY SILLY THAT THIS SHOULD BE NEEDED!! I
1427 should be able to use SOL_SOCKET for this just
1428 like TCP and SCTP */
1429 /* IT IS EVEN SILLIER THAT THERE COULD BE SYSTEMS
1430 WITH IPPROTO_DCCP and no SOL_DCCP */
1431 #ifndef SOL_DCCP
1432 #define SOL_DCCP SOL_SOCKET
1433 #define NETPERF_NEED_CLEANUP 1
1434 #endif
1435 (res->ai_protocol == IPPROTO_DCCP) ? SOL_DCCP : SOL_SOCKET,
1436 #ifdef NETPERF_NEED_CLEANUP
1437 #undef SOL_DCCP
1438 #undef NETPERF_NEED_CLEANUP
1439 #endif
1440
1441 #else
1442 SOL_SOCKET,
1443 #endif
1444 SO_REUSEADDR,
1445 (const char *)&on,
1446 sizeof(on)) < 0) {
1447 fprintf(where,
1448 "netperf: create_data_socket: SO_REUSEADDR failed %d\n",
1449 errno);
1450 fflush(where);
1451 }
1452
1453 /* bind only if we must */
1454 if ((get_port_number(res) != 0) ||
1455 (res->ai_protocol == IPPROTO_UDP)) {
1456 if (bind(temp_socket,
1457 res->ai_addr,
1458 res->ai_addrlen) < 0) {
1459 if (debug) {
1460 fprintf(where,
1461 "netperf: create_data_socket: data socket bind failed: %s (errno %d)\n",
1462 strerror(errno),
1463 errno);
1464 fprintf(where," port: %d\n",get_port_number(res));
1465 fflush(where);
1466 }
1467 }
1468 }
1469 /* this one is a slightly grudgingly added backside covering for
1470 those folks who (ab)use netperf as a functional testing tool, and
1471 further compound that error by running tests on systems also
1472 connected to their site networks, and then compound it even
1473 further compound it by running UDP_STREAM tests over links that
1474 generate link-down events and so cause the traffic to be sent out
1475 the default route into their corporate network... frankly such
1476 people should not be allowed to run netperf in the first place
1477 but there we are... raj 20091026 */
1478
1479 #if defined (SO_DONTROUTE)
1480 if (!routing_allowed) {
1481 if (setsockopt(temp_socket,
1482 SOL_SOCKET,
1483 SO_DONTROUTE,
1484 (char *)&one,
1485 sizeof(one)) == SOCKET_ERROR) {
1486 fprintf(where,
1487 "netperf: create_data_socket: so_dontroute: errno %d\n",
1488 errno);
1489 fflush(where);
1490 }
1491 }
1492 #endif
1493
1494 #if defined(SO_PRIORITY)
1495 if (local_socket_prio >= 0) {
1496 if (setsockopt(temp_socket,
1497 SOL_SOCKET,
1498 SO_PRIORITY,
1499 &local_socket_prio,
1500 sizeof(int)) == SOCKET_ERROR) {
1501 fprintf(where,
1502 "netperf: create_data_socket: so_priority: errno %d\n",
1503 errno);
1504 fflush(where);
1505 local_socket_prio = -2;
1506 }
1507 else {
1508 sock_opt_len = 4;
1509 getsockopt(temp_socket,
1510 SOL_SOCKET,
1511 SO_PRIORITY,
1512 &local_socket_prio,
1513 &sock_opt_len);
1514 }
1515 }
1516 #else
1517 local_socket_prio = -3;
1518 #endif
1519
1520 #if defined (IP_TOS) || defined(IPV6_TCLASS)
1521 if (local_socket_tos > 0)
1522 local_socket_tos = set_socket_tos(temp_socket,res->ai_family, local_socket_tos);
1523 #endif
1524
1525 /* some platforms can be told to set a rate on a socket */
1526 #ifndef SO_MAX_PACING_RATE
1527 #define SO_MAX_PACING_RATE 47
1528 #endif
1529
1530 if (pacing_rate > 0) {
1531 if (setsockopt(temp_socket, SOL_SOCKET, SO_MAX_PACING_RATE,
1532 &pacing_rate,
1533 sizeof(pacing_rate)) < 0) {
1534 fprintf(where, "netperf: setsockopt: SO_MAX_PACING_RATE: errno %d\n",
1535 errno);
1536 }
1537 }
1538
1539 return temp_socket;
1540 }
1541
1542 #ifdef KLUDGE_SOCKET_OPTIONS
1543
1544
1545 /* This routine is for those BROKEN systems which do not correctly */
1546 /* pass socket attributes through calls such as accept(). It should */
1547 /* only be called for those broken systems. I *really* don't want to */
1548 /* have this, but even broken systems must be measured. raj 11/95 */
1549 void
kludge_socket_options(int temp_socket)1550 kludge_socket_options(int temp_socket)
1551 {
1552
1553 set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
1554 set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
1555
1556 /* now, we may wish to enable the copy avoidance features on the */
1557 /* local system. of course, this may not be possible... */
1558 /* those calls were only valid for HP-UX, and I know that HP-UX is */
1559 /* written correctly, and so we do not need to include those calls */
1560 /* in this kludgy routine. raj 11/95 */
1561
1562
1563 /* Now, we will see about setting the TCP_NODELAY flag on the local */
1564 /* socket. We will only do this for those systems that actually */
1565 /* support the option. If it fails, note the fact, but keep going. */
1566 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
1567 /* will cause an error to be displayed */
1568
1569 #ifdef TCP_NODELAY
1570 if (loc_nodelay) {
1571 one = 1;
1572 if(setsockopt(temp_socket,
1573 getprotobyname("tcp")->p_proto,
1574 TCP_NODELAY,
1575 (char *)&one,
1576 sizeof(one)) == SOCKET_ERROR) {
1577 fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n",
1578 errno);
1579 fflush(where);
1580 }
1581
1582 if (debug > 1) {
1583 fprintf(where,
1584 "netperf: kludge_socket_options: TCP_NODELAY requested...\n");
1585 fflush(where);
1586 }
1587 }
1588 #else /* TCP_NODELAY */
1589
1590 loc_nodelay = 0;
1591
1592 #endif /* TCP_NODELAY */
1593
1594 }
1595
1596 #endif /* KLUDGE_SOCKET_OPTIONS */
1597
1598
1599 static void *
get_address_address(struct addrinfo * info)1600 get_address_address(struct addrinfo *info)
1601 {
1602 struct sockaddr_in *sin;
1603 #if defined(AF_INET6)
1604 struct sockaddr_in6 *sin6;
1605 #endif
1606
1607 switch(info->ai_family) {
1608 case AF_INET:
1609 sin = (struct sockaddr_in *)info->ai_addr;
1610 return(&(sin->sin_addr));
1611 break;
1612 #if defined(AF_INET6)
1613 case AF_INET6:
1614 sin6 = (struct sockaddr_in6 *)info->ai_addr;
1615 return(&(sin6->sin6_addr));
1616 break;
1617 #endif
1618 default:
1619 fprintf(stderr,"we never expected to get here in get_address_address\n");
1620 fflush(stderr);
1621 exit(-1);
1622 }
1623 }
1624
1625 #if defined(WIN32)
1626 #if !defined(InetNtop)
1627 /* +*+ Why isn't this in the winsock headers yet? */
1628 const char *
1629 inet_ntop(int af, const void *src, char *dst, size_t size);
1630 #endif
1631 #endif
1632
1633 /* This routine is a generic test header printer for the topmost header */
1634 void
print_top_test_header(char test_name[],struct addrinfo * source,struct addrinfo * destination)1635 print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination)
1636 {
1637
1638 char *address_buf;
1639
1640 #ifdef AF_INET6
1641 address_buf = malloc(INET6_ADDRSTRLEN);
1642 #else
1643 address_buf = malloc(16); /* magic constant */
1644 #endif
1645
1646 if (address_buf == NULL) {
1647 fprintf(where,"Unable to allocate address_buf\n");
1648 fflush(where);
1649 exit(1);
1650 }
1651
1652 /* we want to have some additional, interesting information in the
1653 headers. we know some of it here, but not all, so we will only
1654 print the test title here and will print the results titles after
1655 the test is finished */
1656 fprintf(where,"%s",test_name);
1657
1658 address_buf[0] = '\0';
1659 inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf));
1660 fprintf(where,
1661 " from %s (%s) port %u %s",
1662 source->ai_canonname,
1663 address_buf,
1664 get_port_number(source),
1665 inet_ftos(source->ai_family));
1666
1667 address_buf[0] = '\0';
1668 inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf));
1669 fprintf(where,
1670 " to %s (%s) port %u %s",
1671 destination->ai_canonname,
1672 address_buf,
1673 get_port_number(destination),
1674 inet_ftos(destination->ai_family));
1675
1676 if (iteration_max > 1) {
1677 fprintf(where,
1678 " : +/-%.3f%% @ %2d%% conf. %s",
1679 interval/0.02,
1680 confidence_level,
1681 result_confidence_only ? " on result only" : "");
1682 }
1683 if ((loc_nodelay > 0) || (rem_nodelay > 0)) {
1684 fprintf(where," : nodelay");
1685 }
1686 if ((loc_sndavoid > 0) ||
1687 (loc_rcvavoid > 0) ||
1688 (rem_sndavoid > 0) ||
1689 (rem_rcvavoid > 0)) {
1690 fprintf(where," : copy avoidance");
1691 }
1692
1693 if (no_control) {
1694 fprintf(where," : no control");
1695 }
1696
1697 #ifdef WANT_HISTOGRAM
1698 fprintf(where," : histogram");
1699 #endif /* WANT_HISTOGRAM */
1700
1701 #ifdef WANT_INTERVALS
1702 #ifndef WANT_SPIN
1703 fprintf(where," : interval");
1704 #else
1705 fprintf(where," : spin interval");
1706 #endif
1707 #endif /* WANT_INTERVALS */
1708
1709 #ifdef DIRTY
1710 fprintf(where," : dirty data");
1711 #endif /* DIRTY */
1712 #ifdef WANT_DEMO
1713 fprintf(where," : demo");
1714 #endif
1715 #ifdef WANT_FIRST_BURST
1716 /* a little hokey perhaps, but we really only want this to be
1717 emitted for tests where it actually is used, which means a
1718 "REQUEST/RESPONSE" test. raj 2005-11-10 */
1719 if (strstr(test_name,"REQUEST/RESPONSE")) {
1720 fprintf(where," : first burst %d",first_burst_size);
1721 }
1722 #endif
1723 if (cpu_binding_requested) {
1724 fprintf(where," : cpu bind");
1725 }
1726 fprintf(where,"\n");
1727
1728 free(address_buf);
1729 }
1730
1731 /* if WANT_MIGRATION is defined, we will use the send_tcp_stream()
1732 call in src/nettest_omni.c */
1733 #ifndef WANT_MIGRATION
1734
1735 /* This routine implements the TCP unidirectional data transfer test */
1736 /* (a.k.a. stream) for the sockets interface. It receives its */
1737 /* parameters via global variables from the shell and writes its */
1738 /* output to the standard output. */
1739
1740 void
send_tcp_stream(char remote_host[])1741 send_tcp_stream(char remote_host[])
1742 {
1743
1744 char *tput_title = "\
1745 Recv Send Send \n\
1746 Socket Socket Message Elapsed \n\
1747 Size Size Size Time Throughput \n\
1748 bytes bytes bytes secs. %s/sec \n\n";
1749
1750 char *tput_fmt_0 =
1751 "%7.2f %s\n";
1752
1753 char *tput_fmt_1 =
1754 "%6d %6d %6d %-6.2f %7.2f %s\n";
1755
1756 char *cpu_title = "\
1757 Recv Send Send Utilization Service Demand\n\
1758 Socket Socket Message Elapsed Send Recv Send Recv\n\
1759 Size Size Size Time Throughput local remote local remote\n\
1760 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
1761
1762 char *cpu_fmt_0 =
1763 "%6.3f %c %s\n";
1764
1765 char *cpu_fmt_1 =
1766 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
1767
1768 char *ksink_fmt = "\n\
1769 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
1770 Local Remote Local Remote Xfered Per Per\n\
1771 Send Recv Send Recv Send (avg) Recv (avg)\n\
1772 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
1773
1774 char *ksink_fmt2 = "\n\
1775 Maximum\n\
1776 Segment\n\
1777 Size (bytes)\n\
1778 %6d\n";
1779
1780
1781 float elapsed_time;
1782
1783 /* what we want is to have a buffer space that is at least one */
1784 /* send-size greater than our send window. this will insure that we */
1785 /* are never trying to re-use a buffer that may still be in the hands */
1786 /* of the transport. This buffer will be malloc'd after we have found */
1787 /* the size of the local senc socket buffer. We will want to deal */
1788 /* with alignment and offset concerns as well. */
1789
1790 struct ring_elt *send_ring;
1791
1792 int len;
1793 unsigned int nummessages = 0;
1794 SOCKET send_socket;
1795 int bytes_remaining;
1796 int tcp_mss = -1; /* possibly uninitialized on printf far below */
1797
1798 /* with links like fddi, one can send > 32 bits worth of bytes
1799 during a test... ;-) at some point, this should probably become a
1800 64bit integral type, but those are not entirely common
1801 yet... time passes, and 64 bit types do indeed become common. */
1802 #if defined(WIN32) && _MSC_VER <= 1200
1803 __int64 local_bytes_sent = 0;
1804 #else
1805 unsigned long long local_bytes_sent = 0;
1806 #endif
1807
1808 double bytes_sent = 0.0;
1809
1810 float local_cpu_utilization;
1811 float local_service_demand;
1812 float remote_cpu_utilization;
1813 float remote_service_demand;
1814
1815 double thruput;
1816
1817 struct addrinfo *remote_res;
1818 struct addrinfo *local_res;
1819
1820 struct tcp_stream_request_struct *tcp_stream_request;
1821 struct tcp_stream_response_struct *tcp_stream_response;
1822 struct tcp_stream_results_struct *tcp_stream_result;
1823
1824 tcp_stream_request =
1825 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
1826 tcp_stream_response =
1827 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
1828 tcp_stream_result =
1829 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
1830
1831 #ifdef WANT_HISTOGRAM
1832 if (verbosity > 1) {
1833 time_hist = HIST_new();
1834 }
1835 #endif /* WANT_HISTOGRAM */
1836 /* since we are now disconnected from the code that established the */
1837 /* control socket, and since we want to be able to use different */
1838 /* protocols and such, we are passed the name of the remote host and */
1839 /* must turn that into the test specific addressing information. */
1840
1841 /* complete_addrinfos will either succede or exit the process */
1842 complete_addrinfos(&remote_res,
1843 &local_res,
1844 remote_host,
1845 SOCK_STREAM,
1846 IPPROTO_TCP,
1847 0);
1848
1849 if ( print_headers ) {
1850 print_top_test_header("TCP STREAM TEST",local_res,remote_res);
1851 }
1852
1853 send_ring = NULL;
1854 confidence_iteration = 1;
1855 init_stat();
1856
1857 /* we have a great-big while loop which controls the number of times */
1858 /* we run a particular test. this is for the calculation of a */
1859 /* confidence interval (I really should have stayed awake during */
1860 /* probstats :). If the user did not request confidence measurement */
1861 /* (no confidence is the default) then we will only go though the */
1862 /* loop once. the confidence stuff originates from the folks at IBM */
1863
1864 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
1865 (confidence_iteration <= iteration_min)) {
1866
1867 /* initialize a few counters. we have to remember that we might be */
1868 /* going through the loop more than once. */
1869
1870 nummessages = 0;
1871 bytes_sent = 0.0;
1872 times_up = 0;
1873
1874 /*set up the data socket */
1875 send_socket = create_data_socket(local_res);
1876
1877 if (send_socket == INVALID_SOCKET){
1878 perror("netperf: send_tcp_stream: tcp stream data socket");
1879 exit(1);
1880 }
1881
1882 if (debug) {
1883 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
1884 }
1885
1886 /* at this point, we have either retrieved the socket buffer sizes, */
1887 /* or have tried to set them, so now, we may want to set the send */
1888 /* size based on that (because the user either did not use a -m */
1889 /* option, or used one with an argument of 0). If the socket buffer */
1890 /* size is not available, we will set the send size to 4KB - no */
1891 /* particular reason, just arbitrary... */
1892 if (send_size == 0) {
1893 if (lss_size > 0) {
1894 send_size = lss_size;
1895 }
1896 else {
1897 send_size = 4096;
1898 }
1899 }
1900
1901 /* set-up the data buffer ring with the requested alignment and offset. */
1902 /* note also that we have allocated a quantity */
1903 /* of memory that is at least one send-size greater than our socket */
1904 /* buffer size. We want to be sure that there are at least two */
1905 /* buffers allocated - this can be a bit of a problem when the */
1906 /* send_size is bigger than the socket size, so we must check... the */
1907 /* user may have wanted to explicitly set the "width" of our send */
1908 /* buffers, we should respect that wish... */
1909 if (send_width == 0) {
1910 send_width = (lss_size/send_size) + 1;
1911 if (send_width == 1) send_width++;
1912 }
1913
1914 if (send_ring == NULL) {
1915 /* only allocate the send ring once. this is a networking test, */
1916 /* not a memory allocation test. this way, we do not need a */
1917 /* deallocate_buffer_ring() routine, and I don't feel like */
1918 /* writing one anyway :) raj 11/94 */
1919 send_ring = allocate_buffer_ring(send_width,
1920 send_size,
1921 local_send_align,
1922 local_send_offset);
1923 }
1924
1925 /* If the user has requested cpu utilization measurements, we must */
1926 /* calibrate the cpu(s). We will perform this task within the tests */
1927 /* themselves. If the user has specified the cpu rate, then */
1928 /* calibrate_local_cpu will return rather quickly as it will have */
1929 /* nothing to do. If local_cpu_rate is zero, then we will go through */
1930 /* all the "normal" calibration stuff and return the rate back. */
1931
1932 if (local_cpu_usage) {
1933 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1934 }
1935
1936 if (!no_control) {
1937 /* Tell the remote end to do a listen. The server alters the
1938 socket paramters on the other side at this point, hence the
1939 reason for all the values being passed in the setup
1940 message. If the user did not specify any of the parameters,
1941 they will be passed as 0, which will indicate to the remote
1942 that no changes beyond the system's default should be
1943 used. Alignment is the exception, it will default to 1, which
1944 will be no alignment alterations. */
1945
1946 netperf_request.content.request_type = DO_TCP_STREAM;
1947 tcp_stream_request->send_buf_size = rss_size_req;
1948 tcp_stream_request->recv_buf_size = rsr_size_req;
1949 tcp_stream_request->receive_size = recv_size;
1950 tcp_stream_request->no_delay = rem_nodelay;
1951 tcp_stream_request->recv_alignment = remote_recv_align;
1952 tcp_stream_request->recv_offset = remote_recv_offset;
1953 tcp_stream_request->measure_cpu = remote_cpu_usage;
1954 tcp_stream_request->cpu_rate = remote_cpu_rate;
1955 if (test_time) {
1956 tcp_stream_request->test_length = test_time;
1957 }
1958 else {
1959 tcp_stream_request->test_length = test_bytes;
1960 }
1961 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
1962 tcp_stream_request->so_sndavoid = rem_sndavoid;
1963 #ifdef DIRTY
1964 tcp_stream_request->dirty_count = rem_dirty_count;
1965 tcp_stream_request->clean_count = rem_clean_count;
1966 #endif /* DIRTY */
1967 tcp_stream_request->port = atoi(remote_data_port);
1968 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
1969 tcp_stream_request->recv_aio = rem_rcvaio;
1970 if (debug > 1) {
1971 fprintf(where,
1972 "netperf: send_tcp_stream: requesting TCP stream test\n");
1973 }
1974
1975 send_request();
1976
1977 /* The response from the remote will contain all of the relevant
1978 socket parameters for this test type. We will put them back
1979 into the variables here so they can be displayed if desired.
1980 The remote will have calibrated CPU if necessary, and will
1981 have done all the needed set-up we will have calibrated the
1982 cpu locally before sending the request, and will grab the
1983 counter value right after the connect returns. The remote
1984 will grab the counter right after the accept call. This saves
1985 the hassle of extra messages being sent for the TCP
1986 tests. */
1987
1988 recv_response();
1989
1990 if (!netperf_response.content.serv_errno) {
1991 if (debug)
1992 fprintf(where,"remote listen done.\n");
1993 rsr_size = tcp_stream_response->recv_buf_size;
1994 rss_size = tcp_stream_response->send_buf_size;
1995 rem_nodelay = tcp_stream_response->no_delay;
1996 remote_cpu_usage= tcp_stream_response->measure_cpu;
1997 remote_cpu_rate = tcp_stream_response->cpu_rate;
1998
1999 /* we have to make sure that the server port number is in
2000 network order */
2001 set_port_number(remote_res,
2002 (short)tcp_stream_response->data_port_number);
2003
2004 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
2005 rem_sndavoid = tcp_stream_response->so_sndavoid;
2006 }
2007 else {
2008 Set_errno(netperf_response.content.serv_errno);
2009 fprintf(where,
2010 "netperf: remote error %d",
2011 netperf_response.content.serv_errno);
2012 perror("");
2013 fflush(where);
2014
2015 exit(1);
2016 }
2017 }
2018
2019 #ifdef WANT_DEMO
2020 demo_stream_setup(lss_size,rsr_size);
2021 #endif
2022
2023 /*Connect up to the remote port on the data socket */
2024 if (connect(send_socket,
2025 remote_res->ai_addr,
2026 remote_res->ai_addrlen) == INVALID_SOCKET){
2027 perror("netperf: send_tcp_stream: data socket connect failed");
2028 exit(1);
2029 }
2030
2031 #ifdef WIN32
2032 /* this is used so the timer thread can close the socket out from */
2033 /* under us, which to date is the easiest/cleanest/least */
2034 /* Windows-specific way I can find to force the winsock calls to */
2035 /* return WSAEINTR with the test is over. anything that will run on */
2036 /* 95 and NT and is closer to what netperf expects from Unix signals */
2037 /* and such would be appreciated raj 1/96 */
2038 win_kludge_socket = send_socket;
2039 #endif /* WIN32 */
2040
2041 /* Data Socket set-up is finished. If there were problems, either */
2042 /* the connect would have failed, or the previous response would */
2043 /* have indicated a problem. I failed to see the value of the */
2044 /* extra message after the accept on the remote. If it failed, */
2045 /* we'll see it here. If it didn't, we might as well start pumping */
2046 /* data. */
2047
2048 /* Set-up the test end conditions. For a stream test, they can be */
2049 /* either time or byte-count based. */
2050
2051 if (test_time) {
2052 /* The user wanted to end the test after a period of time. */
2053 times_up = 0;
2054 bytes_remaining = 0;
2055 /* in previous revisions, we had the same code repeated throught */
2056 /* all the test suites. this was unnecessary, and meant more */
2057 /* work for me when I wanted to switch to POSIX signals, so I */
2058 /* have abstracted this out into a routine in netlib.c. if you */
2059 /* are experiencing signal problems, you might want to look */
2060 /* there. raj 11/94 */
2061 start_timer(test_time);
2062 }
2063 else {
2064 /* The tester wanted to send a number of bytes. */
2065 bytes_remaining = test_bytes;
2066 times_up = 1;
2067 }
2068
2069 /* The cpu_start routine will grab the current time and possibly */
2070 /* value of the idle counter for later use in measuring cpu */
2071 /* utilization and/or service demand and thruput. */
2072
2073 cpu_start(local_cpu_usage);
2074
2075 /* we only start the interval timer if we are using the
2076 timer-timed intervals rather than the sit and spin ones. raj
2077 2006-02-06 */
2078 #if defined(WANT_INTERVALS)
2079 INTERVALS_INIT();
2080 #endif /* WANT_INTERVALS */
2081
2082 /* before we start, initialize a few variables */
2083
2084 #ifdef WANT_DEMO
2085 if (demo_mode) {
2086 demo_first_timestamp();
2087 }
2088 #endif
2089
2090
2091 /* We use an "OR" to control test execution. When the test is */
2092 /* controlled by time, the byte count check will always return false. */
2093 /* When the test is controlled by byte count, the time test will */
2094 /* always return false. When the test is finished, the whole */
2095 /* expression will go false and we will stop sending data. */
2096
2097 while ((!times_up) || (bytes_remaining > 0)) {
2098
2099 #if HAVE_AIO
2100 /* When using aio, wait for the previous write for this buffer to
2101 complete. */
2102 if (loc_sndaio > 0 && send_ring->completion_ptr != NULL) {
2103 const struct aiocb *iocblist[1];
2104 struct aiocb *iocb;
2105 int error;
2106
2107 iocb = send_ring->completion_ptr;
2108 iocblist[0] = iocb;
2109 if (aio_suspend(iocblist, 1, NULL) == -1) {
2110 if (errno == EINTR) {
2111 /* the test was interrupted, must be the end of test */
2112 break;
2113 }
2114 perror("netperf: data send error");
2115 exit(1);
2116 }
2117
2118 error = aio_error(iocb);
2119 if (error == 0)
2120 len = aio_return(iocb);
2121 else {
2122 len = SOCKET_ERROR;
2123 errno = error;
2124 }
2125 }
2126 #endif
2127
2128 #ifdef DIRTY
2129 access_buffer(send_ring->buffer_ptr,
2130 send_size,
2131 loc_dirty_count,
2132 loc_clean_count);
2133 #endif /* DIRTY */
2134
2135 #ifdef WANT_HISTOGRAM
2136 if (verbosity > 1) {
2137 /* timestamp just before we go into send and then again just
2138 after we come out raj 8/94 */
2139 /* but lets only do this if there is going to be a histogram
2140 displayed */
2141 HIST_timestamp(&time_one);
2142 }
2143 #endif /* WANT_HISTOGRAM */
2144
2145 #if HAVE_AIO
2146 if (loc_sndaio > 0) {
2147 struct aiocb *iocb, *old;
2148
2149 old = iocb = send_ring->completion_ptr;
2150 if (iocb == NULL) {
2151 iocb = calloc(1, sizeof(*iocb));
2152 send_ring->completion_ptr = iocb;
2153 } else
2154 memset(iocb, 0, sizeof(*iocb));
2155 iocb->aio_nbytes = send_size;
2156 iocb->aio_fildes = send_socket;
2157 iocb->aio_buf = send_ring->buffer_ptr;
2158 if (aio_write(iocb) == -1) {
2159 if (errno == EINTR) {
2160 /* the test was interrupted, must be the end of test */
2161 /* clear the completion pointer to avoid trying to cancel it */
2162 send_ring->completion_ptr = NULL;
2163 send_ring = send_ring->next;
2164 break;
2165 }
2166 perror("netperf: data send error");
2167 exit(1);
2168 }
2169 if (old == NULL)
2170 /* No previous write was completed. */
2171 goto next_buffer;
2172 } else
2173 #endif
2174 len = send(send_socket,
2175 send_ring->buffer_ptr,
2176 send_size,
2177 0);
2178
2179 if(len != send_size) {
2180 if ((len >=0) || SOCKET_EINTR(len)) {
2181 /* the test was interrupted, must be the end of test */
2182 break;
2183 }
2184 perror("netperf: data send error");
2185 printf("len was %d\n",len);
2186 exit(1);
2187 }
2188
2189 local_bytes_sent += send_size;
2190
2191 #if HAVE_AIO
2192 next_buffer:
2193 #endif
2194
2195 #ifdef WANT_HISTOGRAM
2196 if (verbosity > 1) {
2197 /* timestamp the exit from the send call and update the histogram */
2198 HIST_timestamp(&time_two);
2199 HIST_add(time_hist,delta_micro(&time_one,&time_two));
2200 }
2201 #endif /* WANT_HISTOGRAM */
2202
2203 #ifdef WANT_DEMO
2204 demo_stream_interval(send_size);
2205 #endif
2206
2207 #if defined(WANT_INTERVALS)
2208 INTERVALS_WAIT();
2209 #endif /* WANT_INTERVALS */
2210
2211 /* now we want to move our pointer to the next position in the */
2212 /* data buffer...we may also want to wrap back to the "beginning" */
2213 /* of the bufferspace, so we will mod the number of messages sent */
2214 /* by the send width, and use that to calculate the offset to add */
2215 /* to the base pointer. */
2216 nummessages++;
2217 send_ring = send_ring->next;
2218 if (bytes_remaining) {
2219 bytes_remaining -= send_size;
2220 }
2221 }
2222
2223 /* The test is over. Flush the buffers to the remote end. We do a */
2224 /* graceful release to insure that all data has been taken by the */
2225 /* remote. */
2226
2227 #if HAVE_AIO
2228 if (loc_sndaio > 0) {
2229 const struct aiocb *iocblist[1];
2230 struct ring_elt *send_ring2;
2231 struct aiocb *iocb;
2232 int error;
2233
2234 send_ring2 = send_ring;
2235 while (send_ring2->completion_ptr != NULL) {
2236 if (aio_cancel(send_socket, send_ring2->completion_ptr) == -1) {
2237 perror("netperf: data send error");
2238 exit(1);
2239 }
2240 send_ring2 = send_ring2->next;
2241 if (send_ring2 == send_ring)
2242 break;
2243 }
2244
2245 while (send_ring->completion_ptr != NULL) {
2246 iocb = send_ring->completion_ptr;
2247 iocblist[0] = iocb;
2248 if (aio_suspend(iocblist, 1, NULL) == -1) {
2249 perror("netperf: data send error");
2250 exit(1);
2251 }
2252
2253 error = aio_error(iocb);
2254 if (error == 0)
2255 local_bytes_sent += aio_return(iocb);
2256 else if (error != ECANCELED) {
2257 errno = error;
2258 perror("netperf: data send error");
2259 exit(1);
2260 }
2261 send_ring->completion_ptr = NULL;
2262 send_ring = send_ring->next;
2263 free(iocb);
2264 }
2265 }
2266 #endif
2267
2268 /* but first, if the verbosity is greater than 1, find-out what */
2269 /* the TCP maximum segment_size was (if possible) */
2270 if (verbosity > 1) {
2271 tcp_mss = -1;
2272 get_tcp_info(send_socket,&tcp_mss);
2273 }
2274
2275 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR && !times_up) {
2276 perror("netperf: cannot shutdown tcp stream socket");
2277 exit(1);
2278 }
2279
2280 /* hang a recv() off the socket to block until the remote has */
2281 /* brought all the data up into the application. it will do a */
2282 /* shutdown to cause a FIN to be sent our way. We will assume that */
2283 /* any exit from the recv() call is good... raj 4/93 */
2284
2285 recv(send_socket, send_ring->buffer_ptr, send_size, 0);
2286
2287 /* this call will always give us the elapsed time for the test, and */
2288 /* will also store-away the necessaries for cpu utilization */
2289
2290 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
2291 /* measured and how */
2292 /* long did we really */
2293 /* run? */
2294
2295 /* we are finished with the socket, so close it to prevent hitting */
2296 /* the limit on maximum open files. */
2297
2298 close(send_socket);
2299
2300 #if defined(WANT_INTERVALS)
2301 #ifdef WIN32
2302 stop_itimer();
2303 #endif
2304 #endif /* WANT_INTERVALS */
2305
2306 if (!no_control) {
2307 /* Get the statistics from the remote end. The remote will have
2308 calculated service demand and all those interesting
2309 things. If it wasn't supposed to care, it will return obvious
2310 values. */
2311
2312 recv_response();
2313 if (!netperf_response.content.serv_errno) {
2314 if (debug)
2315 fprintf(where,
2316 "remote reporting results for %.2f seconds\n",
2317 tcp_stream_result->elapsed_time);
2318 }
2319 else {
2320 Set_errno(netperf_response.content.serv_errno);
2321 fprintf(where,
2322 "netperf: remote error %d",
2323 netperf_response.content.serv_errno);
2324 perror("");
2325 fflush(where);
2326
2327 exit(1);
2328 }
2329
2330 /* We now calculate what our thruput was for the test. In the
2331 future, we may want to include a calculation of the thruput
2332 measured by the remote, but it should be the case that for a
2333 TCP stream test, that the two numbers should be *very*
2334 close... We calculate bytes_sent regardless of the way the
2335 test length was controlled. If it was time, we needed to,
2336 and if it was by bytes, the user may have specified a number
2337 of bytes that wasn't a multiple of the send_size, so we
2338 really didn't send what he asked for ;-) */
2339
2340 bytes_sent = ntohd(tcp_stream_result->bytes_received);
2341 }
2342 else {
2343 bytes_sent = (double)local_bytes_sent;
2344 }
2345
2346 thruput = calc_thruput(bytes_sent);
2347
2348 if (local_cpu_usage || remote_cpu_usage) {
2349 /* We must now do a little math for service demand and cpu */
2350 /* utilization for the system(s) */
2351 /* Of course, some of the information might be bogus because */
2352 /* there was no idle counter in the kernel(s). We need to make */
2353 /* a note of this for the user's benefit...*/
2354 if (local_cpu_usage) {
2355
2356 local_cpu_utilization = calc_cpu_util(0.0);
2357 local_service_demand = calc_service_demand(bytes_sent,
2358 0.0,
2359 0.0,
2360 0);
2361 }
2362 else {
2363 local_cpu_utilization = (float) -1.0;
2364 local_service_demand = (float) -1.0;
2365 }
2366
2367 if (remote_cpu_usage) {
2368
2369 remote_cpu_utilization = tcp_stream_result->cpu_util;
2370 remote_service_demand = calc_service_demand(bytes_sent,
2371 0.0,
2372 remote_cpu_utilization,
2373 tcp_stream_result->num_cpus);
2374 }
2375 else {
2376 remote_cpu_utilization = (float) -1.0;
2377 remote_service_demand = (float) -1.0;
2378 }
2379 }
2380 else {
2381 /* we were not measuring cpu, for the confidence stuff, we */
2382 /* should make it -1.0 */
2383 local_cpu_utilization = (float) -1.0;
2384 local_service_demand = (float) -1.0;
2385 remote_cpu_utilization = (float) -1.0;
2386 remote_service_demand = (float) -1.0;
2387 }
2388
2389 /* at this point, we want to calculate the confidence information. */
2390 /* if debugging is on, calculate_confidence will print-out the */
2391 /* parameters we pass it */
2392
2393 calculate_confidence(confidence_iteration,
2394 elapsed_time,
2395 thruput,
2396 local_cpu_utilization,
2397 remote_cpu_utilization,
2398 local_service_demand,
2399 remote_service_demand);
2400
2401
2402 confidence_iteration++;
2403 }
2404
2405 /* at this point, we have finished making all the runs that we */
2406 /* will be making. so, we should extract what the calcuated values */
2407 /* are for all the confidence stuff. we could make the values */
2408 /* global, but that seemed a little messy, and it did not seem worth */
2409 /* all the mucking with header files. so, we create a routine much */
2410 /* like calcualte_confidence, which just returns the mean values. */
2411 /* raj 11/94 */
2412
2413 retrieve_confident_values(&elapsed_time,
2414 &thruput,
2415 &local_cpu_utilization,
2416 &remote_cpu_utilization,
2417 &local_service_demand,
2418 &remote_service_demand);
2419
2420 /* We are now ready to print all the information. If the user */
2421 /* has specified zero-level verbosity, we will just print the */
2422 /* local service demand, or the remote service demand. If the */
2423 /* user has requested verbosity level 1, he will get the basic */
2424 /* "streamperf" numbers. If the user has specified a verbosity */
2425 /* of greater than 1, we will display a veritable plethora of */
2426 /* background information from outside of this block as it it */
2427 /* not cpu_measurement specific... */
2428
2429 if (confidence < 0) {
2430 /* we did not hit confidence, but were we asked to look for it? */
2431 if (iteration_max > 1) {
2432 display_confidence();
2433 }
2434 }
2435
2436 if (local_cpu_usage || remote_cpu_usage) {
2437 local_cpu_method = format_cpu_method(cpu_method);
2438 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
2439
2440 switch (verbosity) {
2441 case 0:
2442 if (local_cpu_usage) {
2443 fprintf(where,
2444 cpu_fmt_0,
2445 local_service_demand,
2446 local_cpu_method,
2447 ((print_headers) ||
2448 (result_brand == NULL)) ? "" : result_brand);
2449 }
2450 else {
2451 fprintf(where,
2452 cpu_fmt_0,
2453 remote_service_demand,
2454 remote_cpu_method,
2455 ((print_headers) ||
2456 (result_brand == NULL)) ? "" : result_brand);
2457 }
2458 break;
2459 case 1:
2460 case 2:
2461 if (print_headers) {
2462 fprintf(where,
2463 cpu_title,
2464 format_units(),
2465 local_cpu_method,
2466 remote_cpu_method);
2467 }
2468
2469 fprintf(where,
2470 cpu_fmt_1, /* the format string */
2471 rsr_size, /* remote recvbuf size */
2472 lss_size, /* local sendbuf size */
2473 send_size, /* how large were the sends */
2474 elapsed_time, /* how long was the test */
2475 thruput, /* what was the xfer rate */
2476 local_cpu_utilization, /* local cpu */
2477 remote_cpu_utilization, /* remote cpu */
2478 local_service_demand, /* local service demand */
2479 remote_service_demand, /* remote service demand */
2480 ((print_headers) ||
2481 (result_brand == NULL)) ? "" : result_brand);
2482 break;
2483 }
2484 }
2485 else {
2486 /* The tester did not wish to measure service demand. */
2487
2488 switch (verbosity) {
2489 case 0:
2490 fprintf(where,
2491 tput_fmt_0,
2492 thruput,
2493 ((print_headers) ||
2494 (result_brand == NULL)) ? "" : result_brand);
2495 break;
2496 case 1:
2497 case 2:
2498 if (print_headers) {
2499 fprintf(where,tput_title,format_units());
2500 }
2501 fprintf(where,
2502 tput_fmt_1, /* the format string */
2503 rsr_size, /* remote recvbuf size */
2504 lss_size, /* local sendbuf size */
2505 send_size, /* how large were the sends */
2506 elapsed_time, /* how long did it take */
2507 thruput, /* how fast did it go */
2508 ((print_headers) ||
2509 (result_brand == NULL)) ? "" : result_brand);
2510 break;
2511 }
2512 }
2513
2514 /* it would be a good thing to include information about some of the */
2515 /* other parameters that may have been set for this test, but at the */
2516 /* moment, I do not wish to figure-out all the formatting, so I will */
2517 /* just put this comment here to help remind me that it is something */
2518 /* that should be done at a later time. */
2519
2520 if (verbosity > 1) {
2521 /* The user wanted to know it all, so we will give it to him. */
2522 /* This information will include as much as we can find about */
2523 /* TCP statistics, the alignments of the sends and receives */
2524 /* and all that sort of rot... */
2525
2526 /* this stuff needs to be worked-out in the presence of confidence */
2527 /* intervals and multiple iterations of the test... raj 11/94 */
2528
2529 fprintf(where,
2530 ksink_fmt,
2531 "Bytes",
2532 "Bytes",
2533 "Bytes",
2534 local_send_align,
2535 remote_recv_align,
2536 local_send_offset,
2537 remote_recv_offset,
2538 bytes_sent,
2539 bytes_sent / (double)nummessages,
2540 nummessages,
2541 bytes_sent / (double)tcp_stream_result->recv_calls,
2542 tcp_stream_result->recv_calls);
2543 fprintf(where,
2544 ksink_fmt2,
2545 tcp_mss);
2546 fflush(where);
2547 #ifdef WANT_HISTOGRAM
2548 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
2549 fflush(where);
2550 HIST_report(time_hist);
2551 #endif /* WANT_HISTOGRAM */
2552 }
2553
2554 }
2555
2556
2557
2558 /* This routine implements the netperf-side TCP unidirectional data
2559 transfer test (a.k.a. stream) for the sockets interface where the
2560 data flow is from the netserver to the netperf. It receives its
2561 parameters via global variables from the shell and writes its
2562 output to the standard output. */
2563
2564
2565 void
send_tcp_maerts(char remote_host[])2566 send_tcp_maerts(char remote_host[])
2567 {
2568
2569 char *tput_title = "\
2570 Recv Send Send \n\
2571 Socket Socket Message Elapsed \n\
2572 Size Size Size Time Throughput \n\
2573 bytes bytes bytes secs. %s/sec \n\n";
2574
2575 char *tput_fmt_0 =
2576 "%7.2f %s\n";
2577
2578 char *tput_fmt_1 =
2579 "%6d %6d %6d %-6.2f %7.2f %s\n";
2580
2581 char *cpu_title = "\
2582 Recv Send Send Utilization Service Demand\n\
2583 Socket Socket Message Elapsed Recv Send Recv Send\n\
2584 Size Size Size Time Throughput local remote local remote\n\
2585 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
2586
2587 char *cpu_fmt_0 =
2588 "%6.3f %c %s\n";
2589
2590 char *cpu_fmt_1 =
2591 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
2592
2593 char *ksink_fmt = "\n\
2594 Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\
2595 Local Remote Local Remote Xfered Per Per\n\
2596 Recv Send Recv Send Recv (avg) Send (avg)\n\
2597 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
2598
2599 char *ksink_fmt2 = "\n\
2600 Maximum\n\
2601 Segment\n\
2602 Size (bytes)\n\
2603 %6d\n";
2604
2605
2606 float elapsed_time;
2607
2608 /* what we want is to have a buffer space that is at least one */
2609 /* recv-size greater than our recv window. this will insure that we */
2610 /* are never trying to re-use a buffer that may still be in the hands */
2611 /* of the transport. This buffer will be malloc'd after we have found */
2612 /* the size of the local senc socket buffer. We will want to deal */
2613 /* with alignment and offset concerns as well. */
2614
2615 struct ring_elt *recv_ring;
2616
2617 int len;
2618 unsigned int nummessages = 0;
2619 SOCKET recv_socket;
2620 int bytes_remaining;
2621 int tcp_mss = -1; /* possibly uninitialized on printf far below */
2622
2623 /* with links like fddi, one can recv > 32 bits worth of bytes
2624 during a test... ;-) at some point, this should probably become a
2625 64bit integral type, but those are not entirely common yet. of
2626 course, time passes and they do become common.
2627 */
2628 double bytes_sent = 0.0;
2629
2630 #if defined(WIN32) && (_MSC_VER < 1200)
2631 __int64 local_bytes_recvd = 0;
2632 #else
2633 unsigned long long local_bytes_recvd = 0;
2634 #endif
2635
2636 float local_cpu_utilization;
2637 float local_service_demand;
2638 float remote_cpu_utilization;
2639 float remote_service_demand;
2640
2641 double thruput;
2642
2643 struct addrinfo *remote_res;
2644 struct addrinfo *local_res;
2645
2646 struct tcp_maerts_request_struct *tcp_maerts_request;
2647 struct tcp_maerts_response_struct *tcp_maerts_response;
2648 struct tcp_maerts_results_struct *tcp_maerts_result;
2649
2650 tcp_maerts_request =
2651 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
2652 tcp_maerts_response =
2653 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
2654 tcp_maerts_result =
2655 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
2656
2657 #ifdef WANT_HISTOGRAM
2658 if (verbosity > 1) {
2659 time_hist = HIST_new();
2660 }
2661 #endif /* WANT_HISTOGRAM */
2662 /* since we are now disconnected from the code that established the */
2663 /* control socket, and since we want to be able to use different */
2664 /* protocols and such, we are passed the name of the remote host and */
2665 /* must turn that into the test specific addressing information. */
2666
2667 complete_addrinfos(&remote_res,
2668 &local_res,
2669 remote_host,
2670 SOCK_STREAM,
2671 IPPROTO_TCP,
2672 0);
2673
2674 if ( print_headers ) {
2675 print_top_test_header("TCP MAERTS TEST",local_res,remote_res);
2676 }
2677
2678 recv_ring = NULL;
2679 confidence_iteration = 1;
2680 init_stat();
2681
2682 /* we have a great-big while loop which controls the number of times */
2683 /* we run a particular test. this is for the calculation of a */
2684 /* confidence interval (I really should have stayed awake during */
2685 /* probstats :). If the user did not request confidence measurement */
2686 /* (no confidence is the default) then we will only go though the */
2687 /* loop once. the confidence stuff originates from the folks at IBM */
2688
2689 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2690 (confidence_iteration <= iteration_min)) {
2691
2692 /* initialize a few counters. we have to remember that we might be */
2693 /* going through the loop more than once. */
2694
2695 nummessages = 0;
2696 bytes_sent = 0.0;
2697 times_up = 0;
2698
2699 /*set up the data socket */
2700 recv_socket = create_data_socket(local_res);
2701
2702 if (recv_socket == INVALID_SOCKET){
2703 perror("netperf: send_tcp_maerts: tcp stream data socket");
2704 exit(1);
2705 }
2706
2707 if (debug) {
2708 fprintf(where,"send_tcp_maerts: recv_socket obtained...\n");
2709 }
2710
2711 /* at this point, we have either retrieved the socket buffer sizes, */
2712 /* or have tried to set them, so now, we may want to set the recv */
2713 /* size based on that (because the user either did not use a -m */
2714 /* option, or used one with an argument of 0). If the socket buffer */
2715 /* size is not available, we will set the recv size to 4KB - no */
2716 /* particular reason, just arbitrary... */
2717 if (recv_size == 0) {
2718 if (lsr_size > 0) {
2719 recv_size = lsr_size;
2720 }
2721 else {
2722 recv_size = 4096;
2723 }
2724 }
2725
2726 /* set-up the data buffer ring with the requested alignment and offset. */
2727 /* note also that we have allocated a quantity */
2728 /* of memory that is at least one recv-size greater than our socket */
2729 /* buffer size. We want to be sure that there are at least two */
2730 /* buffers allocated - this can be a bit of a problem when the */
2731 /* recv_size is bigger than the socket size, so we must check... the */
2732 /* user may have wanted to explicitly set the "width" of our recv */
2733 /* buffers, we should respect that wish... */
2734 if (recv_width == 0) {
2735 recv_width = (lsr_size/recv_size) + 1;
2736 if (recv_width == 1) recv_width++;
2737 }
2738
2739 if (recv_ring == NULL) {
2740 /* only allocate the recv ring once. this is a networking test, */
2741 /* not a memory allocation test. this way, we do not need a */
2742 /* deallocate_buffer_ring() routine, and I don't feel like */
2743 /* writing one anyway :) raj 11/94 */
2744 recv_ring = allocate_buffer_ring(recv_width,
2745 recv_size,
2746 local_recv_align,
2747 local_recv_offset);
2748 }
2749
2750 /* If the user has requested cpu utilization measurements, we must */
2751 /* calibrate the cpu(s). We will perform this task within the tests */
2752 /* themselves. If the user has specified the cpu rate, then */
2753 /* calibrate_local_cpu will return rather quickly as it will have */
2754 /* nothing to do. If local_cpu_rate is zero, then we will go through */
2755 /* all the "normal" calibration stuff and return the rate back. */
2756
2757 if (local_cpu_usage) {
2758 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2759 }
2760
2761 if (!no_control) {
2762 /* Tell the remote end to do a listen. The server alters the
2763 socket paramters on the other side at this point, hence the
2764 reason for all the values being passed in the setup
2765 message. If the user did not specify any of the parameters,
2766 they will be passed as 0, which will indicate to the remote
2767 that no changes beyond the system's default should be
2768 used. Alignment is the exception, it will default to 1, which
2769 will be no alignment alterations. */
2770
2771 netperf_request.content.request_type = DO_TCP_MAERTS;
2772 tcp_maerts_request->send_buf_size = rss_size_req;
2773 tcp_maerts_request->recv_buf_size = rsr_size_req;
2774 tcp_maerts_request->send_size = send_size;
2775 tcp_maerts_request->no_delay = rem_nodelay;
2776 tcp_maerts_request->send_alignment = remote_send_align;
2777 tcp_maerts_request->send_offset = remote_send_offset;
2778 tcp_maerts_request->measure_cpu = remote_cpu_usage;
2779 tcp_maerts_request->cpu_rate = remote_cpu_rate;
2780 if (test_time) {
2781 tcp_maerts_request->test_length = test_time;
2782 }
2783 else {
2784 tcp_maerts_request->test_length = test_bytes;
2785 }
2786 tcp_maerts_request->so_rcvavoid = rem_rcvavoid;
2787 tcp_maerts_request->so_sndavoid = rem_sndavoid;
2788 #ifdef DIRTY
2789 tcp_maerts_request->dirty_count = rem_dirty_count;
2790 tcp_maerts_request->clean_count = rem_clean_count;
2791 #endif /* DIRTY */
2792 tcp_maerts_request->port = atoi(remote_data_port);
2793 tcp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family);
2794 if (debug > 1) {
2795 fprintf(where,
2796 "netperf: send_tcp_maerts: requesting TCP maerts test\n");
2797 }
2798
2799 send_request();
2800
2801 /* The response from the remote will contain all of the relevant
2802 socket parameters for this test type. We will put them back
2803 into the variables here so they can be displayed if desired.
2804 The remote will have calibrated CPU if necessary, and will
2805 have done all the needed set-up we will have calibrated the
2806 cpu locally before sending the request, and will grab the
2807 counter value right after the connect returns. The remote
2808 will grab the counter right after the accept call. This saves
2809 the hassle of extra messages being sent for the TCP
2810 tests. */
2811
2812 recv_response();
2813
2814 if (!netperf_response.content.serv_errno) {
2815 if (debug)
2816 fprintf(where,"remote listen done.\n");
2817 rsr_size = tcp_maerts_response->recv_buf_size;
2818 rss_size = tcp_maerts_response->send_buf_size;
2819 rem_nodelay = tcp_maerts_response->no_delay;
2820 remote_cpu_usage= tcp_maerts_response->measure_cpu;
2821 remote_cpu_rate = tcp_maerts_response->cpu_rate;
2822 send_size = tcp_maerts_response->send_size;
2823
2824 /* we have to make sure that the server port number is in
2825 network order */
2826 set_port_number(remote_res,
2827 (short)tcp_maerts_response->data_port_number);
2828 rem_rcvavoid = tcp_maerts_response->so_rcvavoid;
2829 rem_sndavoid = tcp_maerts_response->so_sndavoid;
2830 }
2831 else {
2832 Set_errno(netperf_response.content.serv_errno);
2833 fprintf(where,
2834 "netperf: remote error %d",
2835 netperf_response.content.serv_errno);
2836 perror("");
2837 fflush(where);
2838
2839 exit(1);
2840 }
2841 }
2842
2843 #ifdef WANT_DEMO
2844 demo_stream_setup(lsr_size,rss_size);
2845 #endif
2846
2847 /*Connect up to the remote port on the data socket */
2848 if (connect(recv_socket,
2849 remote_res->ai_addr,
2850 remote_res->ai_addrlen) == INVALID_SOCKET){
2851 perror("netperf: send_tcp_maerts: data socket connect failed");
2852 exit(1);
2853 }
2854
2855 #ifdef WIN32
2856 /* this is used so the timer thread can close the socket out from */
2857 /* under us, which to date is the easiest/cleanest/least */
2858 /* Windows-specific way I can find to force the winsock calls to */
2859 /* return WSAEINTR with the test is over. anything that will run on */
2860 /* 95 and NT and is closer to what netperf expects from Unix signals */
2861 /* and such would be appreciated raj 1/96 */
2862 win_kludge_socket = recv_socket;
2863 #endif /* WIN32 */
2864
2865 /* Data Socket set-up is finished. If there were problems, either */
2866 /* the connect would have failed, or the previous response would */
2867 /* have indicated a problem. I failed to see the value of the */
2868 /* extra message after the accept on the remote. If it failed, */
2869 /* we'll see it here. If it didn't, we might as well start pumping */
2870 /* data. */
2871
2872 /* Set-up the test end conditions. For a maerts test, they can be */
2873 /* either time or byte-count based. */
2874
2875 if (test_time) {
2876 /* The user wanted to end the test after a period of time. */
2877 times_up = 0;
2878 bytes_remaining = 0;
2879 /* in previous revisions, we had the same code repeated throught */
2880 /* all the test suites. this was unnecessary, and meant more */
2881 /* work for me when I wanted to switch to POSIX signals, so I */
2882 /* have abstracted this out into a routine in netlib.c. if you */
2883 /* are experiencing signal problems, you might want to look */
2884 /* there. raj 11/94 */
2885 if (!no_control) {
2886 /* this is a netperf to netserver test, netserver will close
2887 to tell us the test is over, so use PAD_TIME to avoid
2888 causing the netserver fits. */
2889 start_timer(test_time + PAD_TIME);
2890 }
2891 else {
2892 /* this is a netperf to data source test, no PAD_TIME */
2893 start_timer(test_time);
2894 }
2895 }
2896 else {
2897 /* The tester wanted to recv a number of bytes. we don't do that
2898 in a TCP_MAERTS test. sorry. raj 2002-06-21 */
2899 printf("netperf: send_tcp_maerts: test must be timed\n");
2900 exit(1);
2901 }
2902
2903 /* The cpu_start routine will grab the current time and possibly */
2904 /* value of the idle counter for later use in measuring cpu */
2905 /* utilization and/or service demand and thruput. */
2906
2907 cpu_start(local_cpu_usage);
2908
2909 #ifdef WANT_INTERVALS
2910 INTERVALS_INIT();
2911 #endif /* WANT_INTERVALS */
2912
2913 /* before we start, initialize a few variables */
2914
2915 #ifdef WANT_DEMO
2916 if (demo_mode) {
2917 demo_first_timestamp();
2918 }
2919 #endif
2920
2921 /* the test will continue until we either get a zero-byte recv()
2922 on the socket or our failsafe timer expires. most of the time
2923 we trust that we get a zero-byte recieve from the socket. raj
2924 2002-06-21 */
2925
2926 #ifdef WANT_HISTOGRAM
2927 if (verbosity > 1) {
2928 /* timestamp just before we go into recv and then again just
2929 after we come out raj 8/94 */
2930 /* but only if we are actually going to display a histogram. raj
2931 2006-02-07 */
2932 HIST_timestamp(&time_one);
2933 }
2934 #endif /* WANT_HISTOGRAM */
2935
2936 while ((!times_up) && (len=recv(recv_socket,
2937 recv_ring->buffer_ptr,
2938 recv_size,
2939 0)) > 0 ) {
2940
2941 #ifdef WANT_HISTOGRAM
2942 if (verbosity > 1) {
2943 /* timestamp the exit from the recv call and update the histogram */
2944 HIST_timestamp(&time_two);
2945 HIST_add(time_hist,delta_micro(&time_one,&time_two));
2946 }
2947 #endif /* WANT_HISTOGRAM */
2948
2949 #ifdef DIRTY
2950 access_buffer(recv_ring->buffer_ptr,
2951 recv_size,
2952 loc_dirty_count,
2953 loc_clean_count);
2954 #endif /* DIRTY */
2955
2956 #ifdef WANT_DEMO
2957 demo_stream_interval(len);
2958 #endif
2959
2960 #ifdef WANT_INTERVALS
2961 INTERVALS_WAIT();
2962 #endif /* WANT_INTERVALS */
2963
2964 /* now we want to move our pointer to the next position in the */
2965 /* data buffer...we may also want to wrap back to the "beginning" */
2966 /* of the bufferspace, so we will mod the number of messages sent */
2967 /* by the recv width, and use that to calculate the offset to add */
2968 /* to the base pointer. */
2969 nummessages++;
2970 recv_ring = recv_ring->next;
2971 if (bytes_remaining) {
2972 bytes_remaining -= len;
2973 }
2974
2975 local_bytes_recvd += len;
2976
2977 #ifdef WANT_HISTOGRAM
2978 if (verbosity > 1) {
2979 /* make sure we timestamp just before we go into recv */
2980 /* raj 2004-06-15 */
2981 HIST_timestamp(&time_one);
2982 }
2983 #endif /* WANT_HISTOGRAM */
2984
2985 }
2986
2987 /* an EINTR is to be expected when this is a no_control test */
2988 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
2989 perror("send_tcp_maerts: data recv error");
2990 printf("len was %d\n",len);
2991 exit(1);
2992 }
2993
2994 /* if we get here, it must mean we had a recv return of 0 before
2995 the watchdog timer expired, or the watchdog timer expired and
2996 this was a no_control test */
2997
2998 /* The test is over. Flush the buffers to the remote end. We do a
2999 graceful release to tell the remote we have all the data. */
3000
3001 /* but first, if the verbosity is greater than 1, find-out what */
3002 /* the TCP maximum segment_size was (if possible) */
3003 if (verbosity > 1) {
3004 tcp_mss = -1;
3005 get_tcp_info(recv_socket,&tcp_mss);
3006 }
3007
3008 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
3009 perror("netperf: cannot shutdown tcp maerts socket");
3010 exit(1);
3011 }
3012
3013 stop_timer();
3014
3015 #if defined(WANT_INTERVALS)
3016 #ifdef WIN32
3017 stop_itimer();
3018 #endif
3019 #endif /* WANT_INTERVALS */
3020
3021 /* this call will always give us the local elapsed time for the
3022 test, and will also store-away the necessaries for cpu
3023 utilization */
3024
3025 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
3026 /* measured and how */
3027 /* long did we really */
3028 /* run? */
3029
3030 /* we are finished with the socket, so close it to prevent hitting */
3031 /* the limit on maximum open files. */
3032
3033 close(recv_socket);
3034
3035 if (!no_control) {
3036 /* Get the statistics from the remote end. The remote will have
3037 calculated service demand and all those interesting
3038 things. If it wasn't supposed to care, it will return obvious
3039 values. */
3040
3041 recv_response();
3042 if (!netperf_response.content.serv_errno) {
3043 if (debug)
3044 fprintf(where,"remote results obtained\n");
3045 }
3046 else {
3047 Set_errno(netperf_response.content.serv_errno);
3048 fprintf(where,
3049 "netperf: remote error %d",
3050 netperf_response.content.serv_errno);
3051 perror("");
3052 fflush(where);
3053
3054 exit(1);
3055 }
3056
3057 /* We now calculate what our thruput was for the test. In the
3058 future, we may want to include a calculation of the thruput
3059 measured by the remote, but it should be the case that for a
3060 TCP maerts test, that the two numbers should be *very*
3061 close... We calculate bytes_sent regardless of the way the
3062 test length was controlled. If it was time, we needed to,
3063 and if it was by bytes, the user may have specified a number
3064 of bytes that wasn't a multiple of the recv_size, so we
3065 really didn't recv what he asked for ;-) */
3066
3067 bytes_sent = ntohd(tcp_maerts_result->bytes_sent);
3068 }
3069 else {
3070 bytes_sent = (double)local_bytes_recvd;
3071 }
3072
3073
3074 thruput = calc_thruput(bytes_sent);
3075
3076 if (local_cpu_usage || remote_cpu_usage) {
3077 /* We must now do a little math for service demand and cpu */
3078 /* utilization for the system(s) */
3079 /* Of course, some of the information might be bogus because */
3080 /* there was no idle counter in the kernel(s). We need to make */
3081 /* a note of this for the user's benefit...*/
3082 if (local_cpu_usage) {
3083
3084 local_cpu_utilization = calc_cpu_util(0.0);
3085 local_service_demand = calc_service_demand(bytes_sent,
3086 0.0,
3087 0.0,
3088 0);
3089 }
3090 else {
3091 local_cpu_utilization = (float) -1.0;
3092 local_service_demand = (float) -1.0;
3093 }
3094
3095 if (remote_cpu_usage) {
3096
3097 remote_cpu_utilization = tcp_maerts_result->cpu_util;
3098 remote_service_demand = calc_service_demand(bytes_sent,
3099 0.0,
3100 remote_cpu_utilization,
3101 tcp_maerts_result->num_cpus);
3102 }
3103 else {
3104 remote_cpu_utilization = (float) -1.0;
3105 remote_service_demand = (float) -1.0;
3106 }
3107 }
3108 else {
3109 /* we were not measuring cpu, for the confidence stuff, we */
3110 /* should make it -1.0 */
3111 local_cpu_utilization = (float) -1.0;
3112 local_service_demand = (float) -1.0;
3113 remote_cpu_utilization = (float) -1.0;
3114 remote_service_demand = (float) -1.0;
3115 }
3116
3117 /* at this point, we want to calculate the confidence information. */
3118 /* if debugging is on, calculate_confidence will print-out the */
3119 /* parameters we pass it */
3120
3121 calculate_confidence(confidence_iteration,
3122 elapsed_time,
3123 thruput,
3124 local_cpu_utilization,
3125 remote_cpu_utilization,
3126 local_service_demand,
3127 remote_service_demand);
3128
3129
3130 confidence_iteration++;
3131 }
3132
3133 /* at this point, we have finished making all the runs that we */
3134 /* will be making. so, we should extract what the calcuated values */
3135 /* are for all the confidence stuff. we could make the values */
3136 /* global, but that seemed a little messy, and it did not seem worth */
3137 /* all the mucking with header files. so, we create a routine much */
3138 /* like calcualte_confidence, which just returns the mean values. */
3139 /* raj 11/94 */
3140
3141 retrieve_confident_values(&elapsed_time,
3142 &thruput,
3143 &local_cpu_utilization,
3144 &remote_cpu_utilization,
3145 &local_service_demand,
3146 &remote_service_demand);
3147
3148 /* We are now ready to print all the information. If the user */
3149 /* has specified zero-level verbosity, we will just print the */
3150 /* local service demand, or the remote service demand. If the */
3151 /* user has requested verbosity level 1, he will get the basic */
3152 /* "streamperf" numbers. If the user has specified a verbosity */
3153 /* of greater than 1, we will display a veritable plethora of */
3154 /* background information from outside of this block as it it */
3155 /* not cpu_measurement specific... */
3156
3157 if (confidence < 0) {
3158 /* we did not hit confidence, but were we asked to look for it? */
3159 if (iteration_max > 1) {
3160 display_confidence();
3161 }
3162 }
3163
3164 if (local_cpu_usage || remote_cpu_usage) {
3165 local_cpu_method = format_cpu_method(cpu_method);
3166 remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method);
3167
3168 switch (verbosity) {
3169 case 0:
3170 if (local_cpu_usage) {
3171 fprintf(where,
3172 cpu_fmt_0,
3173 local_service_demand,
3174 local_cpu_method,
3175 ((print_headers) ||
3176 (result_brand == NULL)) ? "" : result_brand);
3177 }
3178 else {
3179 fprintf(where,
3180 cpu_fmt_0,
3181 remote_service_demand,
3182 remote_cpu_method,
3183 ((print_headers) ||
3184 (result_brand == NULL)) ? "" : result_brand);
3185 }
3186 break;
3187 case 1:
3188 case 2:
3189 if (print_headers) {
3190 fprintf(where,
3191 cpu_title,
3192 format_units(),
3193 local_cpu_method,
3194 remote_cpu_method);
3195 }
3196
3197 fprintf(where,
3198 cpu_fmt_1, /* the format string */
3199 rsr_size, /* remote recvbuf size */
3200 lss_size, /* local sendbuf size */
3201 send_size, /* how large were the recvs */
3202 elapsed_time, /* how long was the test */
3203 thruput, /* what was the xfer rate */
3204 local_cpu_utilization, /* local cpu */
3205 remote_cpu_utilization, /* remote cpu */
3206 local_service_demand, /* local service demand */
3207 remote_service_demand, /* remote service demand */
3208 ((print_headers) ||
3209 (result_brand == NULL)) ? "" : result_brand);
3210 break;
3211 }
3212 }
3213 else {
3214 /* The tester did not wish to measure service demand. */
3215
3216 switch (verbosity) {
3217 case 0:
3218 fprintf(where,
3219 tput_fmt_0,
3220 thruput,
3221 ((print_headers) ||
3222 (result_brand == NULL)) ? "" : result_brand);
3223 break;
3224 case 1:
3225 case 2:
3226 if (print_headers) {
3227 fprintf(where,tput_title,format_units());
3228 }
3229 fprintf(where,
3230 tput_fmt_1, /* the format string */
3231 lsr_size, /* local recvbuf size */
3232 rss_size, /* remot sendbuf size */
3233 send_size, /* how large were the recvs */
3234 elapsed_time, /* how long did it take */
3235 thruput, /* how fast did it go */
3236 ((print_headers) ||
3237 (result_brand == NULL)) ? "" : result_brand);
3238 break;
3239 }
3240 }
3241
3242 /* it would be a good thing to include information about some of the */
3243 /* other parameters that may have been set for this test, but at the */
3244 /* moment, I do not wish to figure-out all the formatting, so I will */
3245 /* just put this comment here to help remind me that it is something */
3246 /* that should be done at a later time. */
3247
3248 if (verbosity > 1) {
3249 /* The user wanted to know it all, so we will give it to him. */
3250 /* This information will include as much as we can find about */
3251 /* TCP statistics, the alignments of the sends and receives */
3252 /* and all that sort of rot... */
3253
3254 /* this stuff needs to be worked-out in the presence of confidence */
3255 /* intervals and multiple iterations of the test... raj 11/94 */
3256
3257 fprintf(where,
3258 ksink_fmt,
3259 "Bytes",
3260 "Bytes",
3261 "Bytes",
3262 local_recv_align,
3263 remote_recv_align,
3264 local_recv_offset,
3265 remote_recv_offset,
3266 bytes_sent,
3267 bytes_sent / (double)nummessages,
3268 nummessages,
3269 bytes_sent / (double)tcp_maerts_result->send_calls,
3270 tcp_maerts_result->send_calls);
3271 fprintf(where,
3272 ksink_fmt2,
3273 tcp_mss);
3274 fflush(where);
3275 #ifdef WANT_HISTOGRAM
3276 fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
3277 fflush(where);
3278 HIST_report(time_hist);
3279 #endif /* WANT_HISTOGRAM */
3280 }
3281
3282 }
3283 #endif /* WANT_MIGRATION */
3284
3285
3286 /* this routine implements the TCP_MSS test. All it does is pretend
3287 to be a TCP_STREAM test and report the TCP_MSS for the data
3288 connection. No actual data is transferred. raj 2007-11-07
3289 */
3290 void
send_tcp_mss(char remote_host[])3291 send_tcp_mss(char remote_host[])
3292 {
3293
3294 char *mss_title = "\
3295 Maximum\n\
3296 Segment\n\
3297 Size (bytes)\n\n";
3298
3299 char *mss_fmt_0 =
3300 "%d %s\n";
3301
3302 SOCKET send_socket;
3303 int tcp_mss = -1; /* possibly uninitialized on printf far below */
3304
3305 struct addrinfo *remote_res;
3306 struct addrinfo *local_res;
3307
3308 struct tcp_stream_request_struct *tcp_stream_request;
3309 struct tcp_stream_response_struct *tcp_stream_response;
3310 struct tcp_stream_results_struct *tcp_stream_result;
3311
3312 tcp_stream_request =
3313 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
3314 tcp_stream_response =
3315 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
3316 tcp_stream_result =
3317 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
3318
3319 /* since we are now disconnected from the code that established the */
3320 /* control socket, and since we want to be able to use different */
3321 /* protocols and such, we are passed the name of the remote host and */
3322 /* must turn that into the test specific addressing information. */
3323
3324 /* complete_addrinfos will either succede or exit the process */
3325 complete_addrinfos(&remote_res,
3326 &local_res,
3327 remote_host,
3328 SOCK_STREAM,
3329 IPPROTO_TCP,
3330 0);
3331
3332 if ( print_headers ) {
3333 print_top_test_header("TCP MSS TEST",local_res,remote_res);
3334 }
3335
3336 /*set up the data socket */
3337 send_socket = create_data_socket(local_res);
3338
3339 if (send_socket == INVALID_SOCKET){
3340 perror("netperf: send_tcp_stream: tcp stream data socket");
3341 exit(1);
3342 }
3343
3344 if (debug) {
3345 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
3346 }
3347
3348
3349 if (!no_control) {
3350 /* Tell the remote end to do a listen. The server alters the
3351 socket paramters on the other side at this point, hence the
3352 reason for all the values being passed in the setup
3353 message. If the user did not specify any of the parameters,
3354 they will be passed as 0, which will indicate to the remote
3355 that no changes beyond the system's default should be
3356 used. Alignment is the exception, it will default to 1, which
3357 will be no alignment alterations. */
3358
3359 netperf_request.content.request_type = DO_TCP_STREAM;
3360 tcp_stream_request->send_buf_size = rss_size_req;
3361 tcp_stream_request->recv_buf_size = rsr_size_req;
3362 tcp_stream_request->receive_size = recv_size;
3363 tcp_stream_request->no_delay = rem_nodelay;
3364 tcp_stream_request->recv_alignment = remote_recv_align;
3365 tcp_stream_request->recv_offset = remote_recv_offset;
3366 tcp_stream_request->measure_cpu = remote_cpu_usage;
3367 tcp_stream_request->cpu_rate = remote_cpu_rate;
3368 if (test_time) {
3369 tcp_stream_request->test_length = test_time;
3370 }
3371 else {
3372 tcp_stream_request->test_length = test_bytes;
3373 }
3374 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
3375 tcp_stream_request->so_sndavoid = rem_sndavoid;
3376 #ifdef DIRTY
3377 tcp_stream_request->dirty_count = rem_dirty_count;
3378 tcp_stream_request->clean_count = rem_clean_count;
3379 #endif /* DIRTY */
3380 tcp_stream_request->port = atoi(remote_data_port);
3381 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
3382 tcp_stream_request->recv_aio = rem_rcvaio;
3383 if (debug > 1) {
3384 fprintf(where,
3385 "netperf: send_tcp_mss: requesting TCP stream test\n");
3386 }
3387
3388 send_request();
3389
3390 /* The response from the remote will contain all of the relevant
3391 socket parameters for this test type. We will put them back
3392 into the variables here so they can be displayed if desired.
3393 The remote will have calibrated CPU if necessary, and will
3394 have done all the needed set-up we will have calibrated the
3395 cpu locally before sending the request, and will grab the
3396 counter value right after the connect returns. The remote
3397 will grab the counter right after the accept call. This saves
3398 the hassle of extra messages being sent for the TCP
3399 tests. */
3400
3401 recv_response();
3402
3403 if (!netperf_response.content.serv_errno) {
3404 if (debug)
3405 fprintf(where,"remote listen done.\n");
3406 rsr_size = tcp_stream_response->recv_buf_size;
3407 rss_size = tcp_stream_response->send_buf_size;
3408 rem_nodelay = tcp_stream_response->no_delay;
3409 remote_cpu_usage= tcp_stream_response->measure_cpu;
3410 remote_cpu_rate = tcp_stream_response->cpu_rate;
3411
3412 /* we have to make sure that the server port number is in
3413 network order */
3414 set_port_number(remote_res,
3415 (short)tcp_stream_response->data_port_number);
3416
3417 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
3418 rem_sndavoid = tcp_stream_response->so_sndavoid;
3419 }
3420 else {
3421 Set_errno(netperf_response.content.serv_errno);
3422 fprintf(where,
3423 "netperf: remote error %d",
3424 netperf_response.content.serv_errno);
3425 perror("");
3426 fflush(where);
3427
3428 exit(1);
3429 }
3430 }
3431
3432 /*Connect up to the remote port on the data socket */
3433 if (connect(send_socket,
3434 remote_res->ai_addr,
3435 remote_res->ai_addrlen) == INVALID_SOCKET){
3436 perror("netperf: send_tcp_mss: data socket connect failed");
3437 exit(1);
3438 }
3439
3440
3441 /* find-out what the TCP maximum segment_size was (if possible) */
3442 tcp_mss = -1;
3443 get_tcp_info(send_socket,&tcp_mss);
3444
3445 /* just go ahead and close the socket, the remote should figure it
3446 out */
3447 close(send_socket);
3448
3449 /* statistics? we don't need no stinking statistics */
3450
3451
3452 switch (verbosity) {
3453 case 0:
3454 fprintf(where,
3455 mss_fmt_0,
3456 tcp_mss,
3457 ((print_headers) ||
3458 (result_brand == NULL)) ? "" : result_brand);
3459 break;
3460 case 1:
3461 case 2:
3462 if (print_headers) {
3463 fprintf(where,"%s",mss_title);
3464 }
3465 fprintf(where,
3466 mss_fmt_0, /* the format string */
3467 tcp_mss,
3468 ((print_headers) ||
3469 (result_brand == NULL)) ? "" : result_brand);
3470 break;
3471 }
3472
3473
3474 }
3475
3476
3477
3478 #ifdef HAVE_ICSC_EXS
3479
3480 #include <sys/exs.h>
3481
3482
3483 /* This routine implements the TCP unidirectional data transfer test */
3484 /* (a.k.a. stream) for the sockets interface. It receives its */
3485 /* parameters via global variables from the shell and writes its */
3486 /* output to the standard output. */
3487
3488 void
send_exs_tcp_stream(char remote_host[])3489 send_exs_tcp_stream(char remote_host[])
3490 {
3491
3492 char *tput_title = "\
3493 Recv Send Send \n\
3494 Socket Socket Message Elapsed \n\
3495 Size Size Size Time Throughput \n\
3496 bytes bytes bytes secs. %s/sec \n\n";
3497
3498 char *tput_fmt_0 =
3499 "%7.2f\n";
3500
3501 char *tput_fmt_1 =
3502 "%6d %6d %6d %-6.2f %7.2f \n";
3503
3504 char *cpu_title = "\
3505 Recv Send Send Utilization Service Demand\n\
3506 Socket Socket Message Elapsed Send Recv Send Recv\n\
3507 Size Size Size Time Throughput local remote local remote\n\
3508 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
3509
3510 char *cpu_fmt_0 =
3511 "%6.3f %c\n";
3512
3513 char *cpu_fmt_1 =
3514 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
3515
3516 char *ksink_fmt = "\n\
3517 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
3518 Local Remote Local Remote Xfered Per Per\n\
3519 Send Recv Send Recv Send (avg) Recv (avg)\n\
3520 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
3521
3522 char *ksink_fmt2 = "\n\
3523 Maximum\n\
3524 Segment\n\
3525 Size (bytes)\n\
3526 %6d\n";
3527
3528
3529 float elapsed_time;
3530
3531 /* what we want is to have a buffer space that is at least one */
3532 /* send-size greater than our send window. this will insure that we */
3533 /* are never trying to re-use a buffer that may still be in the hands */
3534 /* of the transport. This buffer will be malloc'd after we have found */
3535 /* the size of the local senc socket buffer. We will want to deal */
3536 /* with alignment and offset concerns as well. */
3537
3538 struct ring_elt *send_ring;
3539
3540 int len;
3541 unsigned int nummessages = 0;
3542 SOCKET send_socket;
3543 int bytes_remaining;
3544 int tcp_mss = -1; /* possibly uninitialized on printf far below */
3545
3546 exs_mhandle_t exs_mhandle;
3547 exs_qhandle_t exs_qhandle;
3548 #define NETPERF_EXS_PENDING 16
3549 int exs_aio_pending;
3550 int exs_aio_eagain;
3551 int exs_aio_dequeued;
3552 int exs_aio_dequeuecnt;
3553 int exs_evtcnt;
3554 #define NETPERF_EXS_QSIZE 128
3555 exs_event_t exs_evtvec[NETPERF_EXS_QSIZE];
3556
3557 /* with links like fddi, one can send > 32 bits worth of bytes */
3558 /* during a test... ;-) at some point, this should probably become a */
3559 /* 64bit integral type, but those are not entirely common yet */
3560
3561 double bytes_sent = 0.0;
3562
3563 float local_cpu_utilization;
3564 float local_service_demand;
3565 float remote_cpu_utilization;
3566 float remote_service_demand;
3567
3568 double thruput;
3569
3570 struct addrinfo *remote_res;
3571 struct addrinfo *local_res;
3572
3573 struct tcp_stream_request_struct *tcp_stream_request;
3574 struct tcp_stream_response_struct *tcp_stream_response;
3575 struct tcp_stream_results_struct *tcp_stream_result;
3576
3577 tcp_stream_request =
3578 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
3579 tcp_stream_response =
3580 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
3581 tcp_stream_result =
3582 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
3583
3584 #if 0 /* def WANT_HISTOGRAM */
3585 time_hist = HIST_new();
3586 #endif /* WANT_HISTOGRAM */
3587 /* since we are now disconnected from the code that established the */
3588 /* control socket, and since we want to be able to use different */
3589 /* protocols and such, we are passed the name of the remote host and */
3590 /* must turn that into the test specific addressing information. */
3591
3592 /* complete_addrinfos will either succede or exit the process */
3593 complete_addrinfos(&remote_res,
3594 &local_res,
3595 remote_host,
3596 SOCK_STREAM,
3597 IPPROTO_TCP,
3598 0);
3599
3600 if ( print_headers ) {
3601 print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res);
3602 }
3603
3604 send_ring = NULL;
3605 confidence_iteration = 1;
3606 init_stat();
3607
3608 /* initialize EXS API and create event queue */
3609 if (exs_init (EXS_VERSION) == -1) {
3610 perror ("netperf: send_exs_tcp_stream: exs_init failed");
3611 exit (1);
3612 }
3613
3614 if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) {
3615 perror ("netperf: send_exs_tcp_stream: exs_qcreate failed");
3616 exit (1);
3617 }
3618 if (debug) {
3619 fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle);
3620 }
3621
3622 /* we have a great-big while loop which controls the number of times */
3623 /* we run a particular test. this is for the calculation of a */
3624 /* confidence interval (I really should have stayed awake during */
3625 /* probstats :). If the user did not request confidence measurement */
3626 /* (no confidence is the default) then we will only go though the */
3627 /* loop once. the confidence stuff originates from the folks at IBM */
3628
3629 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
3630 (confidence_iteration <= iteration_min)) {
3631
3632 /* initialize a few counters. we have to remember that we might be */
3633 /* going through the loop more than once. */
3634
3635 nummessages = 0;
3636 bytes_sent = 0.0;
3637 times_up = 0;
3638
3639 /*set up the data socket */
3640 send_socket = create_data_socket(local_res);
3641
3642 if (send_socket == INVALID_SOCKET){
3643 perror("netperf: send_tcp_stream: tcp stream data socket");
3644 exit(1);
3645 }
3646
3647 if (debug) {
3648 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
3649 }
3650
3651 /* at this point, we have either retrieved the socket buffer sizes, */
3652 /* or have tried to set them, so now, we may want to set the send */
3653 /* size based on that (because the user either did not use a -m */
3654 /* option, or used one with an argument of 0). If the socket buffer */
3655 /* size is not available, we will set the send size to 4KB - no */
3656 /* particular reason, just arbitrary... */
3657 if (send_size == 0) {
3658 if (lss_size > 0) {
3659 send_size = lss_size;
3660 }
3661 else {
3662 send_size = 4096;
3663 }
3664 }
3665
3666 /* set-up the data buffer ring with the requested alignment and offset. */
3667 /* note also that we have allocated a quantity */
3668 /* of memory that is at least one send-size greater than our socket */
3669 /* buffer size. We want to be sure that there are at least two */
3670 /* buffers allocated - this can be a bit of a problem when the */
3671 /* send_size is bigger than the socket size, so we must check... the */
3672 /* user may have wanted to explicitly set the "width" of our send */
3673 /* buffers, we should respect that wish... */
3674 if (send_width == 0) {
3675 send_width = (lss_size/send_size) + 1;
3676 if (send_width == 1) send_width++;
3677 }
3678
3679 if (send_ring == NULL) {
3680 /* only allocate the send ring once. this is a networking test, */
3681 /* not a memory allocation test. this way, we do not need a */
3682 /* deallocate_buffer_ring() routine, and I don't feel like */
3683 /* writing one anyway :) raj 11/94 */
3684 send_ring = allocate_exs_buffer_ring(send_width,
3685 send_size,
3686 local_send_align,
3687 local_send_offset,
3688 &exs_mhandle);
3689 }
3690
3691 /* If the user has requested cpu utilization measurements, we must */
3692 /* calibrate the cpu(s). We will perform this task within the tests */
3693 /* themselves. If the user has specified the cpu rate, then */
3694 /* calibrate_local_cpu will return rather quickly as it will have */
3695 /* nothing to do. If local_cpu_rate is zero, then we will go through */
3696 /* all the "normal" calibration stuff and return the rate back. */
3697
3698 if (local_cpu_usage) {
3699 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3700 }
3701
3702 /* Tell the remote end to do a listen. The server alters the socket */
3703 /* paramters on the other side at this point, hence the reason for */
3704 /* all the values being passed in the setup message. If the user did */
3705 /* not specify any of the parameters, they will be passed as 0, which */
3706 /* will indicate to the remote that no changes beyond the system's */
3707 /* default should be used. Alignment is the exception, it will */
3708 /* default to 1, which will be no alignment alterations. */
3709
3710 netperf_request.content.request_type = DO_TCP_STREAM;
3711 tcp_stream_request->send_buf_size = rss_size_req;
3712 tcp_stream_request->recv_buf_size = rsr_size_req;
3713 tcp_stream_request->receive_size = recv_size;
3714 tcp_stream_request->no_delay = rem_nodelay;
3715 tcp_stream_request->recv_alignment = remote_recv_align;
3716 tcp_stream_request->recv_offset = remote_recv_offset;
3717 tcp_stream_request->measure_cpu = remote_cpu_usage;
3718 tcp_stream_request->cpu_rate = remote_cpu_rate;
3719 if (test_time) {
3720 tcp_stream_request->test_length = test_time;
3721 }
3722 else {
3723 tcp_stream_request->test_length = test_bytes;
3724 }
3725 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
3726 tcp_stream_request->so_sndavoid = rem_sndavoid;
3727 #ifdef DIRTY
3728 tcp_stream_request->dirty_count = rem_dirty_count;
3729 tcp_stream_request->clean_count = rem_clean_count;
3730 #endif /* DIRTY */
3731 tcp_stream_request->port = atoi(remote_data_port);
3732 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
3733 tcp_stream_request->recv_aio = rem_rcvaio;
3734 if (debug > 1) {
3735 fprintf(where,
3736 "netperf: send_tcp_stream: requesting TCP stream test\n");
3737 }
3738
3739 send_request();
3740
3741 /* The response from the remote will contain all of the relevant */
3742 /* socket parameters for this test type. We will put them back into */
3743 /* the variables here so they can be displayed if desired. The */
3744 /* remote will have calibrated CPU if necessary, and will have done */
3745 /* all the needed set-up we will have calibrated the cpu locally */
3746 /* before sending the request, and will grab the counter value right*/
3747 /* after the connect returns. The remote will grab the counter right*/
3748 /* after the accept call. This saves the hassle of extra messages */
3749 /* being sent for the TCP tests. */
3750
3751 recv_response();
3752
3753 if (!netperf_response.content.serv_errno) {
3754 if (debug)
3755 fprintf(where,"remote listen done.\n");
3756 rsr_size = tcp_stream_response->recv_buf_size;
3757 rss_size = tcp_stream_response->send_buf_size;
3758 rem_nodelay = tcp_stream_response->no_delay;
3759 remote_cpu_usage= tcp_stream_response->measure_cpu;
3760 remote_cpu_rate = tcp_stream_response->cpu_rate;
3761
3762 /* we have to make sure that the server port number is in */
3763 /* network order */
3764 set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
3765
3766 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
3767 rem_sndavoid = tcp_stream_response->so_sndavoid;
3768 }
3769 else {
3770 Set_errno(netperf_response.content.serv_errno);
3771 fprintf(where,
3772 "netperf: remote error %d",
3773 netperf_response.content.serv_errno);
3774 perror("");
3775 fflush(where);
3776
3777 exit(1);
3778 }
3779
3780 #if 0 /* def WANT_DEMO */
3781 demo_stream_setup(lss_size,rsr_size);
3782 #endif
3783
3784 /*Connect up to the remote port on the data socket */
3785 if (connect(send_socket,
3786 remote_res->ai_addr,
3787 remote_res->ai_addrlen) == INVALID_SOCKET){
3788 perror("netperf: send_tcp_stream: data socket connect failed");
3789 exit(1);
3790 }
3791
3792 #ifdef WIN32
3793 /* this is used so the timer thread can close the socket out from */
3794 /* under us, which to date is the easiest/cleanest/least */
3795 /* Windows-specific way I can find to force the winsock calls to */
3796 /* return WSAEINTR with the test is over. anything that will run on */
3797 /* 95 and NT and is closer to what netperf expects from Unix signals */
3798 /* and such would be appreciated raj 1/96 */
3799 win_kludge_socket = send_socket;
3800 #endif /* WIN32 */
3801
3802 /* Data Socket set-up is finished. If there were problems, either */
3803 /* the connect would have failed, or the previous response would */
3804 /* have indicated a problem. I failed to see the value of the */
3805 /* extra message after the accept on the remote. If it failed, */
3806 /* we'll see it here. If it didn't, we might as well start pumping */
3807 /* data. */
3808
3809 /* Set-up the test end conditions. For a stream test, they can be */
3810 /* either time or byte-count based. */
3811
3812 if (test_time) {
3813 /* The user wanted to end the test after a period of time. */
3814 times_up = 0;
3815 bytes_remaining = 0;
3816 /* in previous revisions, we had the same code repeated throught */
3817 /* all the test suites. this was unnecessary, and meant more */
3818 /* work for me when I wanted to switch to POSIX signals, so I */
3819 /* have abstracted this out into a routine in netlib.c. if you */
3820 /* are experiencing signal problems, you might want to look */
3821 /* there. raj 11/94 */
3822 start_timer(test_time);
3823 }
3824 else {
3825 /* The tester wanted to send a number of bytes. */
3826 bytes_remaining = test_bytes;
3827 times_up = 1;
3828 }
3829
3830 /* The cpu_start routine will grab the current time and possibly */
3831 /* value of the idle counter for later use in measuring cpu */
3832 /* utilization and/or service demand and thruput. */
3833
3834 cpu_start(local_cpu_usage);
3835
3836 #if 0 /* def WANT_INTERVALS */
3837 INTERVALS_INIT();
3838 #endif /* WANT_INTERVALS */
3839
3840 /* before we start, initialize a few variables */
3841
3842 #if 0 /* def WANT_DEMO */
3843 if (demo_mode) {
3844 demo_first_timestamp();
3845 }
3846 #endif
3847
3848
3849 /* We use an "OR" to control test execution. When the test is */
3850 /* controlled by time, the byte count check will always return false. */
3851 /* When the test is controlled by byte count, the time test will */
3852 /* always return false. When the test is finished, the whole */
3853 /* expression will go false and we will stop sending data. */
3854
3855 exs_aio_pending = 0;
3856 exs_aio_eagain = 0;
3857 exs_aio_dequeuecnt = 0;
3858
3859 while ((!times_up) || (bytes_remaining > 0)) {
3860
3861 #ifdef DIRTY
3862 access_buffer(send_ring->buffer_ptr,
3863 send_size,
3864 loc_dirty_count,
3865 loc_clean_count);
3866 #endif /* DIRTY */
3867
3868 #if 0 /* def WANT_HISTOGRAM */
3869 /* timestamp just before we go into send and then again just after */
3870 /* we come out raj 8/94 */
3871 HIST_timestamp(&time_one);
3872 #endif /* WANT_HISTOGRAM */
3873
3874
3875 /* post up to NETPERF_EXS_PENDING I/Os */
3876 while ((exs_aio_pending < NETPERF_EXS_PENDING) &&
3877 (exs_send (send_socket, send_ring->buffer_ptr, send_size,
3878 0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) {
3879 exs_aio_pending++;
3880
3881 /* now we want to move our pointer to the next
3882 position in the data buffer...we may also want to
3883 wrap back to the "beginning" of the bufferspace, so
3884 we will mod the number of messages sent by the send
3885 width, and use that to calculate the offset to add
3886 to the base pointer. */
3887
3888 nummessages++;
3889 send_ring = send_ring->next;
3890 if (bytes_remaining) {
3891 bytes_remaining -= send_size;
3892 }
3893 }
3894
3895 /* check exs_send result */
3896 if (exs_aio_pending < NETPERF_EXS_PENDING) {
3897 /* standard flow control case */
3898 if (errno == EAGAIN)
3899 exs_aio_eagain++;
3900 /* case of times_up */
3901 else if (errno == EINTR)
3902 break;
3903 /* strange, let's stop */
3904 else {
3905 perror ("netperf: exs_send error");
3906 exit (1);
3907 }
3908 }
3909
3910 /* dequeue events with "threshold" on 1/2 posted */
3911 exs_aio_dequeued =
3912 exs_qdequeue (exs_qhandle, exs_evtvec,
3913 -(exs_aio_pending>>1), NULL);
3914 exs_aio_dequeuecnt++;
3915
3916 /* check exs_dequeue result */
3917 if (exs_aio_dequeued < 0) {
3918 /* case of times_up */
3919 if (errno == EINTR)
3920 break;
3921 /* strange, let's stop */
3922 else {
3923 perror ("netperf: exs_send error");
3924 exit (1);
3925 }
3926 }
3927 /* update number of pending I/Os */
3928 else {
3929 exs_aio_pending -= exs_aio_dequeued;
3930 }
3931
3932
3933 #if 0 /* def WANT_HISTOGRAM */
3934 /* timestamp the exit from the send call and update the histogram */
3935 HIST_timestamp(&time_two);
3936 HIST_add(time_hist,delta_micro(&time_one,&time_two));
3937 #endif /* WANT_HISTOGRAM */
3938
3939 #if 0 /* def WANT_DEMO */
3940 demo_stream_interval(send_size);
3941 #endif
3942
3943 #if 0 /* def WANT_INTERVALS */
3944 INTERVALS_WAIT();
3945 #endif /* WANT_INTERVALS */
3946
3947 }
3948
3949 /* Collect the last completion events */
3950 exs_aio_dequeued =
3951 exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL);
3952 exs_aio_dequeuecnt++;
3953 /* check exs_dequeue result and update number of pending I/Os */
3954 if (exs_aio_dequeued < 0) {
3955 perror ("netperf: exs_send error");
3956 exit (1);
3957 }
3958 exs_aio_pending -= exs_aio_dequeued;
3959
3960 /* Display some async I/O debug info */
3961 if (debug) {
3962 fprintf (where, "send_exs_tcp_stream: "
3963 "aio sent=%d eagain=%d dequeue=%d pending=%d\n",
3964 nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending);
3965 }
3966
3967 /* The test is over. Flush the buffers to the remote end. We do a */
3968 /* graceful release to insure that all data has been taken by the */
3969 /* remote. */
3970
3971 /* but first, if the verbosity is greater than 1, find-out what */
3972 /* the TCP maximum segment_size was (if possible) */
3973 if (verbosity > 1) {
3974 tcp_mss = -1;
3975 get_tcp_info(send_socket,&tcp_mss);
3976 }
3977
3978 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
3979 perror("netperf: cannot shutdown tcp stream socket");
3980 exit(1);
3981 }
3982
3983 /* hang a recv() off the socket to block until the remote has */
3984 /* brought all the data up into the application. it will do a */
3985 /* shutdown to cause a FIN to be sent our way. We will assume that */
3986 /* any exit from the recv() call is good... raj 4/93 */
3987
3988 recv(send_socket, send_ring->buffer_ptr, send_size, 0);
3989
3990 /* this call will always give us the elapsed time for the test, and */
3991 /* will also store-away the necessaries for cpu utilization */
3992
3993 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
3994 /* measured and how */
3995 /* long did we really */
3996 /* run? */
3997
3998 /* we are finished with the socket, so close it to prevent hitting */
3999 /* the limit on maximum open files. */
4000
4001 close(send_socket);
4002
4003 /* Get the statistics from the remote end. The remote will have */
4004 /* calculated service demand and all those interesting things. If it */
4005 /* wasn't supposed to care, it will return obvious values. */
4006
4007 recv_response();
4008 if (!netperf_response.content.serv_errno) {
4009 if (debug)
4010 fprintf(where,"remote results obtained\n");
4011 }
4012 else {
4013 Set_errno(netperf_response.content.serv_errno);
4014 fprintf(where,
4015 "netperf: remote error %d",
4016 netperf_response.content.serv_errno);
4017 perror("");
4018 fflush(where);
4019
4020 exit(1);
4021 }
4022
4023 /* We now calculate what our thruput was for the test. In the future, */
4024 /* we may want to include a calculation of the thruput measured by */
4025 /* the remote, but it should be the case that for a TCP stream test, */
4026 /* that the two numbers should be *very* close... We calculate */
4027 /* bytes_sent regardless of the way the test length was controlled. */
4028 /* If it was time, we needed to, and if it was by bytes, the user may */
4029 /* have specified a number of bytes that wasn't a multiple of the */
4030 /* send_size, so we really didn't send what he asked for ;-) */
4031
4032 bytes_sent = ntohd(tcp_stream_result->bytes_received);
4033
4034 thruput = calc_thruput(bytes_sent);
4035
4036 if (local_cpu_usage || remote_cpu_usage) {
4037 /* We must now do a little math for service demand and cpu */
4038 /* utilization for the system(s) */
4039 /* Of course, some of the information might be bogus because */
4040 /* there was no idle counter in the kernel(s). We need to make */
4041 /* a note of this for the user's benefit...*/
4042 if (local_cpu_usage) {
4043
4044 local_cpu_utilization = calc_cpu_util(0.0);
4045 local_service_demand = calc_service_demand(bytes_sent,
4046 0.0,
4047 0.0,
4048 0);
4049 }
4050 else {
4051 local_cpu_utilization = (float) -1.0;
4052 local_service_demand = (float) -1.0;
4053 }
4054
4055 if (remote_cpu_usage) {
4056
4057 remote_cpu_utilization = tcp_stream_result->cpu_util;
4058 remote_service_demand = calc_service_demand(bytes_sent,
4059 0.0,
4060 remote_cpu_utilization,
4061 tcp_stream_result->num_cpus);
4062 }
4063 else {
4064 remote_cpu_utilization = (float) -1.0;
4065 remote_service_demand = (float) -1.0;
4066 }
4067 }
4068 else {
4069 /* we were not measuring cpu, for the confidence stuff, we */
4070 /* should make it -1.0 */
4071 local_cpu_utilization = (float) -1.0;
4072 local_service_demand = (float) -1.0;
4073 remote_cpu_utilization = (float) -1.0;
4074 remote_service_demand = (float) -1.0;
4075 }
4076
4077 /* at this point, we want to calculate the confidence information. */
4078 /* if debugging is on, calculate_confidence will print-out the */
4079 /* parameters we pass it */
4080
4081 calculate_confidence(confidence_iteration,
4082 elapsed_time,
4083 thruput,
4084 local_cpu_utilization,
4085 remote_cpu_utilization,
4086 local_service_demand,
4087 remote_service_demand);
4088
4089
4090 confidence_iteration++;
4091 }
4092
4093 /* at this point, we have finished making all the runs that we */
4094 /* will be making. so, we should extract what the calcuated values */
4095 /* are for all the confidence stuff. we could make the values */
4096 /* global, but that seemed a little messy, and it did not seem worth */
4097 /* all the mucking with header files. so, we create a routine much */
4098 /* like calcualte_confidence, which just returns the mean values. */
4099 /* raj 11/94 */
4100
4101 retrieve_confident_values(&elapsed_time,
4102 &thruput,
4103 &local_cpu_utilization,
4104 &remote_cpu_utilization,
4105 &local_service_demand,
4106 &remote_service_demand);
4107
4108 /* We are now ready to print all the information. If the user */
4109 /* has specified zero-level verbosity, we will just print the */
4110 /* local service demand, or the remote service demand. If the */
4111 /* user has requested verbosity level 1, he will get the basic */
4112 /* "streamperf" numbers. If the user has specified a verbosity */
4113 /* of greater than 1, we will display a veritable plethora of */
4114 /* background information from outside of this block as it it */
4115 /* not cpu_measurement specific... */
4116
4117 if (confidence < 0) {
4118 /* we did not hit confidence, but were we asked to look for it? */
4119 if (iteration_max > 1) {
4120 display_confidence();
4121 }
4122 }
4123
4124 if (local_cpu_usage || remote_cpu_usage) {
4125 local_cpu_method = format_cpu_method(cpu_method);
4126 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
4127
4128 switch (verbosity) {
4129 case 0:
4130 if (local_cpu_usage) {
4131 fprintf(where,
4132 cpu_fmt_0,
4133 local_service_demand,
4134 local_cpu_method);
4135 }
4136 else {
4137 fprintf(where,
4138 cpu_fmt_0,
4139 remote_service_demand,
4140 remote_cpu_method);
4141 }
4142 break;
4143 case 1:
4144 case 2:
4145 if (print_headers) {
4146 fprintf(where,
4147 cpu_title,
4148 format_units(),
4149 local_cpu_method,
4150 remote_cpu_method);
4151 }
4152
4153 fprintf(where,
4154 cpu_fmt_1, /* the format string */
4155 rsr_size, /* remote recvbuf size */
4156 lss_size, /* local sendbuf size */
4157 send_size, /* how large were the sends */
4158 elapsed_time, /* how long was the test */
4159 thruput, /* what was the xfer rate */
4160 local_cpu_utilization, /* local cpu */
4161 remote_cpu_utilization, /* remote cpu */
4162 local_service_demand, /* local service demand */
4163 remote_service_demand); /* remote service demand */
4164 break;
4165 }
4166 }
4167 else {
4168 /* The tester did not wish to measure service demand. */
4169
4170 switch (verbosity) {
4171 case 0:
4172 fprintf(where,
4173 tput_fmt_0,
4174 thruput);
4175 break;
4176 case 1:
4177 case 2:
4178 if (print_headers) {
4179 fprintf(where,tput_title,format_units());
4180 }
4181 fprintf(where,
4182 tput_fmt_1, /* the format string */
4183 rsr_size, /* remote recvbuf size */
4184 lss_size, /* local sendbuf size */
4185 send_size, /* how large were the sends */
4186 elapsed_time, /* how long did it take */
4187 thruput);/* how fast did it go */
4188 break;
4189 }
4190 }
4191
4192 /* it would be a good thing to include information about some of the */
4193 /* other parameters that may have been set for this test, but at the */
4194 /* moment, I do not wish to figure-out all the formatting, so I will */
4195 /* just put this comment here to help remind me that it is something */
4196 /* that should be done at a later time. */
4197
4198 if (verbosity > 1) {
4199 /* The user wanted to know it all, so we will give it to him. */
4200 /* This information will include as much as we can find about */
4201 /* TCP statistics, the alignments of the sends and receives */
4202 /* and all that sort of rot... */
4203
4204 /* this stuff needs to be worked-out in the presence of confidence */
4205 /* intervals and multiple iterations of the test... raj 11/94 */
4206
4207 fprintf(where,
4208 ksink_fmt,
4209 "Bytes",
4210 "Bytes",
4211 "Bytes",
4212 local_send_align,
4213 remote_recv_align,
4214 local_send_offset,
4215 remote_recv_offset,
4216 bytes_sent,
4217 bytes_sent / (double)nummessages,
4218 nummessages,
4219 bytes_sent / (double)tcp_stream_result->recv_calls,
4220 tcp_stream_result->recv_calls);
4221 fprintf(where,
4222 ksink_fmt2,
4223 tcp_mss);
4224 fflush(where);
4225 #if 0 /* def WANT_HISTOGRAM */
4226 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
4227 fflush(where);
4228 HIST_report(time_hist);
4229 #endif /* WANT_HISTOGRAM */
4230 }
4231
4232 }
4233
4234 #endif /* HAVE_ICSC_EXS */
4235
4236
4237
4238 #if defined(HAVE_SENDFILE)
4239
4240
4241 /* This routine implements the TCP unidirectional data transfer test
4242 (a.k.a. stream) for the sockets interface using the sendfile()
4243 system call - TCP_SENDFILE. It receives its parameters via global
4244 variables from the shell and writes its output to the standard
4245 output. Basically, this is the same test as the send_tcp_stream()
4246 logic and we even tell the remote to do a TCP_STREAM test since for
4247 all it knows, nothig is different. */
4248
4249 void
sendfile_tcp_stream(remote_host)4250 sendfile_tcp_stream(remote_host)
4251 char remote_host[];
4252 {
4253
4254 char *tput_title = "\
4255 Recv Send Send \n\
4256 Socket Socket Message Elapsed \n\
4257 Size Size Size Time Throughput \n\
4258 bytes bytes bytes secs. %s/sec \n\n";
4259
4260 char *tput_fmt_0 =
4261 "%7.2f %s\n";
4262
4263 char *tput_fmt_1 =
4264 "%6d %6d %6d %-6.2f %7.2f %s\n";
4265
4266 char *cpu_title = "\
4267 Recv Send Send Utilization Service Demand\n\
4268 Socket Socket Message Elapsed Send Recv Send Recv\n\
4269 Size Size Size Time Throughput local remote local remote\n\
4270 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
4271
4272 char *cpu_fmt_0 =
4273 "%6.3f %c %s\n";
4274 char *cpu_fmt_1 =
4275 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
4276
4277 char *ksink_fmt = "\n\
4278 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
4279 Local Remote Local Remote Xfered Per Per\n\
4280 Send Recv Send Recv Send (avg) Recv (avg)\n\
4281 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
4282
4283 char *ksink_fmt2 = "\n\
4284 Maximum\n\
4285 Segment\n\
4286 Size (bytes)\n\
4287 %6d\n";
4288
4289 float elapsed_time;
4290
4291 /* what we want is to have a buffer space that is at least one */
4292 /* send-size greater than our send window. this will insure that we */
4293 /* are never trying to re-use a buffer that may still be in the hands */
4294 /* of the transport. This buffer will be malloc'd after we have found */
4295 /* the size of the local senc socket buffer. We will want to deal */
4296 /* with alignment and offset concerns as well. */
4297
4298 struct ring_elt *send_ring;
4299
4300 int len;
4301 unsigned int nummessages = 0;
4302 SOCKET send_socket;
4303 int bytes_remaining;
4304 int tcp_mss = -1; /* possibly uninitialized on printf far below */
4305
4306 /* with links like fddi, one can send > 32 bits worth of bytes */
4307 /* during a test... ;-) at some point, this should probably become a */
4308 /* 64bit integral type, but those are not entirely common yet */
4309 double bytes_sent = 0.0;
4310
4311 float local_cpu_utilization;
4312 float local_service_demand;
4313 float remote_cpu_utilization;
4314 float remote_service_demand;
4315
4316 double thruput;
4317
4318 struct addrinfo *remote_res;
4319 struct addrinfo *local_res;
4320 struct sockaddr_in server;
4321
4322 #if defined(__linux) || defined(__sun)
4323 off_t scratch_offset; /* the linux sendfile() call will update
4324 the offset variable, which is
4325 something we do _not_ want to happen
4326 to the value in the send_ring! so, we
4327 have to use a scratch variable. */
4328 #endif /* __linux || defined(__sun) */
4329 #if defined (USE_OSX)
4330 off_t scratch_len; /* Darwin 9.x need a value-result parameter */
4331 #endif
4332 #if defined (__sun)
4333 size_t scratch_len; /* the sun sendfilev() needs a place to
4334 tell us how many bytes were written,
4335 even though it also returns the value */
4336 sendfilevec_t sv;
4337 #endif /* __sun */
4338
4339 struct tcp_stream_request_struct *tcp_stream_request;
4340 struct tcp_stream_response_struct *tcp_stream_response;
4341 struct tcp_stream_results_struct *tcp_stream_result;
4342
4343 tcp_stream_request =
4344 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
4345 tcp_stream_response =
4346 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
4347 tcp_stream_result =
4348 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
4349
4350 #ifdef WANT_HISTOGRAM
4351 if (verbosity > 1) {
4352 time_hist = HIST_new();
4353 }
4354 #endif /* WANT_HISTOGRAM */
4355
4356 /* since we are now disconnected from the code that established the */
4357 /* control socket, and since we want to be able to use different */
4358 /* protocols and such, we are passed the name of the remote host and */
4359 /* must turn that into the test specific addressing information. */
4360
4361 bzero((char *)&server,
4362 sizeof(server));
4363
4364 complete_addrinfos(&remote_res,
4365 &local_res,
4366 remote_host,
4367 SOCK_STREAM,
4368 IPPROTO_TCP,
4369 0);
4370
4371 if ( print_headers ) {
4372 /* we want to have some additional, interesting information in */
4373 /* the headers. we know some of it here, but not all, so we will */
4374 /* only print the test title here and will print the results */
4375 /* titles after the test is finished */
4376 print_top_test_header("TCP SENDFILE TEST",local_res,remote_res);
4377 }
4378
4379 send_ring = NULL;
4380 confidence_iteration = 1;
4381 init_stat();
4382
4383 /* we have a great-big while loop which controls the number of times */
4384 /* we run a particular test. this is for the calculation of a */
4385 /* confidence interval (I really should have stayed awake during */
4386 /* probstats :). If the user did not request confidence measurement */
4387 /* (no confidence is the default) then we will only go though the */
4388 /* loop once. the confidence stuff originates from the folks at IBM */
4389
4390 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
4391 (confidence_iteration <= iteration_min)) {
4392
4393 /* initialize a few counters. we have to remember that we might be */
4394 /* going through the loop more than once. */
4395
4396 nummessages = 0;
4397 bytes_sent = 0.0;
4398 times_up = 0;
4399
4400 /* set up the data socket */
4401 send_socket = create_data_socket(local_res);
4402
4403 if (send_socket == INVALID_SOCKET){
4404 perror("netperf: sendfile_tcp_stream: tcp stream data socket");
4405 exit(1);
4406 }
4407
4408 if (debug) {
4409 fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n");
4410 }
4411
4412 #if defined(TCP_CORK)
4413 /* should this even be here?!? */
4414 if (loc_tcpcork > 0) {
4415 /* the user wishes for us to set TCP_CORK on the socket */
4416 int one = 1;
4417 if (setsockopt(send_socket,
4418 getprotobyname("tcp")->p_proto,
4419 TCP_CORK,
4420 (char *)&one,
4421 sizeof(one)) == SOCKET_ERROR) {
4422 perror("netperf: sendfile_tcp_stream: tcp_cork");
4423 exit(1);
4424 }
4425 if (debug) {
4426 fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
4427 }
4428 }
4429
4430 #endif /* TCP_CORK */
4431
4432 /* at this point, we have either retrieved the socket buffer sizes, */
4433 /* or have tried to set them, so now, we may want to set the send */
4434 /* size based on that (because the user either did not use a -m */
4435 /* option, or used one with an argument of 0). If the socket buffer */
4436 /* size is not available, we will set the send size to 4KB - no */
4437 /* particular reason, just arbitrary... */
4438
4439 /*check for file size/ min file size here? create file here/ back out???*/
4440
4441 if (send_size == 0) {
4442 if (lss_size > 0) {
4443 send_size = lss_size;
4444 }
4445 else {
4446 send_size = 4096;
4447 }
4448 }
4449
4450 /* set-up the data buffer ring with the requested alignment and
4451 offset. note also that we have allocated a quantity of memory
4452 that is at least one send-size greater than our socket buffer
4453 size. We want to be sure that there are at least two buffers
4454 allocated - this can be a bit of a problem when the send_size
4455 is bigger than the socket size, so we must check... the user
4456 may have wanted to explicitly set the "width" of our send
4457 buffers, we should respect that wish... */
4458
4459 /*sendring -> an offset index that will shift the starting point of the*/
4460 /*section of the file sent throughout the file*/
4461
4462 if (send_width == 0) {
4463 send_width = (lss_size/send_size) + 1;
4464 if (send_width == 1) send_width++;
4465 }
4466
4467 if (send_ring == NULL) {
4468
4469 /* only allocate the send ring once. this is a networking test,
4470 not a memory allocation test. this way, we do not need a
4471 deallocate_buffer_ring() routine, and I don't feel like
4472 writing one anyway :) raj 11/94 */
4473
4474 send_ring = alloc_sendfile_buf_ring(send_width,
4475 send_size,
4476 local_send_align,
4477 local_send_offset);
4478 }
4479
4480 /* If the user has requested cpu utilization measurements, we must
4481 calibrate the cpu(s). We will perform this task within the
4482 tests themselves. If the user has specified the cpu rate, then
4483 calibrate_local_cpu will return rather quickly as it will have
4484 nothing to do. If local_cpu_rate is zero, then we will go
4485 through all the "normal" calibration stuff and return the rate
4486 back. */
4487
4488 if (local_cpu_usage) {
4489 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
4490 }
4491
4492 /* Tell the remote end to do a listen. The server alters the
4493 socket paramters on the other side at this point, hence the
4494 reason for all the values being passed in the setup
4495 message. If the user did not specify any of the parameters,
4496 they will be passed as 0, which will indicate to the remote
4497 that no changes beyond the system's default should be
4498 used. Alignment is the exception, it will default to 1, which
4499 will be no alignment alterations. */
4500
4501 netperf_request.content.request_type = DO_TCP_STREAM;
4502 tcp_stream_request->send_buf_size = rss_size_req;
4503 tcp_stream_request->recv_buf_size = rsr_size_req;
4504 tcp_stream_request->receive_size = recv_size;
4505 tcp_stream_request->no_delay = rem_nodelay;
4506 tcp_stream_request->recv_alignment = remote_recv_align;
4507 tcp_stream_request->recv_offset = remote_recv_offset;
4508 tcp_stream_request->measure_cpu = remote_cpu_usage;
4509 tcp_stream_request->cpu_rate = remote_cpu_rate;
4510
4511 if (test_time) {
4512 tcp_stream_request->test_length = test_time;
4513 }
4514 else {
4515 tcp_stream_request->test_length = test_bytes;
4516 }
4517
4518 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
4519 tcp_stream_request->so_sndavoid = rem_sndavoid;
4520
4521 #ifdef DIRTY
4522 tcp_stream_request->dirty_count = rem_dirty_count;
4523 tcp_stream_request->clean_count = rem_clean_count;
4524 #endif /* DIRTY */
4525 tcp_stream_request->port = atoi(remote_data_port);
4526 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
4527 tcp_stream_request->recv_aio = rem_rcvaio;
4528
4529 if (debug > 1) {
4530 fprintf(where,
4531 "netperf: send_tcp_stream: requesting TCP stream test\n");
4532 }
4533
4534 send_request();
4535
4536 /* The response from the remote will contain all of the relevant
4537 socket parameters for this test type. We will put them back
4538 into the variables here so they can be displayed if desired.
4539 The remote will have calibrated CPU if necessary, and will have
4540 done all the needed set-up we will have calibrated the cpu
4541 locally before sending the request, and will grab the counter
4542 value right after the connect returns. The remote will grab the
4543 counter right after the accept call. This saves the hassle of
4544 extra messages being sent for the TCP tests. */
4545
4546 recv_response();
4547
4548 if (!netperf_response.content.serv_errno) {
4549 if (debug)
4550 fprintf(where,"remote listen done.\n");
4551 rsr_size = tcp_stream_response->recv_buf_size;
4552 rss_size = tcp_stream_response->send_buf_size;
4553 rem_nodelay = tcp_stream_response->no_delay;
4554 remote_cpu_usage= tcp_stream_response->measure_cpu;
4555 remote_cpu_rate = tcp_stream_response->cpu_rate;
4556
4557 /* we have to make sure that the server port number is in */
4558 /* network order */
4559 set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
4560 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
4561 rem_sndavoid = tcp_stream_response->so_sndavoid;
4562 }
4563 else {
4564 Set_errno(netperf_response.content.serv_errno);
4565 fprintf(where,
4566 "netperf: remote error %d",
4567 netperf_response.content.serv_errno);
4568 perror("");
4569 fflush(where);
4570
4571 exit(1);
4572 }
4573
4574 #ifdef WANT_DEMO
4575 demo_stream_setup(lss_size,rsr_size);
4576 #endif
4577
4578 /*Connect up to the remote port on the data socket */
4579 if (connect(send_socket,
4580 remote_res->ai_addr,
4581 remote_res->ai_addrlen) == INVALID_SOCKET){
4582 perror("netperf: send_tcp_stream: data socket connect failed");
4583 printf(" port: %d\n",ntohs(server.sin_port));
4584 exit(1);
4585 }
4586
4587 #ifdef WIN32
4588 /* this is used so the timer thread can close the socket out from */
4589 /* under us, which to date is the easiest/cleanest/least */
4590 /* Windows-specific way I can find to force the winsock calls to */
4591 /* return WSAEINTR with the test is over. anything that will run on */
4592 /* 95 and NT and is closer to what netperf expects from Unix signals */
4593 /* and such would be appreciated raj 1/96 */
4594 win_kludge_socket = send_socket;
4595 #endif /* WIN32 */
4596
4597 /* Data Socket set-up is finished. If there were problems, either
4598 the connect would have failed, or the previous response would
4599 have indicated a problem. I failed to see the value of the
4600 extra message after the accept on the remote. If it failed,
4601 we'll see it here. If it didn't, we might as well start pumping
4602 data. */
4603
4604 /* Set-up the test end conditions. For a stream test, they can be */
4605 /* either time or byte-count based. */
4606
4607 if (test_time) {
4608 /* The user wanted to end the test after a period of time. */
4609 times_up = 0;
4610 bytes_remaining = 0;
4611
4612 /* in previous revisions, we had the same code repeated throught
4613 all the test suites. this was unnecessary, and meant more
4614 work for me when I wanted to switch to POSIX signals, so I
4615 have abstracted this out into a routine in netlib.c. if you
4616 are experiencing signal problems, you might want to look
4617 there. raj 11/94 */
4618
4619 start_timer(test_time);
4620 }
4621 else {
4622 /* The tester wanted to send a number of bytes. */
4623 bytes_remaining = test_bytes;
4624 times_up = 1;
4625 }
4626
4627 /* The cpu_start routine will grab the current time and possibly */
4628 /* value of the idle counter for later use in measuring cpu */
4629 /* utilization and/or service demand and thruput. */
4630
4631 cpu_start(local_cpu_usage);
4632
4633 #ifdef WANT_INTERVALS
4634 INTERVALS_INIT();
4635 #endif /* WANT_INTERVALS */
4636
4637
4638 /* before we start, initialize a few variables */
4639
4640 #ifdef WANT_DEMO
4641 if (demo_mode) {
4642 demo_first_timestamp();
4643 }
4644 #endif
4645
4646 /* We use an "OR" to control test execution. When the test is
4647 controlled by time, the byte count check will always return
4648 false. When the test is controlled by byte count, the time test
4649 will always return false. When the test is finished, the whole
4650 expression will go false and we will stop sending data. */
4651
4652 while ((!times_up) || (bytes_remaining > 0)) {
4653
4654 /* the sendfile_tcp_stream test does not support making the buffers
4655 dirty. 08/2000 */
4656
4657 #ifdef WANT_HISTOGRAM
4658 if (verbosity > 1) {
4659 /* timestamp just before we go into sendfile() and then again
4660 just after we come out raj 08/2000 */
4661 /* but only if we are actually going to display a histogram */
4662 HIST_timestamp(&time_one);
4663 }
4664 #endif /* WANT_HISTOGRAM */
4665
4666 /* you can look at netlib.h for a description of the fields we
4667 are passing to sendfile(). 08/2000 */
4668 if (netperf_sendfile(send_socket, send_ring) != send_size) {
4669 /* the test was interrupted, must be the end of test. the
4670 send_tcp_stream code has some WIN32 ifdefs that we do not
4671 need here. */
4672 if ((len >=0) || SOCKET_EINTR(len)) {
4673 break;
4674 }
4675 perror("netperf: data send error: sendfile");
4676 fprintf(stderr,
4677 "len was %d send_size was %d\n",
4678 len,
4679 send_size);
4680 fflush(stderr);
4681 exit(1);
4682 }
4683
4684 #ifdef WANT_HISTOGRAM
4685 if (verbosity > 1) {
4686 /* timestamp the exit from the send call and update the
4687 histogram */
4688
4689 HIST_timestamp(&time_two);
4690 HIST_add(time_hist,delta_micro(&time_one,&time_two));
4691 }
4692 #endif /* WANT_HISTOGRAM */
4693
4694 #ifdef WANT_DEMO
4695 demo_stream_interval(send_size);
4696 #endif
4697
4698 #ifdef WANT_INTERVALS
4699 INTERVALS_WAIT();
4700 #endif /* WANT_INTERVALS */
4701
4702 /* now we want to move our pointer to the next position in the */
4703 /* data buffer...we may also want to wrap back to the "beginning" */
4704 /* of the bufferspace, so we will mod the number of messages sent */
4705 /* by the send width, and use that to calculate the offset to add */
4706 /* to the base pointer. */
4707
4708 nummessages++;
4709 send_ring = send_ring->next;
4710 if (bytes_remaining) {
4711 bytes_remaining -= send_size;
4712 }
4713 }
4714
4715 /* The test is over. Flush the buffers to the remote end. We do a
4716 graceful release to insure that all data has been taken by the
4717 remote. */
4718
4719 /* but first, if the verbosity is greater than 1, find-out what */
4720 /* the TCP maximum segment_size was (if possible) */
4721 if (verbosity > 1) {
4722 tcp_mss = -1;
4723 get_tcp_info(send_socket,&tcp_mss);
4724 }
4725
4726 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
4727 perror("netperf: cannot shutdown tcp stream socket");
4728 exit(1);
4729 }
4730
4731 /* hang a recv() off the socket to block until the remote has */
4732 /* brought all the data up into the application. it will do a */
4733 /* shutdown to cause a FIN to be sent our way. We will assume that */
4734 /* any exit from the recv() call is good... raj 4/93 */
4735
4736 /* since we are using sendfile() instead of send, we have no
4737 scratch buffer from the send_ring to use for the
4738 receive. however, since we "know" that the recv should be
4739 returning zero bytes (not that we are making the checks we
4740 should) we can pass the address of the flags field. raj 08/2000
4741 */
4742
4743 recv(send_socket,
4744 &(send_ring->flags),
4745 sizeof(send_ring->flags),
4746 0);
4747
4748 /* this call will always give us the elapsed time for the test, and */
4749 /* will also store-away the necessaries for cpu utilization */
4750
4751 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
4752 /* measured and how */
4753 /* long did we really */
4754 /* run? */
4755
4756 /* we are finished with the socket, so close it to prevent hitting */
4757 /* the limit on maximum open files. */
4758
4759 close(send_socket);
4760
4761 #if defined(WANT_INTERVALS)
4762 #ifdef WIN32
4763 stop_itimer();
4764 #endif
4765 #endif /* WANT_INTERVALS */
4766
4767 /* Get the statistics from the remote end. The remote will have */
4768 /* calculated service demand and all those interesting things. If it */
4769 /* wasn't supposed to care, it will return obvious values. */
4770
4771 recv_response();
4772
4773 if (!netperf_response.content.serv_errno) {
4774 if (debug)
4775 fprintf(where,"remote results obtained\n");
4776 }
4777
4778 else {
4779 Set_errno(netperf_response.content.serv_errno);
4780 fprintf(where,
4781 "netperf: remote error %d",
4782 netperf_response.content.serv_errno);
4783 perror("");
4784 fflush(where);
4785
4786 exit(1);
4787 }
4788
4789 /* We now calculate what our thruput was for the test. In the future, */
4790 /* we may want to include a calculation of the thruput measured by */
4791 /* the remote, but it should be the case that for a TCP stream test, */
4792 /* that the two numbers should be *very* close... We calculate */
4793 /* bytes_sent regardless of the way the test length was controlled. */
4794 /* If it was time, we needed to, and if it was by bytes, the user may */
4795 /* have specified a number of bytes that wasn't a multiple of the */
4796 /* send_size, so we really didn't send what he asked for ;-) */
4797
4798 bytes_sent = ntohd(tcp_stream_result->bytes_received);
4799
4800 thruput = calc_thruput(bytes_sent);
4801
4802 if (local_cpu_usage || remote_cpu_usage) {
4803
4804 /* We must now do a little math for service demand and cpu */
4805 /* utilization for the system(s) */
4806 /* Of course, some of the information might be bogus because */
4807 /* there was no idle counter in the kernel(s). We need to make */
4808 /* a note of this for the user's benefit...*/
4809 if (local_cpu_usage) {
4810
4811 local_cpu_utilization = calc_cpu_util(0.0);
4812 local_service_demand = calc_service_demand(bytes_sent,
4813 0.0,
4814 0.0,
4815 0);
4816 }
4817 else {
4818 local_cpu_utilization = (float) -1.0;
4819 local_service_demand = (float) -1.0;
4820 }
4821
4822 if (remote_cpu_usage) {
4823
4824 remote_cpu_utilization = tcp_stream_result->cpu_util;
4825 remote_service_demand = calc_service_demand(bytes_sent,
4826 0.0,
4827 remote_cpu_utilization,
4828 tcp_stream_result->num_cpus);
4829 }
4830 else {
4831 remote_cpu_utilization = (float) -1.0;
4832 remote_service_demand = (float) -1.0;
4833 }
4834 }
4835 else {
4836 /* we were not measuring cpu, for the confidence stuff, we */
4837 /* should make it -1.0 */
4838 local_cpu_utilization = (float) -1.0;
4839 local_service_demand = (float) -1.0;
4840 remote_cpu_utilization = (float) -1.0;
4841 remote_service_demand = (float) -1.0;
4842 }
4843
4844 /* at this point, we want to calculate the confidence information. */
4845 /* if debugging is on, calculate_confidence will print-out the */
4846 /* parameters we pass it */
4847
4848 calculate_confidence(confidence_iteration,
4849 elapsed_time,
4850 thruput,
4851 local_cpu_utilization,
4852 remote_cpu_utilization,
4853 local_service_demand,
4854 remote_service_demand);
4855
4856 confidence_iteration++;
4857 }
4858
4859 /* at this point, we have finished making all the runs that we */
4860 /* will be making. so, we should extract what the calcuated values */
4861 /* are for all the confidence stuff. we could make the values */
4862 /* global, but that seemed a little messy, and it did not seem worth */
4863 /* all the mucking with header files. so, we create a routine much */
4864 /* like calcualte_confidence, which just returns the mean values. */
4865 /* raj 11/94 */
4866
4867 retrieve_confident_values(&elapsed_time,
4868 &thruput,
4869 &local_cpu_utilization,
4870 &remote_cpu_utilization,
4871 &local_service_demand,
4872 &remote_service_demand);
4873
4874 /* We are now ready to print all the information. If the user */
4875 /* has specified zero-level verbosity, we will just print the */
4876 /* local service demand, or the remote service demand. If the */
4877 /* user has requested verbosity level 1, he will get the basic */
4878 /* "streamperf" numbers. If the user has specified a verbosity */
4879 /* of greater than 1, we will display a veritable plethora of */
4880 /* background information from outside of this block as it it */
4881 /* not cpu_measurement specific... */
4882
4883 if (confidence < 0) {
4884 /* we did not hit confidence, but were we asked to look for it? */
4885 if (iteration_max > 1) {
4886 display_confidence();
4887 }
4888 }
4889
4890 if (local_cpu_usage || remote_cpu_usage) {
4891 local_cpu_method = format_cpu_method(cpu_method);
4892 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
4893
4894 switch (verbosity) {
4895 case 0:
4896
4897 if (local_cpu_usage) {
4898 fprintf(where,
4899 cpu_fmt_0,
4900 local_service_demand,
4901 local_cpu_method,
4902 ((print_headers) ||
4903 (result_brand == NULL)) ? "" : result_brand);
4904 }
4905
4906 else {
4907 fprintf(where,
4908 cpu_fmt_0,
4909 remote_service_demand,
4910 remote_cpu_method,
4911 ((print_headers) ||
4912 (result_brand == NULL)) ? "" : result_brand);
4913 }
4914
4915 break;
4916
4917 case 1:
4918 case 2:
4919 if (print_headers) {
4920 fprintf(where,
4921 cpu_title,
4922 format_units(),
4923 local_cpu_method,
4924 remote_cpu_method);
4925 }
4926
4927 fprintf(where,
4928 cpu_fmt_1, /* the format string */
4929 rsr_size, /* remote recvbuf size */
4930 lss_size, /* local sendbuf size */
4931 send_size, /* how large were the sends */
4932 elapsed_time, /* how long was the test */
4933 thruput, /* what was the xfer rate */
4934 local_cpu_utilization, /* local cpu */
4935 remote_cpu_utilization, /* remote cpu */
4936 local_service_demand, /* local service demand */
4937 remote_service_demand, /* remote service demand */
4938 ((print_headers) ||
4939 (result_brand == NULL)) ? "" : result_brand);
4940 break;
4941 }
4942
4943 }
4944
4945 else {
4946 /* The tester did not wish to measure service demand. */
4947
4948 switch (verbosity) {
4949
4950 case 0:
4951
4952 fprintf(where,
4953 tput_fmt_0,
4954 thruput,
4955 ((print_headers) ||
4956 (result_brand == NULL)) ? "" : result_brand);
4957 break;
4958
4959 case 1:
4960 case 2:
4961
4962 if (print_headers) {
4963 fprintf(where,tput_title,format_units());
4964 }
4965
4966 fprintf(where,
4967 tput_fmt_1, /* the format string */
4968 rsr_size, /* remote recvbuf size */
4969 lss_size, /* local sendbuf size */
4970 send_size, /* how large were the sends */
4971 elapsed_time, /* how long did it take */
4972 thruput, /* how fast did it go */
4973 ((print_headers) ||
4974 (result_brand == NULL)) ? "" : result_brand);
4975 break;
4976 }
4977 }
4978
4979 /* it would be a good thing to include information about some of the */
4980 /* other parameters that may have been set for this test, but at the */
4981 /* moment, I do not wish to figure-out all the formatting, so I will */
4982 /* just put this comment here to help remind me that it is something */
4983 /* that should be done at a later time. */
4984
4985 if (verbosity > 1) {
4986
4987 /* The user wanted to know it all, so we will give it to him. */
4988 /* This information will include as much as we can find about */
4989 /* TCP statistics, the alignments of the sends and receives */
4990 /* and all that sort of rot... */
4991
4992 /* this stuff needs to be worked-out in the presence of confidence */
4993 /* intervals and multiple iterations of the test... raj 11/94 */
4994
4995 fprintf(where,
4996 ksink_fmt,
4997 "Bytes",
4998 "Bytes",
4999 "Bytes",
5000 local_send_align,
5001 remote_recv_align,
5002 local_send_offset,
5003 remote_recv_offset,
5004 bytes_sent,
5005 bytes_sent / (double)nummessages,
5006 nummessages,
5007 bytes_sent / (double)tcp_stream_result->recv_calls,
5008 tcp_stream_result->recv_calls);
5009
5010 fprintf(where,
5011 ksink_fmt2,
5012 tcp_mss);
5013
5014 fflush(where);
5015
5016 #ifdef WANT_HISTOGRAM
5017
5018 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
5019 fflush(where);
5020 HIST_report(time_hist);
5021 #endif /* WANT_HISTOGRAM */
5022 }
5023 }
5024
5025 #endif /* HAVE_SENDFILE */
5026
5027 /* This is the server-side routine for the tcp stream test. It is */
5028 /* implemented as one routine. I could break things-out somewhat, but */
5029 /* didn't feel it was necessary. */
5030
5031 void
recv_tcp_stream()5032 recv_tcp_stream()
5033 {
5034
5035 struct sockaddr_storage myaddr_in, peeraddr_in;
5036 SOCKET s_listen,s_data;
5037 netperf_socklen_t addrlen;
5038 int len;
5039 unsigned int receive_calls;
5040 float elapsed_time;
5041 double bytes_received;
5042
5043 struct ring_elt *recv_ring;
5044
5045 struct addrinfo *local_res;
5046 char local_name[BUFSIZ];
5047 char port_buffer[PORTBUFSIZE];
5048
5049 #ifdef DO_SELECT
5050 fd_set readfds;
5051 struct timeval timeout;
5052 #endif /* DO_SELECT */
5053
5054 struct tcp_stream_request_struct *tcp_stream_request;
5055 struct tcp_stream_response_struct *tcp_stream_response;
5056 struct tcp_stream_results_struct *tcp_stream_results;
5057
5058 #ifdef DO_SELECT
5059 FD_ZERO(&readfds);
5060 timeout.tv_sec = 1;
5061 timeout.tv_usec = 0;
5062 #endif /* DO_SELECT */
5063
5064 tcp_stream_request =
5065 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
5066 tcp_stream_response =
5067 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
5068 tcp_stream_results =
5069 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
5070
5071 if (debug) {
5072 fprintf(where,"netserver: recv_tcp_stream: entered...\n");
5073 fflush(where);
5074 }
5075
5076 /* We want to set-up the listen socket with all the desired */
5077 /* parameters and then let the initiator know that all is ready. If */
5078 /* socket size defaults are to be used, then the initiator will have */
5079 /* sent us 0's. If the socket sizes cannot be changed, then we will */
5080 /* send-back what they are. If that information cannot be determined, */
5081 /* then we send-back -1's for the sizes. If things go wrong for any */
5082 /* reason, we will drop back ten yards and punt. */
5083
5084 /* If anything goes wrong, we want the remote to know about it. It */
5085 /* would be best if the error that the remote reports to the user is */
5086 /* the actual error we encountered, rather than some bogus unexpected */
5087 /* response type message. */
5088
5089 if (debug) {
5090 fprintf(where,"recv_tcp_stream: setting the response type...\n");
5091 fflush(where);
5092 }
5093
5094 netperf_response.content.response_type = TCP_STREAM_RESPONSE;
5095
5096 if (debug) {
5097 fprintf(where,"recv_tcp_stream: the response type is set...\n");
5098 fflush(where);
5099 }
5100
5101 /* We now alter the message_ptr variable to be at the desired */
5102 /* alignment with the desired offset. */
5103
5104 if (debug) {
5105 fprintf(where,"recv_tcp_stream: requested alignment of %d\n",
5106 tcp_stream_request->recv_alignment);
5107 fflush(where);
5108 }
5109
5110 /* create_data_socket expects to find some things in the global */
5111 /* variables, so set the globals based on the values in the request. */
5112 /* once the socket has been created, we will set the response values */
5113 /* based on the updated value of those globals. raj 7/94 */
5114 lss_size_req = tcp_stream_request->send_buf_size;
5115 lsr_size_req = tcp_stream_request->recv_buf_size;
5116 loc_nodelay = tcp_stream_request->no_delay;
5117 loc_rcvavoid = tcp_stream_request->so_rcvavoid;
5118 loc_sndavoid = tcp_stream_request->so_sndavoid;
5119 loc_rcvaio = tcp_stream_request->recv_aio;
5120
5121 set_hostname_and_port(local_name,
5122 port_buffer,
5123 nf_to_af(tcp_stream_request->ipfamily),
5124 tcp_stream_request->port);
5125
5126 local_res = complete_addrinfo(local_name,
5127 local_name,
5128 port_buffer,
5129 nf_to_af(tcp_stream_request->ipfamily),
5130 SOCK_STREAM,
5131 IPPROTO_TCP,
5132 0);
5133
5134 s_listen = create_data_socket(local_res);
5135
5136 if (s_listen == INVALID_SOCKET) {
5137 netperf_response.content.serv_errno = errno;
5138 send_response();
5139 exit(1);
5140 }
5141
5142 #ifdef WIN32
5143 /* The test timer can fire during operations on the listening socket,
5144 so to make the start_timer below work we have to move
5145 it to close s_listen while we are blocked on accept. */
5146 win_kludge_socket2 = s_listen;
5147 #endif
5148
5149 /* what sort of sizes did we end-up with? */
5150 if (tcp_stream_request->receive_size == 0) {
5151 if (lsr_size > 0) {
5152 recv_size = lsr_size;
5153 }
5154 else {
5155 recv_size = 4096;
5156 }
5157 }
5158 else {
5159 recv_size = tcp_stream_request->receive_size;
5160 }
5161
5162 /* we want to set-up our recv_ring in a manner analagous to what we */
5163 /* do on the sending side. this is more for the sake of symmetry */
5164 /* than for the needs of say copy avoidance, but it might also be */
5165 /* more realistic - this way one could conceivably go with a */
5166 /* double-buffering scheme when taking the data an putting it into */
5167 /* the filesystem or something like that. raj 7/94 */
5168
5169 if (recv_width == 0) {
5170 recv_width = (lsr_size/recv_size) + 1;
5171 if (recv_width == 1) recv_width++;
5172 }
5173
5174 recv_ring = allocate_buffer_ring(recv_width,
5175 recv_size,
5176 tcp_stream_request->recv_alignment,
5177 tcp_stream_request->recv_offset);
5178
5179 if (debug) {
5180 fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n");
5181 fflush(where);
5182 }
5183
5184 /* Now, let's set-up the socket to listen for connections */
5185 if (listen(s_listen, 5) == SOCKET_ERROR) {
5186 netperf_response.content.serv_errno = errno;
5187 close(s_listen);
5188 send_response();
5189
5190 exit(1);
5191 }
5192
5193
5194 /* now get the port number assigned by the system */
5195 addrlen = sizeof(myaddr_in);
5196 if (getsockname(s_listen,
5197 (struct sockaddr *)&myaddr_in,
5198 &addrlen) == SOCKET_ERROR){
5199 netperf_response.content.serv_errno = errno;
5200 close(s_listen);
5201 send_response();
5202
5203 exit(1);
5204 }
5205
5206 /* Now myaddr_in contains the port and the internet address this is */
5207 /* returned to the sender also implicitly telling the sender that the */
5208 /* socket buffer sizing has been done. */
5209
5210 tcp_stream_response->data_port_number =
5211 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
5212 netperf_response.content.serv_errno = 0;
5213
5214 /* But wait, there's more. If the initiator wanted cpu measurements, */
5215 /* then we must call the calibrate routine, which will return the max */
5216 /* rate back to the initiator. If the CPU was not to be measured, or */
5217 /* something went wrong with the calibration, we will return a -1 to */
5218 /* the initiator. */
5219
5220 tcp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
5221 if (tcp_stream_request->measure_cpu) {
5222 tcp_stream_response->measure_cpu = 1;
5223 tcp_stream_response->cpu_rate =
5224 calibrate_local_cpu(tcp_stream_request->cpu_rate);
5225 }
5226 else {
5227 tcp_stream_response->measure_cpu = 0;
5228 }
5229
5230 /* before we send the response back to the initiator, pull some of */
5231 /* the socket parms from the globals */
5232 tcp_stream_response->send_buf_size = lss_size;
5233 tcp_stream_response->recv_buf_size = lsr_size;
5234 tcp_stream_response->no_delay = loc_nodelay;
5235 tcp_stream_response->so_rcvavoid = loc_rcvavoid;
5236 tcp_stream_response->so_sndavoid = loc_sndavoid;
5237 tcp_stream_response->receive_size = recv_size;
5238
5239 send_response();
5240
5241 addrlen = sizeof(peeraddr_in);
5242
5243 if ((s_data=accept(s_listen,
5244 (struct sockaddr *)&peeraddr_in,
5245 &addrlen)) == INVALID_SOCKET) {
5246 /* Let's just punt. The remote will be given some information */
5247 close(s_listen);
5248 exit(1);
5249 }
5250
5251 #ifdef WIN32
5252 /* this is used so the timer thread can close the socket out from */
5253 /* under us, which to date is the easiest/cleanest/least */
5254 /* Windows-specific way I can find to force the winsock calls to */
5255 /* return WSAEINTR with the test is over. anything that will run on */
5256 /* 95 and NT and is closer to what netperf expects from Unix signals */
5257 /* and such would be appreciated raj 1/96 */
5258 win_kludge_socket = s_data;
5259 win_kludge_socket2 = INVALID_SOCKET;
5260 #endif /* WIN32 */
5261
5262 times_up = 0;
5263
5264 start_timer(tcp_stream_request->test_length + PAD_TIME);
5265
5266 #ifdef KLUDGE_SOCKET_OPTIONS
5267 /* this is for those systems which *INCORRECTLY* fail to pass */
5268 /* attributes across an accept() call. Including this goes against */
5269 /* my better judgement :( raj 11/95 */
5270
5271 kludge_socket_options(s_data);
5272
5273 #endif /* KLUDGE_SOCKET_OPTIONS */
5274
5275 /* Now it's time to start receiving data on the connection. We will */
5276 /* first grab the apropriate counters and then start grabbing. */
5277
5278 cpu_start(tcp_stream_request->measure_cpu);
5279
5280 /* The loop will exit when the sender does a shutdown, which will */
5281 /* return a length of zero */
5282
5283 /* there used to be an #ifdef DIRTY call to access_buffer() here,
5284 but we have switched from accessing the buffer before the recv()
5285 call to accessing the buffer after the recv() call. The
5286 accessing before was, IIRC, related to having dirty data when
5287 doing page-flipping copy avoidance. */
5288
5289 bytes_received = 0;
5290 receive_calls = 0;
5291
5292 #if HAVE_AIO
5293 if (loc_rcvaio > 0) {
5294 struct aiocb *iocb;
5295 unsigned int i;
5296
5297 for (i = 0; i < recv_width; i++) {
5298 assert(recv_ring->completion_ptr == NULL);
5299 iocb = calloc(1, sizeof(*iocb));
5300 iocb->aio_nbytes = recv_size;
5301 iocb->aio_fildes = s_data;
5302 iocb->aio_buf = recv_ring->buffer_ptr;
5303 recv_ring->completion_ptr = iocb;
5304 recv_ring = recv_ring->next;
5305 if (aio_read(iocb) != 0) {
5306 netperf_response.content.serv_errno = errno;
5307 send_response();
5308 exit(1);
5309 }
5310 }
5311 assert(recv_ring->completion_ptr != NULL);
5312 }
5313 #endif
5314
5315 while (!times_up) {
5316 #if HAVE_AIO
5317 if (loc_rcvaio > 0) {
5318 const struct aiocb *iocblist[1];
5319 struct aiocb *iocb;
5320 int error;
5321
5322 /*
5323 * POSIX doesn't define which order jobs of the same priority
5324 * are completed in on all systems. This hopes for FIFO.
5325 */
5326 iocb = recv_ring->completion_ptr;
5327 iocblist[0] = iocb;
5328 if (aio_suspend(iocblist, 1, NULL) == -1) {
5329 len = SOCKET_ERROR;
5330 } else {
5331 error = aio_error(iocb);
5332 if (error == 0) {
5333 len = aio_return(iocb);
5334 } else {
5335 errno = error;
5336 len = SOCKET_ERROR;
5337 }
5338 }
5339 } else
5340 #endif
5341 {
5342 len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0);
5343 }
5344 if (len == 0)
5345 break;
5346 if (len == SOCKET_ERROR ) {
5347 if (times_up) {
5348 break;
5349 }
5350 netperf_response.content.serv_errno = errno;
5351 send_response();
5352 exit(1);
5353 }
5354 bytes_received += len;
5355 receive_calls++;
5356
5357 #ifdef DIRTY
5358 /* we access the buffer after the recv() call now, rather than before */
5359 access_buffer(recv_ring->buffer_ptr,
5360 recv_size,
5361 tcp_stream_request->dirty_count,
5362 tcp_stream_request->clean_count);
5363 #endif /* DIRTY */
5364
5365 #if HAVE_AIO
5366 if (loc_rcvaio > 0) {
5367 struct aiocb *iocb;
5368
5369 iocb = recv_ring->completion_ptr;
5370 memset(iocb, 0, sizeof(*iocb));
5371 iocb->aio_nbytes = recv_size;
5372 iocb->aio_fildes = s_data;
5373 iocb->aio_buf = recv_ring->buffer_ptr;
5374 if (aio_read(iocb) != 0) {
5375 netperf_response.content.serv_errno = errno;
5376 send_response();
5377 exit(1);
5378 }
5379 }
5380 #endif
5381
5382 /* move to the next buffer in the recv_ring */
5383 recv_ring = recv_ring->next;
5384
5385 #ifdef PAUSE
5386 sleep(1);
5387 #endif /* PAUSE */
5388
5389 #ifdef DO_SELECT
5390 FD_SET(s_data,&readfds);
5391 select(s_data+1,&readfds,NULL,NULL,&timeout);
5392 #endif /* DO_SELECT */
5393
5394 }
5395
5396 /* perform a shutdown to signal the sender that */
5397 /* we have received all the data sent. raj 4/93 */
5398
5399 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR && !times_up) {
5400 netperf_response.content.serv_errno = errno;
5401 send_response();
5402 exit(1);
5403 }
5404
5405 cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time);
5406
5407 /* send the results to the sender */
5408
5409 if (debug) {
5410 fprintf(where,
5411 "recv_tcp_stream: got %g bytes\n",
5412 bytes_received);
5413 fprintf(where,
5414 "recv_tcp_stream: got %d recvs\n",
5415 receive_calls);
5416 fflush(where);
5417 }
5418
5419 tcp_stream_results->bytes_received = htond(bytes_received);
5420 tcp_stream_results->elapsed_time = elapsed_time;
5421 tcp_stream_results->recv_calls = receive_calls;
5422
5423 tcp_stream_results->cpu_method = cpu_method;
5424 tcp_stream_results->num_cpus = lib_num_loc_cpus;
5425
5426 if (tcp_stream_request->measure_cpu) {
5427 tcp_stream_results->cpu_util = calc_cpu_util(0.0);
5428 };
5429
5430 if (debug) {
5431 fprintf(where,
5432 "recv_tcp_stream: test complete, sending results.\n");
5433 fprintf(where,
5434 " bytes_received %g receive_calls %d\n",
5435 bytes_received,
5436 receive_calls);
5437 fprintf(where,
5438 " len %d\n",
5439 len);
5440 fflush(where);
5441 }
5442
5443 send_response();
5444
5445 /* we are now done with the sockets */
5446 close(s_data);
5447 close(s_listen);
5448
5449 }
5450
5451 /* This is the server-side routine for the tcp maerts test. It is
5452 implemented as one routine. I could break things-out somewhat, but
5453 didn't feel it was necessary. */
5454
5455 void
recv_tcp_maerts()5456 recv_tcp_maerts()
5457 {
5458
5459 struct sockaddr_storage myaddr_in, peeraddr_in;
5460 struct addrinfo *local_res;
5461 char local_name[BUFSIZ];
5462 char port_buffer[PORTBUFSIZE];
5463
5464 SOCKET s_listen,s_data;
5465 netperf_socklen_t addrlen;
5466 int len;
5467 unsigned int send_calls;
5468 float elapsed_time;
5469 double bytes_sent = 0.0 ;
5470
5471 struct ring_elt *send_ring;
5472
5473 struct tcp_maerts_request_struct *tcp_maerts_request;
5474 struct tcp_maerts_response_struct *tcp_maerts_response;
5475 struct tcp_maerts_results_struct *tcp_maerts_results;
5476
5477 tcp_maerts_request =
5478 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
5479 tcp_maerts_response =
5480 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
5481 tcp_maerts_results =
5482 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
5483
5484 if (debug) {
5485 fprintf(where,"netserver: recv_tcp_maerts: entered...\n");
5486 fflush(where);
5487 }
5488
5489 /* We want to set-up the listen socket with all the desired
5490 parameters and then let the initiator know that all is ready. If
5491 socket size defaults are to be used, then the initiator will have
5492 sent us 0's. If the socket sizes cannot be changed, then we will
5493 send-back what they are. If that information cannot be
5494 determined, then we send-back -1's for the sizes. If things go
5495 wrong for any reason, we will drop back ten yards and punt. */
5496
5497 /* If anything goes wrong, we want the remote to know about it. It
5498 would be best if the error that the remote reports to the user is
5499 the actual error we encountered, rather than some bogus
5500 unexpected response type message. */
5501
5502 if (debug) {
5503 fprintf(where,"recv_tcp_maerts: setting the response type...\n");
5504 fflush(where);
5505 }
5506
5507 netperf_response.content.response_type = TCP_MAERTS_RESPONSE;
5508
5509 if (debug) {
5510 fprintf(where,"recv_tcp_maerts: the response type is set...\n");
5511 fflush(where);
5512 }
5513
5514 /* We now alter the message_ptr variable to be at the desired */
5515 /* alignment with the desired offset. */
5516
5517 if (debug) {
5518 fprintf(where,"recv_tcp_maerts: requested alignment of %d\n",
5519 tcp_maerts_request->send_alignment);
5520 fflush(where);
5521 }
5522
5523 /* Grab a socket to listen on, and then listen on it. */
5524
5525 if (debug) {
5526 fprintf(where,"recv_tcp_maerts: grabbing a socket...\n");
5527 fflush(where);
5528 }
5529
5530 /* create_data_socket expects to find some things in the global */
5531 /* variables, so set the globals based on the values in the request. */
5532 /* once the socket has been created, we will set the response values */
5533 /* based on the updated value of those globals. raj 7/94 */
5534 lss_size_req = tcp_maerts_request->send_buf_size;
5535 lsr_size_req = tcp_maerts_request->recv_buf_size;
5536 loc_nodelay = tcp_maerts_request->no_delay;
5537 loc_rcvavoid = tcp_maerts_request->so_rcvavoid;
5538 loc_sndavoid = tcp_maerts_request->so_sndavoid;
5539
5540 set_hostname_and_port(local_name,
5541 port_buffer,
5542 nf_to_af(tcp_maerts_request->ipfamily),
5543 tcp_maerts_request->port);
5544
5545 local_res = complete_addrinfo(local_name,
5546 local_name,
5547 port_buffer,
5548 nf_to_af(tcp_maerts_request->ipfamily),
5549 SOCK_STREAM,
5550 IPPROTO_TCP,
5551 0);
5552
5553 s_listen = create_data_socket(local_res);
5554
5555 if (s_listen == INVALID_SOCKET) {
5556 netperf_response.content.serv_errno = errno;
5557 send_response();
5558 exit(1);
5559 }
5560
5561 #ifdef WIN32
5562 /* The test timer can fire during operations on the listening socket,
5563 so to make the start_timer below work we have to move
5564 it to close s_listen while we are blocked on accept. */
5565 win_kludge_socket2 = s_listen;
5566 #endif
5567
5568
5569 /* what sort of sizes did we end-up with? */
5570 if (tcp_maerts_request->send_size == 0) {
5571 if (lss_size > 0) {
5572 send_size = lss_size;
5573 }
5574 else {
5575 send_size = 4096;
5576 }
5577 }
5578 else {
5579 send_size = tcp_maerts_request->send_size;
5580 }
5581
5582 /* we want to set-up our recv_ring in a manner analagous to what we */
5583 /* do on the recving side. this is more for the sake of symmetry */
5584 /* than for the needs of say copy avoidance, but it might also be */
5585 /* more realistic - this way one could conceivably go with a */
5586 /* double-buffering scheme when taking the data an putting it into */
5587 /* the filesystem or something like that. raj 7/94 */
5588
5589 if (send_width == 0) {
5590 send_width = (lsr_size/send_size) + 1;
5591 if (send_width == 1) send_width++;
5592 }
5593
5594 send_ring = allocate_buffer_ring(send_width,
5595 send_size,
5596 tcp_maerts_request->send_alignment,
5597 tcp_maerts_request->send_offset);
5598
5599 if (debug) {
5600 fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n");
5601 fflush(where);
5602 }
5603
5604 /* Now, let's set-up the socket to listen for connections */
5605 if (listen(s_listen, 5) == SOCKET_ERROR) {
5606 netperf_response.content.serv_errno = errno;
5607 close(s_listen);
5608 send_response();
5609
5610 exit(1);
5611 }
5612
5613
5614 /* now get the port number assigned by the system */
5615 addrlen = sizeof(myaddr_in);
5616 if (getsockname(s_listen,
5617 (struct sockaddr *)&myaddr_in,
5618 &addrlen) == SOCKET_ERROR){
5619 netperf_response.content.serv_errno = errno;
5620 close(s_listen);
5621 send_response();
5622
5623 exit(1);
5624 }
5625
5626 /* Now myaddr_in contains the port and the internet address this is */
5627 /* returned to the sender also implicitly telling the sender that the */
5628 /* socket buffer sizing has been done. */
5629
5630 tcp_maerts_response->data_port_number =
5631 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
5632 netperf_response.content.serv_errno = 0;
5633
5634 /* But wait, there's more. If the initiator wanted cpu measurements, */
5635 /* then we must call the calibrate routine, which will return the max */
5636 /* rate back to the initiator. If the CPU was not to be measured, or */
5637 /* something went wrong with the calibration, we will return a -1 to */
5638 /* the initiator. */
5639
5640 tcp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */
5641 if (tcp_maerts_request->measure_cpu) {
5642 tcp_maerts_response->measure_cpu = 1;
5643 tcp_maerts_response->cpu_rate =
5644 calibrate_local_cpu(tcp_maerts_request->cpu_rate);
5645 }
5646 else {
5647 tcp_maerts_response->measure_cpu = 0;
5648 }
5649
5650 /* before we send the response back to the initiator, pull some of */
5651 /* the socket parms from the globals */
5652 tcp_maerts_response->send_buf_size = lss_size;
5653 tcp_maerts_response->recv_buf_size = lsr_size;
5654 tcp_maerts_response->no_delay = loc_nodelay;
5655 tcp_maerts_response->so_rcvavoid = loc_rcvavoid;
5656 tcp_maerts_response->so_sndavoid = loc_sndavoid;
5657 tcp_maerts_response->send_size = send_size;
5658
5659 send_response();
5660
5661 addrlen = sizeof(peeraddr_in);
5662
5663 /* we will start the timer before the accept() to be somewhat
5664 analagous to the starting of the timer before the connect() call
5665 in the TCP_STREAM test. raj 2002-06-21 */
5666
5667 start_timer(tcp_maerts_request->test_length);
5668
5669 /* Now it's time to start receiving data on the connection. We will
5670 first grab the apropriate counters and then start grabbing. */
5671
5672 cpu_start(tcp_maerts_request->measure_cpu);
5673
5674
5675 if ((s_data=accept(s_listen,
5676 (struct sockaddr *)&peeraddr_in,
5677 &addrlen)) == INVALID_SOCKET) {
5678 /* Let's just punt. The remote will be given some information */
5679 close(s_listen);
5680 exit(1);
5681 }
5682
5683 #ifdef WIN32
5684 /* this is used so the timer thread can close the socket out from */
5685 /* under us, which to date is the easiest/cleanest/least */
5686 /* Windows-specific way I can find to force the winsock calls to */
5687 /* return WSAEINTR with the test is over. anything that will run on */
5688 /* 95 and NT and is closer to what netperf expects from Unix signals */
5689 /* and such would be appreciated raj 1/96 */
5690 win_kludge_socket = s_data;
5691 win_kludge_socket2 = INVALID_SOCKET;
5692 #endif /* WIN32 */
5693
5694 #ifdef KLUDGE_SOCKET_OPTIONS
5695
5696 /* this is for those systems which *INCORRECTLY* fail to pass
5697 attributes across an accept() call. Including this goes against
5698 my better judgement :( raj 11/95 */
5699
5700 kludge_socket_options(s_data);
5701
5702 #endif /* KLUDGE_SOCKET_OPTIONS */
5703
5704 /* The loop will exit when the sender does a shutdown, which will */
5705 /* return a length of zero */
5706
5707 bytes_sent = 0.0;
5708 send_calls = 0;
5709
5710 len = 0; /* nt-lint; len is not initialized (printf far below) if
5711 times_up initially true.*/
5712 times_up = 0; /* must remember to initialize this little beauty */
5713 while (!times_up) {
5714
5715 #ifdef DIRTY
5716 /* we want to dirty some number of consecutive integers in the buffer */
5717 /* we are about to send. we may also want to bring some number of */
5718 /* them cleanly into the cache. The clean ones will follow any dirty */
5719 /* ones into the cache. */
5720
5721 access_buffer(send_ring->buffer_ptr,
5722 send_size,
5723 tcp_maerts_request->dirty_count,
5724 tcp_maerts_request->clean_count);
5725
5726 #endif /* DIRTY */
5727
5728 if((len=send(s_data,
5729 send_ring->buffer_ptr,
5730 send_size,
5731 0)) != send_size) {
5732 if ((len >=0) || SOCKET_EINTR(len)) {
5733 /* the test was interrupted, must be the end of test */
5734 break;
5735 }
5736 netperf_response.content.serv_errno = errno;
5737 send_response();
5738 exit(1);
5739 }
5740
5741 bytes_sent += len;
5742 send_calls++;
5743
5744 /* more to the next buffer in the send_ring */
5745 send_ring = send_ring->next;
5746
5747 }
5748
5749 /* perform a shutdown to signal the sender that */
5750 /* we have received all the data sent. raj 4/93 */
5751
5752 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
5753 netperf_response.content.serv_errno = errno;
5754 send_response();
5755 exit(1);
5756 }
5757
5758 /* hang a recv() off the socket to block until the remote has
5759 brought all the data up into the application. it will do a
5760 shutdown to cause a FIN to be sent our way. We will assume that
5761 any exit from the recv() call is good... raj 4/93 */
5762
5763 recv(s_data, send_ring->buffer_ptr, send_size, 0);
5764
5765
5766 cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time);
5767
5768 /* send the results to the sender */
5769
5770 if (debug) {
5771 fprintf(where,
5772 "recv_tcp_maerts: got %g bytes\n",
5773 bytes_sent);
5774 fprintf(where,
5775 "recv_tcp_maerts: got %d sends\n",
5776 send_calls);
5777 fflush(where);
5778 }
5779
5780 tcp_maerts_results->bytes_sent = htond(bytes_sent);
5781 tcp_maerts_results->elapsed_time = elapsed_time;
5782 tcp_maerts_results->send_calls = send_calls;
5783
5784 if (tcp_maerts_request->measure_cpu) {
5785 tcp_maerts_results->cpu_util = calc_cpu_util(0.0);
5786 };
5787
5788 if (debug) {
5789 fprintf(where,
5790 "recv_tcp_maerts: test complete, sending results.\n");
5791 fprintf(where,
5792 " bytes_sent %g send_calls %d\n",
5793 bytes_sent,
5794 send_calls);
5795 fprintf(where,
5796 " len %d\n",
5797 len);
5798 fflush(where);
5799 }
5800
5801 tcp_maerts_results->cpu_method = cpu_method;
5802 tcp_maerts_results->num_cpus = lib_num_loc_cpus;
5803 send_response();
5804
5805 /* we are now done with the sockets */
5806 close(s_data);
5807 close(s_listen);
5808
5809 }
5810
5811
5812 /* this routine implements the sending (netperf) side of the TCP_RR */
5813 /* test. */
5814 #ifndef WANT_MIGRATION
5815 void
send_tcp_rr(char remote_host[])5816 send_tcp_rr(char remote_host[])
5817 {
5818
5819 char *tput_title = "\
5820 Local /Remote\n\
5821 Socket Size Request Resp. Elapsed Trans.\n\
5822 Send Recv Size Size Time Rate \n\
5823 bytes Bytes bytes bytes secs. per sec \n\n";
5824
5825 char *tput_title_band = "\
5826 Local /Remote\n\
5827 Socket Size Request Resp. Elapsed \n\
5828 Send Recv Size Size Time Throughput \n\
5829 bytes Bytes bytes bytes secs. %s/sec \n\n";
5830
5831 char *tput_fmt_0 =
5832 "%7.2f %s\n";
5833
5834 char *tput_fmt_1_line_1 = "\
5835 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
5836 char *tput_fmt_1_line_2 = "\
5837 %-6d %-6d\n";
5838
5839 char *cpu_title = "\
5840 Local /Remote\n\
5841 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
5842 Send Recv Size Size Time Rate local remote local remote\n\
5843 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
5844
5845 char *cpu_title_tput = "\
5846 Local /Remote\n\
5847 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\
5848 Send Recv Size Size Time %-8.8s local remote local remote\n\
5849 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
5850
5851 char *cpu_title_latency = "\
5852 Local /Remote\n\
5853 Socket Size Request Resp. Elapsed Latency CPU CPU S.dem S.dem\n\
5854 Send Recv Size Size Time usecs local remote local remote\n\
5855 bytes bytes bytes bytes secs. per tran %% %c %% %c us/Tr us/Tr\n\n";
5856
5857 char *cpu_fmt_0 =
5858 "%6.3f %c %s\n";
5859
5860 char *cpu_fmt_1_line_1 = "\
5861 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
5862
5863 char *cpu_fmt_1_line_2 = "\
5864 %-6d %-6d\n";
5865
5866 char *ksink_fmt = "\
5867 Alignment Offset RoundTrip Trans Throughput\n\
5868 Local Remote Local Remote Latency Rate %-8.8s/s\n\
5869 Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\
5870 %5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n";
5871
5872
5873 int timed_out = 0;
5874 float elapsed_time;
5875
5876 int len;
5877 char *temp_message_ptr;
5878 int nummessages;
5879 SOCKET send_socket;
5880 int trans_remaining;
5881 double bytes_xferd;
5882
5883 struct ring_elt *send_ring;
5884 struct ring_elt *recv_ring;
5885
5886 int rsp_bytes_left;
5887 int rsp_bytes_recvd;
5888
5889 float local_cpu_utilization;
5890 float local_service_demand;
5891 float remote_cpu_utilization;
5892 float remote_service_demand;
5893 double thruput;
5894
5895 struct addrinfo *local_res;
5896 struct addrinfo *remote_res;
5897
5898 struct tcp_rr_request_struct *tcp_rr_request;
5899 struct tcp_rr_response_struct *tcp_rr_response;
5900 struct tcp_rr_results_struct *tcp_rr_result;
5901
5902 #ifdef WANT_FIRST_BURST
5903 #define REQUEST_CWND_INITIAL 2
5904 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
5905 Unix and the state of New Jersey - both were simple an unspoiled.
5906 then it was realized that some stacks are quite picky about
5907 initial congestion windows and a non-trivial initial burst of
5908 requests would not be individual segments even with TCP_NODELAY
5909 set. so, we have to start tracking a poor-man's congestion window
5910 up here in window space because we want to try to make something
5911 happen that frankly, we cannot guarantee with the specification
5912 of TCP. ain't that grand?-) raj 2006-01-30 */
5913 int requests_outstanding = 0;
5914 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having
5915 three requests
5916 outstanding at the
5917 beginning of the test
5918 is ok with TCP stacks
5919 of interest. the first
5920 two will come from our
5921 first_burst loop, and
5922 the third from our
5923 regularly scheduled
5924 send */
5925 #endif
5926
5927 tcp_rr_request =
5928 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
5929 tcp_rr_response=
5930 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
5931 tcp_rr_result =
5932 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
5933
5934 #ifdef WANT_HISTOGRAM
5935 if (verbosity > 1) {
5936 time_hist = HIST_new();
5937 }
5938 #endif /* WANT_HISTOGRAM */
5939
5940 /* since we are now disconnected from the code that established the */
5941 /* control socket, and since we want to be able to use different */
5942 /* protocols and such, we are passed the name of the remote host and */
5943 /* must turn that into the test specific addressing information. */
5944
5945 complete_addrinfos(&remote_res,
5946 &local_res,
5947 remote_host,
5948 SOCK_STREAM,
5949 IPPROTO_TCP,
5950 0);
5951
5952 if ( print_headers ) {
5953 print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res);
5954 }
5955
5956 /* initialize a few counters */
5957
5958 send_ring = NULL;
5959 recv_ring = NULL;
5960 confidence_iteration = 1;
5961 init_stat();
5962
5963 /* we have a great-big while loop which controls the number of times */
5964 /* we run a particular test. this is for the calculation of a */
5965 /* confidence interval (I really should have stayed awake during */
5966 /* probstats :). If the user did not request confidence measurement */
5967 /* (no confidence is the default) then we will only go though the */
5968 /* loop once. the confidence stuff originates from the folks at IBM */
5969
5970 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
5971 (confidence_iteration <= iteration_min)) {
5972
5973 /* initialize a few counters. we have to remember that we might be */
5974 /* going through the loop more than once. */
5975
5976 nummessages = 0;
5977 bytes_xferd = 0.0;
5978 times_up = 0;
5979 timed_out = 0;
5980 trans_remaining = 0;
5981
5982 #ifdef WANT_FIRST_BURST
5983 /* we have to remember to reset the number of transactions
5984 outstanding and the "congestion window for each new
5985 iteration. raj 2006-01-31 */
5986 requests_outstanding = 0;
5987 request_cwnd = REQUEST_CWND_INITIAL;
5988 #endif
5989
5990
5991 /* set-up the data buffers with the requested alignment and offset. */
5992 /* since this is a request/response test, default the send_width and */
5993 /* recv_width to 1 and not two raj 7/94 */
5994
5995 if (send_width == 0) send_width = 1;
5996 if (recv_width == 0) recv_width = 1;
5997
5998 if (send_ring == NULL) {
5999 send_ring = allocate_buffer_ring(send_width,
6000 req_size,
6001 local_send_align,
6002 local_send_offset);
6003 }
6004
6005 if (recv_ring == NULL) {
6006 recv_ring = allocate_buffer_ring(recv_width,
6007 rsp_size,
6008 local_recv_align,
6009 local_recv_offset);
6010 }
6011
6012 /*set up the data socket */
6013 send_socket = create_data_socket(local_res);
6014
6015 if (send_socket == INVALID_SOCKET){
6016 perror("netperf: send_tcp_rr: tcp stream data socket");
6017 exit(1);
6018 }
6019
6020 if (debug) {
6021 fprintf(where,"send_tcp_rr: send_socket obtained...\n");
6022 }
6023
6024 /* If the user has requested cpu utilization measurements, we must */
6025 /* calibrate the cpu(s). We will perform this task within the tests */
6026 /* themselves. If the user has specified the cpu rate, then */
6027 /* calibrate_local_cpu will return rather quickly as it will have */
6028 /* nothing to do. If local_cpu_rate is zero, then we will go through */
6029 /* all the "normal" calibration stuff and return the rate back.*/
6030
6031 if (local_cpu_usage) {
6032 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
6033 }
6034
6035 if (!no_control) {
6036 /* Tell the remote end to do a listen. The server alters the
6037 socket paramters on the other side at this point, hence the
6038 reason for all the values being passed in the setup
6039 message. If the user did not specify any of the parameters,
6040 they will be passed as 0, which will indicate to the remote
6041 that no changes beyond the system's default should be
6042 used. Alignment is the exception, it will default to 8, which
6043 will be no alignment alterations. */
6044
6045 netperf_request.content.request_type = DO_TCP_RR;
6046 tcp_rr_request->recv_buf_size = rsr_size_req;
6047 tcp_rr_request->send_buf_size = rss_size_req;
6048 tcp_rr_request->recv_alignment = remote_recv_align;
6049 tcp_rr_request->recv_offset = remote_recv_offset;
6050 tcp_rr_request->send_alignment = remote_send_align;
6051 tcp_rr_request->send_offset = remote_send_offset;
6052 tcp_rr_request->request_size = req_size;
6053 tcp_rr_request->response_size = rsp_size;
6054 tcp_rr_request->no_delay = rem_nodelay;
6055 tcp_rr_request->measure_cpu = remote_cpu_usage;
6056 tcp_rr_request->cpu_rate = remote_cpu_rate;
6057 tcp_rr_request->so_rcvavoid = rem_rcvavoid;
6058 tcp_rr_request->so_sndavoid = rem_sndavoid;
6059 if (test_time) {
6060 tcp_rr_request->test_length = test_time;
6061 }
6062 else {
6063 tcp_rr_request->test_length = test_trans * -1;
6064 }
6065 tcp_rr_request->port = atoi(remote_data_port);
6066 tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
6067
6068 if (debug > 1) {
6069 fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n");
6070 }
6071
6072 send_request();
6073
6074 /* The response from the remote will contain all of the relevant
6075 socket parameters for this test type. We will put them back
6076 into the variables here so they can be displayed if desired.
6077 The remote will have calibrated CPU if necessary, and will
6078 have done all the needed set-up we will have calibrated the
6079 cpu locally before sending the request, and will grab the
6080 counter value right after the connect returns. The remote
6081 will grab the counter right after the accept call. This saves
6082 the hassle of extra messages being sent for the TCP
6083 tests. */
6084
6085 recv_response();
6086
6087 if (!netperf_response.content.serv_errno) {
6088 if (debug)
6089 fprintf(where,"remote listen done.\n");
6090 rsr_size = tcp_rr_response->recv_buf_size;
6091 rss_size = tcp_rr_response->send_buf_size;
6092 rem_nodelay = tcp_rr_response->no_delay;
6093 remote_cpu_usage = tcp_rr_response->measure_cpu;
6094 remote_cpu_rate = tcp_rr_response->cpu_rate;
6095 /* make sure that port numbers are in network order */
6096 set_port_number(remote_res,(short)tcp_rr_response->data_port_number);
6097 }
6098 else {
6099 Set_errno(netperf_response.content.serv_errno);
6100 fprintf(where,
6101 "netperf: remote error %d",
6102 netperf_response.content.serv_errno);
6103 perror("");
6104 fflush(where);
6105
6106 exit(1);
6107 }
6108 }
6109
6110 #ifdef WANT_DEMO
6111 demo_rr_setup(1000);
6112 #endif
6113
6114 /*Connect up to the remote port on the data socket */
6115 if (connect(send_socket,
6116 remote_res->ai_addr,
6117 remote_res->ai_addrlen) == INVALID_SOCKET){
6118 perror("netperf: data socket connect failed");
6119
6120 exit(1);
6121 }
6122
6123 #ifdef WIN32
6124 /* this is used so the timer thread can close the socket out from */
6125 /* under us, which to date is the easiest/cleanest/least */
6126 /* Windows-specific way I can find to force the winsock calls to */
6127 /* return WSAEINTR with the test is over. anything that will run on */
6128 /* 95 and NT and is closer to what netperf expects from Unix signals */
6129 /* and such would be appreciated raj 1/96 */
6130 win_kludge_socket = send_socket;
6131 #endif /* WIN32 */
6132
6133 /* Data Socket set-up is finished. If there were problems, either the */
6134 /* connect would have failed, or the previous response would have */
6135 /* indicated a problem. I failed to see the value of the extra */
6136 /* message after the accept on the remote. If it failed, we'll see it */
6137 /* here. If it didn't, we might as well start pumping data. */
6138
6139 /* Set-up the test end conditions. For a request/response test, they */
6140 /* can be either time or transaction based. */
6141
6142 if (test_time) {
6143 /* The user wanted to end the test after a period of time. */
6144 times_up = 0;
6145 trans_remaining = 0;
6146 start_timer(test_time);
6147 }
6148 else {
6149 /* The tester wanted to send a number of bytes. */
6150 trans_remaining = test_bytes;
6151 times_up = 1;
6152 }
6153
6154 /* The cpu_start routine will grab the current time and possibly */
6155 /* value of the idle counter for later use in measuring cpu */
6156 /* utilization and/or service demand and thruput. */
6157
6158 cpu_start(local_cpu_usage);
6159
6160 #ifdef WANT_INTERVALS
6161 INTERVALS_INIT();
6162 #endif /* WANT_INTERVALS */
6163
6164 /* We use an "OR" to control test execution. When the test is */
6165 /* controlled by time, the byte count check will always return false. */
6166 /* When the test is controlled by byte count, the time test will */
6167 /* always return false. When the test is finished, the whole */
6168 /* expression will go false and we will stop sending data. I think I */
6169 /* just arbitrarily decrement trans_remaining for the timed test, but */
6170 /* will not do that just yet... One other question is whether or not */
6171 /* the send buffer and the receive buffer should be the same buffer. */
6172
6173 #ifdef WANT_DEMO
6174 if (demo_mode) {
6175 demo_first_timestamp();
6176 }
6177 #endif
6178
6179 while ((!times_up) || (trans_remaining > 0)) {
6180 /* send the request. we assume that if we use a blocking socket, */
6181 /* the request will be sent at one shot. */
6182
6183 #ifdef WANT_FIRST_BURST
6184 /* we can inject no more than request_cwnd, which will grow with
6185 time, and no more than first_burst_size. we don't use <= to
6186 account for the "regularly scheduled" send call. of course
6187 that makes it more a "max_outstanding_ than a
6188 "first_burst_size" but for now we won't fix the names. also,
6189 I suspect the extra check against < first_burst_size is
6190 redundant since later I expect to make sure that request_cwnd
6191 can never get larger than first_burst_size, but just at the
6192 moment I'm feeling like a belt and suspenders kind of
6193 programmer. raj 2006-01-30 */
6194 while ((first_burst_size > 0) &&
6195 (requests_outstanding < request_cwnd) &&
6196 (requests_outstanding < first_burst_size)) {
6197 if (debug) {
6198 fprintf(where,
6199 "injecting, req_outstndng %d req_cwnd %d burst %d\n",
6200 requests_outstanding,
6201 request_cwnd,
6202 first_burst_size);
6203 }
6204 if ((len = send(send_socket,
6205 send_ring->buffer_ptr,
6206 req_size,
6207 0)) != req_size) {
6208 /* we should never hit the end of the test in the first burst */
6209 perror("send_tcp_rr: initial burst data send error");
6210 exit(-1);
6211 }
6212 requests_outstanding += 1;
6213 }
6214
6215 #endif /* WANT_FIRST_BURST */
6216
6217 #ifdef WANT_HISTOGRAM
6218 if (verbosity > 1) {
6219 /* timestamp just before our call to send, and then again just
6220 after the receive raj 8/94 */
6221 /* but only if we are actually going to display one. raj
6222 2007-02-07 */
6223
6224 HIST_timestamp(&time_one);
6225 }
6226 #endif /* WANT_HISTOGRAM */
6227
6228 if ((len = send(send_socket,
6229 send_ring->buffer_ptr,
6230 req_size,
6231 0)) != req_size) {
6232 if (SOCKET_EINTR(len) || (errno == 0)) {
6233 /* we hit the end of a */
6234 /* timed test. */
6235 timed_out = 1;
6236 break;
6237 }
6238 perror("send_tcp_rr: data send error");
6239 exit(1);
6240 }
6241 send_ring = send_ring->next;
6242
6243 #ifdef WANT_FIRST_BURST
6244 requests_outstanding += 1;
6245 #endif
6246
6247 /* receive the response */
6248 rsp_bytes_left = rsp_size;
6249 temp_message_ptr = recv_ring->buffer_ptr;
6250 while(rsp_bytes_left > 0) {
6251 if((rsp_bytes_recvd=recv(send_socket,
6252 temp_message_ptr,
6253 rsp_bytes_left,
6254 0)) == SOCKET_ERROR || rsp_bytes_recvd == 0) {
6255 if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
6256 /* We hit the end of a timed test. */
6257 timed_out = 1;
6258 break;
6259 }
6260 perror("send_tcp_rr: data recv error");
6261 exit(1);
6262 }
6263 rsp_bytes_left -= rsp_bytes_recvd;
6264 temp_message_ptr += rsp_bytes_recvd;
6265 }
6266 recv_ring = recv_ring->next;
6267
6268 #ifdef WANT_FIRST_BURST
6269 /* so, since we've gotten a response back, update the
6270 bookkeeping accordingly. there is one less request
6271 outstanding and we can put one more out there than before. */
6272 requests_outstanding -= 1;
6273 if (request_cwnd < first_burst_size) {
6274 request_cwnd += 1;
6275 if (debug) {
6276 fprintf(where,
6277 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
6278 request_cwnd,
6279 first_burst_size,
6280 requests_outstanding);
6281 }
6282 }
6283 #endif
6284 if (timed_out) {
6285 /* we may have been in a nested while loop - we need */
6286 /* another call to break. */
6287 break;
6288 }
6289
6290 #ifdef WANT_HISTOGRAM
6291 if (verbosity > 1) {
6292 HIST_timestamp(&time_two);
6293 HIST_add(time_hist,delta_micro(&time_one,&time_two));
6294 }
6295 #endif /* WANT_HISTOGRAM */
6296
6297 #ifdef WANT_DEMO
6298 demo_rr_interval(1);
6299 #endif
6300
6301 #ifdef WANT_INTERVALS
6302 INTERVALS_WAIT();
6303 #endif /* WANT_INTERVALS */
6304
6305 nummessages++;
6306 if (trans_remaining) {
6307 trans_remaining--;
6308 }
6309
6310 if (debug > 3) {
6311 if ((nummessages % 100) == 0) {
6312 fprintf(where,
6313 "Transaction %d completed\n",
6314 nummessages);
6315 fflush(where);
6316 }
6317 }
6318 }
6319
6320 /* At this point we used to call shutdown on the data socket to be
6321 sure all the data was delivered, but this was not germane in a
6322 request/response test, and it was causing the tests to "hang"
6323 when they were being controlled by time. So, I have replaced
6324 this shutdown call with a call to close that can be found later
6325 in the procedure. */
6326
6327 /* this call will always give us the elapsed time for the test,
6328 and will also store-away the necessaries for cpu utilization */
6329
6330 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
6331 /* measured? how long */
6332 /* did we really run? */
6333
6334 #if defined(WANT_INTERVALS)
6335 #ifdef WIN32
6336 stop_itimer();
6337 #endif
6338 #endif /* WANT_INTERVALS */
6339
6340 if (!no_control) {
6341 /* Get the statistics from the remote end. The remote will have
6342 calculated CPU utilization. If it wasn't supposed to care, it
6343 will return obvious values. */
6344
6345 recv_response();
6346 if (!netperf_response.content.serv_errno) {
6347 if (debug)
6348 fprintf(where,"remote results obtained\n");
6349 }
6350 else {
6351 Set_errno(netperf_response.content.serv_errno);
6352 fprintf(where,"netperf: remote error %d",
6353 netperf_response.content.serv_errno);
6354 perror("");
6355 fflush(where);
6356 exit(1);
6357 }
6358 }
6359
6360 /* We now calculate what our "throughput" was for the test. */
6361
6362 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
6363 thruput = nummessages/elapsed_time;
6364
6365 if (local_cpu_usage || remote_cpu_usage) {
6366 /* We must now do a little math for service demand and cpu
6367 utilization for the system(s) Of course, some of the
6368 information might be bogus because there was no idle counter in
6369 the kernel(s). We need to make a note of this for the user's
6370 benefit... */
6371 if (local_cpu_usage) {
6372 local_cpu_utilization = calc_cpu_util(0.0);
6373 /* since calc_service demand is doing ms/Kunit we will
6374 multiply the number of transaction by 1024 to get "good"
6375 numbers */
6376 local_service_demand = calc_service_demand((double) nummessages*1024,
6377 0.0,
6378 0.0,
6379 0);
6380 }
6381 else {
6382 local_cpu_utilization = (float) -1.0;
6383 local_service_demand = (float) -1.0;
6384 }
6385
6386 if (remote_cpu_usage) {
6387 remote_cpu_utilization = tcp_rr_result->cpu_util;
6388 /* since calc_service demand is doing ms/Kunit we will
6389 multiply the number of transaction by 1024 to get "good"
6390 numbers */
6391 remote_service_demand = calc_service_demand((double) nummessages*1024,
6392 0.0,
6393 remote_cpu_utilization,
6394 tcp_rr_result->num_cpus);
6395 }
6396 else {
6397 remote_cpu_utilization = (float) -1.0;
6398 remote_service_demand = (float) -1.0;
6399 }
6400
6401 }
6402 else {
6403 /* we were not measuring cpu, for the confidence stuff, we */
6404 /* should make it -1.0 */
6405 local_cpu_utilization = (float) -1.0;
6406 local_service_demand = (float) -1.0;
6407 remote_cpu_utilization = (float) -1.0;
6408 remote_service_demand = (float) -1.0;
6409 }
6410
6411 /* at this point, we want to calculate the confidence information.
6412 if debugging is on, calculate_confidence will print-out the
6413 parameters we pass it */
6414
6415 calculate_confidence(confidence_iteration,
6416 elapsed_time,
6417 thruput,
6418 local_cpu_utilization,
6419 remote_cpu_utilization,
6420 local_service_demand,
6421 remote_service_demand);
6422
6423
6424 confidence_iteration++;
6425
6426 /* we are now done with the socket, so close it */
6427 close(send_socket);
6428
6429 }
6430
6431 retrieve_confident_values(&elapsed_time,
6432 &thruput,
6433 &local_cpu_utilization,
6434 &remote_cpu_utilization,
6435 &local_service_demand,
6436 &remote_service_demand);
6437
6438 /* We are now ready to print all the information. If the user has
6439 specified zero-level verbosity, we will just print the local
6440 service demand, or the remote service demand. If the user has
6441 requested verbosity level 1, he will get the basic "streamperf"
6442 numbers. If the user has specified a verbosity of greater than 1,
6443 we will display a veritable plethora of background information
6444 from outside of this block as it it not cpu_measurement
6445 specific... */
6446
6447 if (confidence < 0) {
6448 /* we did not hit confidence, but were we asked to look for it? */
6449 if (iteration_max > 1) {
6450 display_confidence();
6451 }
6452 }
6453
6454 if (local_cpu_usage || remote_cpu_usage) {
6455 local_cpu_method = format_cpu_method(cpu_method);
6456 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
6457
6458 switch (verbosity) {
6459 case 0:
6460 if (local_cpu_usage) {
6461 fprintf(where,
6462 cpu_fmt_0,
6463 local_service_demand,
6464 local_cpu_method,
6465 ((print_headers) ||
6466 (result_brand == NULL)) ? "" : result_brand);
6467 }
6468 else {
6469 fprintf(where,
6470 cpu_fmt_0,
6471 remote_service_demand,
6472 remote_cpu_method,
6473 ((print_headers) ||
6474 (result_brand == NULL)) ? "" : result_brand);
6475 }
6476 break;
6477 case 1:
6478 case 2:
6479 if (print_headers) {
6480 if ('x' == libfmt) {
6481 fprintf(where,
6482 cpu_title,
6483 local_cpu_method,
6484 remote_cpu_method);
6485 }
6486 else {
6487 fprintf(where,
6488 cpu_title_tput,
6489 format_units(),
6490 local_cpu_method,
6491 remote_cpu_method);
6492 }
6493 }
6494
6495 fprintf(where,
6496 cpu_fmt_1_line_1, /* the format string */
6497 lss_size, /* local sendbuf size */
6498 lsr_size,
6499 req_size, /* how large were the requests */
6500 rsp_size, /* guess */
6501 elapsed_time, /* how long was the test */
6502 ('x' == libfmt) ? thruput :
6503 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6504 1.0),
6505 local_cpu_utilization, /* local cpu */
6506 remote_cpu_utilization, /* remote cpu */
6507 local_service_demand, /* local service demand */
6508 remote_service_demand, /* remote service demand */
6509 ((print_headers) ||
6510 (result_brand == NULL)) ? "" : result_brand);
6511 fprintf(where,
6512 cpu_fmt_1_line_2,
6513 rss_size,
6514 rsr_size);
6515 break;
6516 }
6517 }
6518 else {
6519 /* The tester did not wish to measure service demand. */
6520
6521 switch (verbosity) {
6522 case 0:
6523 fprintf(where,
6524 tput_fmt_0,
6525 ('x' == libfmt) ? thruput :
6526 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6527 1.0),
6528 ((print_headers) ||
6529 (result_brand == NULL)) ? "" : result_brand);
6530 break;
6531 case 1:
6532 case 2:
6533 if (print_headers) {
6534 fprintf(where,
6535 ('x' == libfmt) ? tput_title : tput_title_band,
6536 format_units());
6537 }
6538
6539 fprintf(where,
6540 tput_fmt_1_line_1, /* the format string */
6541 lss_size,
6542 lsr_size,
6543 req_size, /* how large were the requests */
6544 rsp_size, /* how large were the responses */
6545 elapsed_time, /* how long did it take */
6546 /* are we trans or do we need to convert to bytes then
6547 bits? at this point, thruput is in our "confident"
6548 transactions per second. we can convert to a
6549 bidirectional bitrate by multiplying that by the sum
6550 of the req_size and rsp_size. we pass that to
6551 calc_thruput_interval_omni with an elapsed time of
6552 1.0 s to get it converted to [kmg]bits/s or
6553 [KMG]Bytes/s */
6554 ('x' == libfmt) ? thruput :
6555 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6556 1.0),
6557 ((print_headers) ||
6558 (result_brand == NULL)) ? "" : result_brand);
6559 fprintf(where,
6560 tput_fmt_1_line_2,
6561 rss_size, /* remote recvbuf size */
6562 rsr_size);
6563
6564 break;
6565 }
6566 }
6567
6568 /* it would be a good thing to include information about some of the */
6569 /* other parameters that may have been set for this test, but at the */
6570 /* moment, I do not wish to figure-out all the formatting, so I will */
6571 /* just put this comment here to help remind me that it is something */
6572 /* that should be done at a later time. */
6573
6574 /* how to handle the verbose information in the presence of */
6575 /* confidence intervals is yet to be determined... raj 11/94 */
6576 if (verbosity > 1) {
6577 /* The user wanted to know it all, so we will give it to him. */
6578 /* This information will include as much as we can find about */
6579 /* TCP statistics, the alignments of the sends and receives */
6580 /* and all that sort of rot... */
6581
6582 /* normally, you might think that if we were messing about with
6583 the value of libfmt we would need to put it back again, but
6584 since this is basically the last thing we are going to do with
6585 it, it does not matter. so there :) raj 2007-06-08 */
6586 /* if the user was asking for transactions, then we report
6587 megabits per second for the unidirectional throughput,
6588 otherwise we use the desired units. */
6589 if ('x' == libfmt) {
6590 libfmt = 'm';
6591 }
6592
6593 fprintf(where,
6594 ksink_fmt,
6595 format_units(),
6596 local_send_align,
6597 remote_recv_offset,
6598 local_send_offset,
6599 remote_recv_offset,
6600 /* if the user has enable burst mode, we have to remember
6601 to account for that in the number of transactions
6602 outstanding at any one time. otherwise we will
6603 underreport the latency of individual
6604 transactions. learned from saf by raj 2007-06-08 */
6605 (((double)1.0/thruput)*(double)1000000.0) *
6606 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)),
6607 thruput,
6608 calc_thruput_interval_omni(thruput * (double)req_size,1.0),
6609 calc_thruput_interval_omni(thruput * (double)rsp_size,1.0));
6610
6611 #ifdef WANT_HISTOGRAM
6612 fprintf(where,"\nHistogram of request/response times\n");
6613 fflush(where);
6614 HIST_report(time_hist);
6615 #endif /* WANT_HISTOGRAM */
6616
6617 }
6618
6619 }
6620 #endif /* WANT_MIGRATION */
6621
6622 #if defined(__linux)
6623 /*
6624 * Linux has this odd behavior where if the socket buffers are larger than
6625 * a device's txqueuelen, the kernel will silently drop transmits which would
6626 * not fit into the tx queue, and not pass an ENOBUFS error back to the
6627 * application. As a result, a UDP stream test can report absurd transmit
6628 * bandwidths (like 20Gb/s on a 1GbE NIC). This behavior can be avoided if
6629 * you request extended error reporting on the socket. This is done by
6630 * setting the IP_RECVERR socket option at the IP level.
6631 */
6632 static void
enable_enobufs(int s)6633 enable_enobufs(int s)
6634 {
6635 int on = 1;
6636
6637 /* Per Brian Ginsbach, the likes of SLES12 do not have "ip" listed
6638 in /etc/protocols and others may have an incorrect value. At his
6639 suggestion, we'll just go with IPPROTO_IP. And while I am here,
6640 perhaps we should be trying IPPROTO_IPV6 if that fails */
6641 if (setsockopt(s, IPPROTO_IP, IP_RECVERR, (char *)&on, sizeof(on)) < 0) {
6642 if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVERR, (char *)&on, sizeof(on)) < 0) {
6643 fprintf(where, "%s failed: setsockopt (errno %d)\n",__FUNCTION__,errno);
6644 fflush(where);
6645 return;
6646 }
6647 }
6648 }
6649 #endif
6650
6651 #ifndef WANT_MIGRATION
6652 void
send_udp_stream(char remote_host[])6653 send_udp_stream(char remote_host[])
6654 {
6655 /**********************************************************************/
6656 /* */
6657 /* UDP Unidirectional Send Test */
6658 /* */
6659 /**********************************************************************/
6660
6661 #define UDP_LENGTH_MAX 0XFFFF - 28
6662
6663 char *tput_title = "\
6664 Socket Message Elapsed Messages \n\
6665 Size Size Time Okay Errors Throughput\n\
6666 bytes bytes secs # # %s/sec\n\n";
6667
6668 char *tput_fmt_0 =
6669 "%7.2f\n";
6670
6671 char *tput_fmt_1 = "\
6672 %6d %6d %-7.2f %7d %6d %7.2f\n\
6673 %6d %-7.2f %7d %7.2f\n\n";
6674
6675
6676 char *cpu_title = "\
6677 Socket Message Elapsed Messages CPU Service\n\
6678 Size Size Time Okay Errors Throughput Util Demand\n\
6679 bytes bytes secs # # %s/sec %% %c%c us/KB\n\n";
6680
6681 char *cpu_fmt_0 =
6682 "%6.2f %c\n";
6683
6684 char *cpu_fmt_1 = "\
6685 %6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
6686 %6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
6687
6688 unsigned int messages_recvd;
6689 unsigned int messages_sent;
6690 unsigned int failed_sends;
6691
6692 float elapsed_time,
6693 local_cpu_utilization,
6694 remote_cpu_utilization;
6695
6696 float local_service_demand, remote_service_demand;
6697 double local_thruput, remote_thruput;
6698 double bytes_sent;
6699 double bytes_recvd;
6700
6701
6702 int len;
6703 struct ring_elt *send_ring;
6704 SOCKET data_socket;
6705
6706 unsigned int sum_messages_sent;
6707 unsigned int sum_messages_recvd;
6708 unsigned int sum_failed_sends;
6709 double sum_local_thruput;
6710
6711 struct addrinfo *local_res;
6712 struct addrinfo *remote_res;
6713
6714 struct udp_stream_request_struct *udp_stream_request;
6715 struct udp_stream_response_struct *udp_stream_response;
6716 struct udp_stream_results_struct *udp_stream_results;
6717
6718 udp_stream_request =
6719 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
6720 udp_stream_response =
6721 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
6722 udp_stream_results =
6723 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
6724
6725 #ifdef WANT_HISTOGRAM
6726 if (verbosity > 1) {
6727 time_hist = HIST_new();
6728 }
6729 #endif /* WANT_HISTOGRAM */
6730
6731 /* since we are now disconnected from the code that established the */
6732 /* control socket, and since we want to be able to use different */
6733 /* protocols and such, we are passed the name of the remote host and */
6734 /* must turn that into the test specific addressing information. */
6735
6736 complete_addrinfos(&remote_res,
6737 &local_res,
6738 remote_host,
6739 SOCK_DGRAM,
6740 IPPROTO_UDP,
6741 0);
6742
6743 if ( print_headers ) {
6744 print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res);
6745 }
6746
6747 send_ring = NULL;
6748 confidence_iteration = 1;
6749 init_stat();
6750 sum_messages_sent = 0;
6751 sum_messages_recvd = 0;
6752 sum_failed_sends = 0;
6753 sum_local_thruput = 0.0;
6754
6755 /* we have a great-big while loop which controls the number of times */
6756 /* we run a particular test. this is for the calculation of a */
6757 /* confidence interval (I really should have stayed awake during */
6758 /* probstats :). If the user did not request confidence measurement */
6759 /* (no confidence is the default) then we will only go though the */
6760 /* loop once. the confidence stuff originates from the folks at IBM */
6761
6762 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
6763 (confidence_iteration <= iteration_min)) {
6764
6765 /* initialize a few counters. we have to remember that we might be */
6766 /* going through the loop more than once. */
6767 messages_sent = 0;
6768 messages_recvd = 0;
6769 failed_sends = 0;
6770 times_up = 0;
6771
6772 /*set up the data socket */
6773 data_socket = create_data_socket(local_res);
6774
6775 if (data_socket == INVALID_SOCKET){
6776 perror("udp_send: data socket");
6777 exit(1);
6778 }
6779
6780 /* now, we want to see if we need to set the send_size */
6781 if (send_size == 0) {
6782 if (lss_size > 0) {
6783 send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX);
6784 }
6785 else {
6786 send_size = 4096;
6787 }
6788 }
6789
6790
6791 /* set-up the data buffer with the requested alignment and offset, */
6792 /* most of the numbers here are just a hack to pick something nice */
6793 /* and big in an attempt to never try to send a buffer a second time */
6794 /* before it leaves the node...unless the user set the width */
6795 /* explicitly. */
6796 if (send_width == 0) send_width = 32;
6797
6798 if (send_ring == NULL ) {
6799 send_ring = allocate_buffer_ring(send_width,
6800 send_size,
6801 local_send_align,
6802 local_send_offset);
6803 }
6804
6805
6806 /* if the user supplied a cpu rate, this call will complete rather */
6807 /* quickly, otherwise, the cpu rate will be retured to us for */
6808 /* possible display. The Library will keep it's own copy of this data */
6809 /* for use elsewhere. We will only display it. (Does that make it */
6810 /* "opaque" to us?) */
6811
6812 if (local_cpu_usage)
6813 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
6814
6815 if (!no_control) {
6816 /* Tell the remote end to set up the data connection. The server
6817 sends back the port number and alters the socket parameters
6818 there. Of course this is a datagram service so no connection
6819 is actually set up, the server just sets up the socket and
6820 binds it. */
6821
6822 netperf_request.content.request_type = DO_UDP_STREAM;
6823 udp_stream_request->recv_buf_size = rsr_size_req;
6824 udp_stream_request->message_size = send_size;
6825 udp_stream_request->recv_connected = remote_connected;
6826 udp_stream_request->recv_alignment = remote_recv_align;
6827 udp_stream_request->recv_offset = remote_recv_offset;
6828 udp_stream_request->measure_cpu = remote_cpu_usage;
6829 udp_stream_request->cpu_rate = remote_cpu_rate;
6830 udp_stream_request->test_length = test_time;
6831 udp_stream_request->so_rcvavoid = rem_rcvavoid;
6832 udp_stream_request->so_sndavoid = rem_sndavoid;
6833 udp_stream_request->port = atoi(remote_data_port);
6834 udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
6835
6836 send_request();
6837
6838 recv_response();
6839
6840 if (!netperf_response.content.serv_errno) {
6841 if (debug)
6842 fprintf(where,"send_udp_stream: remote data connection done.\n");
6843 }
6844 else {
6845 Set_errno(netperf_response.content.serv_errno);
6846 perror("send_udp_stream: error on remote");
6847 exit(1);
6848 }
6849
6850 /* Place the port number returned by the remote into the sockaddr */
6851 /* structure so our sends can be sent to the correct place. Also get */
6852 /* some of the returned socket buffer information for user display. */
6853
6854 /* make sure that port numbers are in the proper order */
6855 set_port_number(remote_res,(short)udp_stream_response->data_port_number);
6856
6857 rsr_size = udp_stream_response->recv_buf_size;
6858 rss_size = udp_stream_response->send_buf_size;
6859 remote_cpu_rate = udp_stream_response->cpu_rate;
6860 }
6861
6862 #ifdef WANT_DEMO
6863 demo_stream_setup(lss_size,rsr_size);
6864 #endif
6865
6866 /* We "connect" up to the remote post to allow is to use the send */
6867 /* call instead of the sendto call. Presumeably, this is a little */
6868 /* simpler, and a little more efficient. I think that it also means */
6869 /* that we can be informed of certain things, but am not sure */
6870 /* yet...also, this is the way I would expect a client to behave */
6871 /* when talking to a server */
6872 if (local_connected) {
6873 if (connect(data_socket,
6874 remote_res->ai_addr,
6875 remote_res->ai_addrlen) == INVALID_SOCKET){
6876 perror("send_udp_stream: data socket connect failed");
6877 exit(1);
6878 } else if (debug) {
6879 fprintf(where,"send_udp_stream: connected data socket.\n");
6880 fflush(where);
6881 }
6882 }
6883
6884 #if defined (__linux)
6885 enable_enobufs(data_socket);
6886 #endif
6887
6888 #ifdef WIN32
6889 /* this is used so the timer thread can close the socket out from */
6890 /* under us, which to date is the easiest/cleanest/least */
6891 /* Windows-specific way I can find to force the winsock calls to */
6892 /* return WSAEINTR with the test is over. anything that will run on */
6893 /* 95 and NT and is closer to what netperf expects from Unix signals */
6894 /* and such would be appreciated raj 1/96 */
6895 win_kludge_socket = data_socket;
6896 #endif /* WIN32 */
6897
6898 /* set up the timer to call us after test_time. one of these days, */
6899 /* it might be nice to figure-out a nice reliable way to have the */
6900 /* test controlled by a byte count as well, but since UDP is not */
6901 /* reliable, that could prove difficult. so, in the meantime, we */
6902 /* only allow a UDP_STREAM test to be a timed test. */
6903
6904 if (test_time) {
6905 times_up = 0;
6906 start_timer(test_time);
6907 }
6908 else {
6909 fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n");
6910 fflush(where);
6911 }
6912
6913 /* Get the start count for the idle counter and the start time */
6914
6915 cpu_start(local_cpu_usage);
6916
6917 #ifdef WANT_INTERVALS
6918 INTERVALS_INIT();
6919 #endif /* WANT_INTERVALS */
6920
6921 #ifdef WANT_DEMO
6922 if (demo_mode) {
6923 demo_first_timestamp();
6924 }
6925 #endif
6926
6927 /* Send datagrams like there was no tomorrow. at somepoint it might */
6928 /* be nice to set this up so that a quantity of bytes could be sent, */
6929 /* but we still need some sort of end of test trigger on the receive */
6930 /* side. that could be a select with a one second timeout, but then */
6931 /* if there is a test where none of the data arrives for awile and */
6932 /* then starts again, we would end the test too soon. something to */
6933 /* think about... */
6934 while (!times_up) {
6935
6936 #ifdef DIRTY
6937 /* we want to dirty some number of consecutive integers in the buffer */
6938 /* we are about to send. we may also want to bring some number of */
6939 /* them cleanly into the cache. The clean ones will follow any dirty */
6940 /* ones into the cache. */
6941
6942 access_buffer(send_ring->buffer_ptr,
6943 send_size,
6944 loc_dirty_count,
6945 loc_clean_count);
6946 #endif /* DIRTY */
6947
6948 #ifdef WANT_HISTOGRAM
6949 if (verbosity > 1) {
6950 HIST_timestamp(&time_one);
6951 }
6952 #endif /* WANT_HISTOGRAM */
6953
6954 if (local_connected) {
6955 len = send(data_socket,
6956 send_ring->buffer_ptr,
6957 send_size,
6958 0);
6959 } else {
6960 len = sendto(data_socket,
6961 send_ring->buffer_ptr,
6962 send_size,
6963 0,
6964 remote_res->ai_addr,
6965 remote_res->ai_addrlen);
6966 }
6967
6968 if (len != send_size) {
6969 if ((len >= 0) ||
6970 SOCKET_EINTR(len))
6971 break;
6972 if (errno == ENOBUFS) {
6973 failed_sends++;
6974 continue;
6975 }
6976 perror("udp_send: data send error");
6977 exit(1);
6978 }
6979 messages_sent++;
6980
6981 /* now we want to move our pointer to the next position in the */
6982 /* data buffer... */
6983
6984 send_ring = send_ring->next;
6985
6986
6987 #ifdef WANT_HISTOGRAM
6988 if (verbosity > 1) {
6989 /* get the second timestamp */
6990 HIST_timestamp(&time_two);
6991 HIST_add(time_hist,delta_micro(&time_one,&time_two));
6992 }
6993 #endif /* WANT_HISTOGRAM */
6994
6995 #ifdef WANT_DEMO
6996 demo_stream_interval(send_size);
6997 #endif
6998
6999 #ifdef WANT_INTERVALS
7000 INTERVALS_WAIT();
7001 #endif /* WANT_INTERVALS */
7002
7003 }
7004
7005 /* This is a timed test, so the remote will be returning to us after */
7006 /* a time. We should not need to send any "strange" messages to tell */
7007 /* the remote that the test is completed, unless we decide to add a */
7008 /* number of messages to the test. */
7009
7010 /* the test is over, so get stats and stuff */
7011 cpu_stop(local_cpu_usage,
7012 &elapsed_time);
7013
7014 #if defined(WANT_INTERVALS)
7015 #ifdef WIN32
7016 stop_itimer();
7017 #endif
7018 #endif /* WANT_INTERVALS */
7019
7020 if (!no_control) {
7021 /* Get the statistics from the remote end */
7022 recv_response();
7023 if (!netperf_response.content.serv_errno) {
7024 if (debug)
7025 fprintf(where,"send_udp_stream: remote results obtained\n");
7026 }
7027 else {
7028 Set_errno(netperf_response.content.serv_errno);
7029 perror("send_udp_stream: error on remote");
7030 exit(1);
7031 }
7032 messages_recvd = udp_stream_results->messages_recvd;
7033 bytes_recvd = (double) send_size * (double) messages_recvd;
7034 }
7035 else {
7036 /* since there was no control connection, we've no idea what was
7037 actually received. raj 2007-02-08 */
7038 messages_recvd = -1;
7039 bytes_recvd = -1.0;
7040 }
7041
7042 bytes_sent = (double) send_size * (double) messages_sent;
7043 local_thruput = calc_thruput(bytes_sent);
7044
7045
7046 /* we asume that the remote ran for as long as we did */
7047
7048 remote_thruput = calc_thruput(bytes_recvd);
7049
7050 /* print the results for this socket and message size */
7051
7052 if (local_cpu_usage || remote_cpu_usage) {
7053 /* We must now do a little math for service demand and cpu */
7054 /* utilization for the system(s) We pass zeros for the local */
7055 /* cpu utilization and elapsed time to tell the routine to use */
7056 /* the libraries own values for those. */
7057 if (local_cpu_usage) {
7058 local_cpu_utilization = calc_cpu_util(0.0);
7059 /* shouldn't this really be based on bytes_recvd, since that is */
7060 /* the effective throughput of the test? I think that it should, */
7061 /* so will make the change raj 11/94 */
7062 local_service_demand = calc_service_demand(bytes_recvd,
7063 0.0,
7064 0.0,
7065 0);
7066 }
7067 else {
7068 local_cpu_utilization = (float) -1.0;
7069 local_service_demand = (float) -1.0;
7070 }
7071
7072 /* The local calculations could use variables being kept by */
7073 /* the local netlib routines. The remote calcuations need to */
7074 /* have a few things passed to them. */
7075 if (remote_cpu_usage) {
7076 remote_cpu_utilization = udp_stream_results->cpu_util;
7077 remote_service_demand = calc_service_demand(bytes_recvd,
7078 0.0,
7079 remote_cpu_utilization,
7080 udp_stream_results->num_cpus);
7081 }
7082 else {
7083 remote_cpu_utilization = (float) -1.0;
7084 remote_service_demand = (float) -1.0;
7085 }
7086 }
7087 else {
7088 /* we were not measuring cpu, for the confidence stuff, we */
7089 /* should make it -1.0 */
7090 local_cpu_utilization = (float) -1.0;
7091 local_service_demand = (float) -1.0;
7092 remote_cpu_utilization = (float) -1.0;
7093 remote_service_demand = (float) -1.0;
7094 }
7095
7096 /* at this point, we want to calculate the confidence information. */
7097 /* if debugging is on, calculate_confidence will print-out the */
7098 /* parameters we pass it */
7099
7100 calculate_confidence(confidence_iteration,
7101 elapsed_time,
7102 remote_thruput,
7103 local_cpu_utilization,
7104 remote_cpu_utilization,
7105 local_service_demand,
7106 remote_service_demand);
7107
7108 /* since the routine calculate_confidence is rather generic, and */
7109 /* we have a few other parms of interest, we will do a little work */
7110 /* here to caclulate their average. */
7111 sum_messages_sent += messages_sent;
7112 sum_messages_recvd += messages_recvd;
7113 sum_failed_sends += failed_sends;
7114 sum_local_thruput += local_thruput;
7115
7116 confidence_iteration++;
7117
7118 /* this datapoint is done, so we don't need the socket any longer */
7119 close(data_socket);
7120
7121 }
7122
7123 /* we should reach this point once the test is finished */
7124
7125 retrieve_confident_values(&elapsed_time,
7126 &remote_thruput,
7127 &local_cpu_utilization,
7128 &remote_cpu_utilization,
7129 &local_service_demand,
7130 &remote_service_demand);
7131
7132 /* some of the interesting values aren't covered by the generic */
7133 /* confidence routine */
7134 messages_sent = sum_messages_sent / (confidence_iteration -1);
7135 messages_recvd = sum_messages_recvd / (confidence_iteration -1);
7136 failed_sends = sum_failed_sends / (confidence_iteration -1);
7137 local_thruput = sum_local_thruput / (confidence_iteration -1);
7138
7139 /* We are now ready to print all the information. If the user */
7140 /* has specified zero-level verbosity, we will just print the */
7141 /* local service demand, or the remote service demand. If the */
7142 /* user has requested verbosity level 1, he will get the basic */
7143 /* "streamperf" numbers. If the user has specified a verbosity */
7144 /* of greater than 1, we will display a veritable plethora of */
7145 /* background information from outside of this block as it it */
7146 /* not cpu_measurement specific... */
7147
7148
7149 if (confidence < 0) {
7150 /* we did not hit confidence, but were we asked to look for it? */
7151 if (iteration_max > 1) {
7152 display_confidence();
7153 }
7154 }
7155
7156 if (local_cpu_usage || remote_cpu_usage) {
7157 local_cpu_method = format_cpu_method(cpu_method);
7158 remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method);
7159
7160 switch (verbosity) {
7161 case 0:
7162 if (local_cpu_usage) {
7163 fprintf(where,
7164 cpu_fmt_0,
7165 local_service_demand,
7166 local_cpu_method);
7167 }
7168 else {
7169 fprintf(where,
7170 cpu_fmt_0,
7171 remote_service_demand,
7172 local_cpu_method);
7173 }
7174 break;
7175 case 1:
7176 case 2:
7177 if (print_headers) {
7178 fprintf(where,
7179 cpu_title,
7180 format_units(),
7181 local_cpu_method,
7182 remote_cpu_method);
7183 }
7184
7185 fprintf(where,
7186 cpu_fmt_1, /* the format string */
7187 lss_size, /* local sendbuf size */
7188 send_size, /* how large were the sends */
7189 elapsed_time, /* how long was the test */
7190 messages_sent,
7191 failed_sends,
7192 local_thruput, /* what was the xfer rate */
7193 local_cpu_utilization, /* local cpu */
7194 local_service_demand, /* local service demand */
7195 rsr_size,
7196 elapsed_time,
7197 messages_recvd,
7198 remote_thruput,
7199 remote_cpu_utilization, /* remote cpu */
7200 remote_service_demand); /* remote service demand */
7201 break;
7202 }
7203 }
7204 else {
7205 /* The tester did not wish to measure service demand. */
7206 switch (verbosity) {
7207 case 0:
7208 fprintf(where,
7209 tput_fmt_0,
7210 local_thruput);
7211 break;
7212 case 1:
7213 case 2:
7214 if (print_headers) {
7215 fprintf(where,tput_title,format_units());
7216 }
7217 fprintf(where,
7218 tput_fmt_1, /* the format string */
7219 lss_size, /* local sendbuf size */
7220 send_size, /* how large were the sends */
7221 elapsed_time, /* how long did it take */
7222 messages_sent,
7223 failed_sends,
7224 local_thruput,
7225 rsr_size, /* remote recvbuf size */
7226 elapsed_time,
7227 messages_recvd,
7228 remote_thruput);
7229 break;
7230 }
7231 }
7232
7233 fflush(where);
7234 #ifdef WANT_HISTOGRAM
7235 if (verbosity > 1) {
7236 fprintf(where,"\nHistogram of time spent in send() call\n");
7237 fflush(where);
7238 HIST_report(time_hist);
7239 }
7240 #endif /* WANT_HISTOGRAM */
7241
7242 }
7243 #endif /* WANT_MIGRATION */
7244
7245
7246 /* this routine implements the receive side (netserver) of the */
7247 /* UDP_STREAM performance test. */
7248
7249 void
recv_udp_stream()7250 recv_udp_stream()
7251 {
7252 struct ring_elt *recv_ring;
7253 struct addrinfo *local_res;
7254 char local_name[BUFSIZ];
7255 char port_buffer[PORTBUFSIZE];
7256
7257 struct sockaddr_storage myaddr_in;
7258 SOCKET s_data;
7259 netperf_socklen_t addrlen;
7260 struct sockaddr_storage remote_addr;
7261 netperf_socklen_t remote_addrlen;
7262
7263 int len = 0;
7264 unsigned int bytes_received = 0;
7265 float elapsed_time;
7266
7267 int message_size;
7268 unsigned int messages_recvd = 0;
7269
7270 struct udp_stream_request_struct *udp_stream_request;
7271 struct udp_stream_response_struct *udp_stream_response;
7272 struct udp_stream_results_struct *udp_stream_results;
7273
7274 udp_stream_request =
7275 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
7276 udp_stream_response =
7277 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
7278 udp_stream_results =
7279 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
7280
7281 if (debug) {
7282 fprintf(where,"netserver: recv_udp_stream: entered...\n");
7283 fflush(where);
7284 }
7285
7286 /* We want to set-up the listen socket with all the desired */
7287 /* parameters and then let the initiator know that all is ready. If */
7288 /* socket size defaults are to be used, then the initiator will have */
7289 /* sent us 0's. If the socket sizes cannot be changed, then we will */
7290 /* send-back what they are. If that information cannot be determined, */
7291 /* then we send-back -1's for the sizes. If things go wrong for any */
7292 /* reason, we will drop back ten yards and punt. */
7293
7294 /* If anything goes wrong, we want the remote to know about it. It */
7295 /* would be best if the error that the remote reports to the user is */
7296 /* the actual error we encountered, rather than some bogus unexpected */
7297 /* response type message. */
7298
7299 if (debug > 1) {
7300 fprintf(where,"recv_udp_stream: setting the response type...\n");
7301 fflush(where);
7302 }
7303
7304 netperf_response.content.response_type = UDP_STREAM_RESPONSE;
7305
7306 if (debug > 2) {
7307 fprintf(where,"recv_udp_stream: the response type is set...\n");
7308 fflush(where);
7309 }
7310
7311 /* We now alter the message_ptr variable to be at the desired */
7312 /* alignment with the desired offset. */
7313
7314 if (debug > 1) {
7315 fprintf(where,"recv_udp_stream: requested alignment of %d\n",
7316 udp_stream_request->recv_alignment);
7317 fflush(where);
7318 }
7319
7320 if (recv_width == 0) recv_width = 1;
7321
7322 recv_ring = allocate_buffer_ring(recv_width,
7323 udp_stream_request->message_size,
7324 udp_stream_request->recv_alignment,
7325 udp_stream_request->recv_offset);
7326
7327 if (debug > 1) {
7328 fprintf(where,"recv_udp_stream: receive alignment and offset set...\n");
7329 fflush(where);
7330 }
7331
7332 /* Grab a socket to listen on, and then listen on it. */
7333
7334 if (debug > 1) {
7335 fprintf(where,"recv_udp_stream: grabbing a socket...\n");
7336 fflush(where);
7337 }
7338
7339 /* create_data_socket expects to find some things in the global */
7340 /* variables, so set the globals based on the values in the request. */
7341 /* once the socket has been created, we will set the response values */
7342 /* based on the updated value of those globals. raj 7/94 */
7343 lsr_size_req = udp_stream_request->recv_buf_size;
7344 loc_rcvavoid = udp_stream_request->so_rcvavoid;
7345 loc_sndavoid = udp_stream_request->so_sndavoid;
7346 local_connected = udp_stream_request->recv_connected;
7347
7348 set_hostname_and_port(local_name,
7349 port_buffer,
7350 nf_to_af(udp_stream_request->ipfamily),
7351 udp_stream_request->port);
7352
7353 local_res = complete_addrinfo(local_name,
7354 local_name,
7355 port_buffer,
7356 nf_to_af(udp_stream_request->ipfamily),
7357 SOCK_DGRAM,
7358 IPPROTO_UDP,
7359 0);
7360
7361 s_data = create_data_socket(local_res);
7362
7363 if (s_data == INVALID_SOCKET) {
7364 netperf_response.content.serv_errno = errno;
7365 send_response();
7366 exit(1);
7367 }
7368
7369 udp_stream_response->test_length = udp_stream_request->test_length;
7370
7371 /* now get the port number assigned by the system */
7372 addrlen = sizeof(myaddr_in);
7373 if (getsockname(s_data,
7374 (struct sockaddr *)&myaddr_in,
7375 &addrlen) == SOCKET_ERROR){
7376 netperf_response.content.serv_errno = errno;
7377 close(s_data);
7378 send_response();
7379
7380 exit(1);
7381 }
7382
7383 /* Now myaddr_in contains the port and the internet address this is */
7384 /* returned to the sender also implicitly telling the sender that the */
7385 /* socket buffer sizing has been done. */
7386
7387 udp_stream_response->data_port_number =
7388 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
7389 netperf_response.content.serv_errno = 0;
7390
7391 /* But wait, there's more. If the initiator wanted cpu measurements, */
7392 /* then we must call the calibrate routine, which will return the max */
7393 /* rate back to the initiator. If the CPU was not to be measured, or */
7394 /* something went wrong with the calibration, we will return a -1 to */
7395 /* the initiator. */
7396
7397 udp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
7398 udp_stream_response->measure_cpu = 0;
7399 if (udp_stream_request->measure_cpu) {
7400 /* We will pass the rate into the calibration routine. If the */
7401 /* user did not specify one, it will be 0.0, and we will do a */
7402 /* "real" calibration. Otherwise, all it will really do is */
7403 /* store it away... */
7404 udp_stream_response->measure_cpu = 1;
7405 udp_stream_response->cpu_rate =
7406 calibrate_local_cpu(udp_stream_request->cpu_rate);
7407 }
7408
7409 message_size = udp_stream_request->message_size;
7410 test_time = udp_stream_request->test_length;
7411
7412 /* before we send the response back to the initiator, pull some of */
7413 /* the socket parms from the globals */
7414 udp_stream_response->send_buf_size = lss_size;
7415 udp_stream_response->recv_buf_size = lsr_size;
7416 udp_stream_response->so_rcvavoid = loc_rcvavoid;
7417 udp_stream_response->so_sndavoid = loc_sndavoid;
7418
7419 send_response();
7420
7421 /* Now it's time to start receiving data on the connection. We will */
7422 /* first grab the apropriate counters and then start grabbing. */
7423
7424 cpu_start(udp_stream_request->measure_cpu);
7425
7426 #ifdef WIN32
7427 /* this is used so the timer thread can close the socket out from */
7428 /* under us, which to date is the easiest/cleanest/least */
7429 /* Windows-specific way I can find to force the winsock calls to */
7430 /* return WSAEINTR with the test is over. anything that will run on */
7431 /* 95 and NT and is closer to what netperf expects from Unix signals */
7432 /* and such would be appreciated raj 1/96 */
7433 win_kludge_socket = s_data;
7434 #endif /* WIN32 */
7435
7436 /* The loop will exit when the timer pops, or if we happen to recv a */
7437 /* message of less than send_size bytes... */
7438
7439 times_up = 0;
7440
7441 start_timer(test_time + PAD_TIME);
7442
7443 if (debug) {
7444 fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n");
7445 fflush(where);
7446 }
7447
7448 /* We "connect" up to the remote post to allow us to use the recv */
7449 /* call instead of the recvfrom call. Presumeably, this is a little */
7450 /* simpler, and a little more efficient. */
7451
7452 if (local_connected) {
7453
7454 /* Receive the first message using recvfrom to find the remote address */
7455 remote_addrlen = sizeof(remote_addr);
7456 len = recvfrom(s_data, recv_ring->buffer_ptr,
7457 message_size, 0,
7458 (struct sockaddr*)&remote_addr, &remote_addrlen);
7459 if (len != message_size) {
7460 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
7461 netperf_response.content.serv_errno = errno;
7462 send_response();
7463 exit(1);
7464 }
7465 }
7466 messages_recvd++;
7467 recv_ring = recv_ring->next;
7468
7469
7470 /* Now connect with the remote socket address */
7471 if (connect(s_data,
7472 (struct sockaddr*)&remote_addr,
7473 remote_addrlen )== INVALID_SOCKET) {
7474 netperf_response.content.serv_errno = errno;
7475 close(s_data);
7476 send_response();
7477 exit(1);
7478 }
7479
7480 if (debug) {
7481 fprintf(where,"recv_udp_stream: connected data socket\n");
7482 fflush(where);
7483 }
7484 }
7485
7486 while (!times_up) {
7487 if(local_connected) {
7488 len = recv(s_data,
7489 recv_ring->buffer_ptr,
7490 message_size,
7491 0);
7492 } else {
7493 len = recvfrom(s_data,
7494 recv_ring->buffer_ptr,
7495 message_size,
7496 0,0,0);
7497 }
7498
7499 if (len != message_size) {
7500 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
7501 netperf_response.content.serv_errno = errno;
7502 send_response();
7503 exit(1);
7504 }
7505 break;
7506 }
7507 messages_recvd++;
7508 recv_ring = recv_ring->next;
7509 }
7510
7511 if (debug) {
7512 fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd);
7513 fflush(where);
7514 }
7515
7516
7517 /* The loop now exits due timer or < send_size bytes received. in */
7518 /* reality, we only really support a timed UDP_STREAM test. raj */
7519 /* 12/95 */
7520
7521 cpu_stop(udp_stream_request->measure_cpu,&elapsed_time);
7522
7523 if (times_up) {
7524 /* we ended on a timer, subtract the PAD_TIME */
7525 elapsed_time -= (float)PAD_TIME;
7526 }
7527 else {
7528 stop_timer();
7529 }
7530
7531 if (debug) {
7532 fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time);
7533 fflush(where);
7534 }
7535
7536
7537 /* We will count the "off" message that got us out of the loop */
7538 bytes_received = (messages_recvd * message_size) + len;
7539
7540 /* send the results to the sender */
7541
7542 if (debug) {
7543 fprintf(where,
7544 "recv_udp_stream: got %d bytes\n",
7545 bytes_received);
7546 fflush(where);
7547 }
7548
7549 netperf_response.content.response_type = UDP_STREAM_RESULTS;
7550 udp_stream_results->bytes_received = bytes_received;
7551 udp_stream_results->messages_recvd = messages_recvd;
7552 udp_stream_results->elapsed_time = elapsed_time;
7553 udp_stream_results->cpu_method = cpu_method;
7554 udp_stream_results->num_cpus = lib_num_loc_cpus;
7555 if (udp_stream_request->measure_cpu) {
7556 udp_stream_results->cpu_util = calc_cpu_util(elapsed_time);
7557 }
7558 else {
7559 udp_stream_results->cpu_util = (float) -1.0;
7560 }
7561
7562 if (debug > 1) {
7563 fprintf(where,
7564 "recv_udp_stream: test complete, sending results.\n");
7565 fflush(where);
7566 }
7567
7568 send_response();
7569
7570 close(s_data);
7571
7572 }
7573
7574 #ifndef WANT_MIGRATION
7575 void
send_udp_rr(char remote_host[])7576 send_udp_rr(char remote_host[])
7577 {
7578
7579 char *tput_title = "\
7580 Local /Remote\n\
7581 Socket Size Request Resp. Elapsed Trans.\n\
7582 Send Recv Size Size Time Rate \n\
7583 bytes Bytes bytes bytes secs. per sec \n\n";
7584
7585 char *tput_title_band = "\
7586 Local /Remote\n\
7587 Socket Size Request Resp. Elapsed \n\
7588 Send Recv Size Size Time Throughput \n\
7589 bytes Bytes bytes bytes secs. %s/sec \n\n";
7590
7591 char *tput_fmt_0 =
7592 "%7.2f %s\n";
7593
7594 char *tput_fmt_1_line_1 = "\
7595 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
7596
7597 char *tput_fmt_1_line_2 = "\
7598 %-6d %-6d\n";
7599
7600 char *cpu_title = "\
7601 Local /Remote\n\
7602 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
7603 Send Recv Size Size Time Rate local remote local remote\n\
7604 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
7605
7606 char *cpu_title_tput = "\
7607 Local /Remote\n\
7608 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\
7609 Send Recv Size Size Time %-8.8s local remote local remote\n\
7610 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
7611
7612 char *cpu_fmt_0 =
7613 "%6.3f %c %s\n";
7614
7615 char *cpu_fmt_1_line_1 = "\
7616 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
7617
7618 char *cpu_fmt_1_line_2 = "\
7619 %-6d %-6d\n";
7620
7621 float elapsed_time;
7622
7623 struct ring_elt *send_ring;
7624 struct ring_elt *recv_ring;
7625
7626 int len;
7627 int nummessages;
7628 SOCKET send_socket;
7629 int trans_remaining;
7630 int bytes_xferd;
7631
7632 int rsp_bytes_recvd;
7633
7634 float local_cpu_utilization;
7635 float local_service_demand;
7636 float remote_cpu_utilization;
7637 float remote_service_demand;
7638 double thruput;
7639
7640 struct addrinfo *local_res;
7641 struct addrinfo *remote_res;
7642
7643 struct udp_rr_request_struct *udp_rr_request;
7644 struct udp_rr_response_struct *udp_rr_response;
7645 struct udp_rr_results_struct *udp_rr_result;
7646
7647 udp_rr_request =
7648 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
7649 udp_rr_response =
7650 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
7651 udp_rr_result =
7652 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
7653
7654 #ifdef WANT_HISTOGRAM
7655 if (verbosity > 1) {
7656 time_hist = HIST_new();
7657 }
7658 #endif
7659
7660 /* since we are now disconnected from the code that established the */
7661 /* control socket, and since we want to be able to use different */
7662 /* protocols and such, we are passed the name of the remote host and */
7663 /* must turn that into the test specific addressing information. */
7664
7665 complete_addrinfos(&remote_res,
7666 &local_res,
7667 remote_host,
7668 SOCK_DGRAM,
7669 IPPROTO_UDP,
7670 0);
7671
7672 if ( print_headers ) {
7673 print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res);
7674 }
7675
7676 /* initialize a few counters */
7677
7678 send_ring = NULL;
7679 recv_ring = NULL;
7680 nummessages = 0;
7681 bytes_xferd = 0;
7682 times_up = 0;
7683 confidence_iteration = 1;
7684 init_stat();
7685
7686 /* we have a great-big while loop which controls the number of times */
7687 /* we run a particular test. this is for the calculation of a */
7688 /* confidence interval (I really should have stayed awake during */
7689 /* probstats :). If the user did not request confidence measurement */
7690 /* (no confidence is the default) then we will only go though the */
7691 /* loop once. the confidence stuff originates from the folks at IBM */
7692
7693 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
7694 (confidence_iteration <= iteration_min)) {
7695
7696 nummessages = 0;
7697 bytes_xferd = 0;
7698 times_up = 0;
7699 trans_remaining = 0;
7700
7701 /* set-up the data buffers with the requested alignment and offset */
7702
7703 if (send_width == 0) send_width = 1;
7704 if (recv_width == 0) recv_width = 1;
7705
7706 if (send_ring == NULL) {
7707 send_ring = allocate_buffer_ring(send_width,
7708 req_size,
7709 local_send_align,
7710 local_send_offset);
7711 }
7712
7713 if (recv_ring == NULL) {
7714 recv_ring = allocate_buffer_ring(recv_width,
7715 rsp_size,
7716 local_recv_align,
7717 local_recv_offset);
7718 }
7719
7720 /*set up the data socket */
7721 send_socket = create_data_socket(local_res);
7722
7723 if (send_socket == INVALID_SOCKET){
7724 perror("netperf: send_udp_rr: udp rr data socket");
7725 exit(1);
7726 }
7727
7728 if (debug) {
7729 fprintf(where,"send_udp_rr: send_socket obtained...\n");
7730 }
7731
7732 /* If the user has requested cpu utilization measurements, we must */
7733 /* calibrate the cpu(s). We will perform this task within the tests */
7734 /* themselves. If the user has specified the cpu rate, then */
7735 /* calibrate_local_cpu will return rather quickly as it will have */
7736 /* nothing to do. If local_cpu_rate is zero, then we will go through */
7737 /* all the "normal" calibration stuff and return the rate back. If */
7738 /* there is no idle counter in the kernel idle loop, the */
7739 /* local_cpu_rate will be set to -1. */
7740
7741 if (local_cpu_usage) {
7742 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
7743 }
7744
7745 if (!no_control) {
7746 /* Tell the remote end to do a listen. The server alters the
7747 socket paramters on the other side at this point, hence the
7748 reason for all the values being passed in the setup
7749 message. If the user did not specify any of the parameters,
7750 they will be passed as 0, which will indicate to the remote
7751 that no changes beyond the system's default should be
7752 used. Alignment is the exception, it will default to 8, which
7753 will be no alignment alterations. */
7754
7755 netperf_request.content.request_type = DO_UDP_RR;
7756 udp_rr_request->recv_buf_size = rsr_size_req;
7757 udp_rr_request->send_buf_size = rss_size_req;
7758 udp_rr_request->recv_alignment = remote_recv_align;
7759 udp_rr_request->recv_offset = remote_recv_offset;
7760 udp_rr_request->send_alignment = remote_send_align;
7761 udp_rr_request->send_offset = remote_send_offset;
7762 udp_rr_request->request_size = req_size;
7763 udp_rr_request->response_size = rsp_size;
7764 udp_rr_request->measure_cpu = remote_cpu_usage;
7765 udp_rr_request->cpu_rate = remote_cpu_rate;
7766 udp_rr_request->so_rcvavoid = rem_rcvavoid;
7767 udp_rr_request->so_sndavoid = rem_sndavoid;
7768 if (test_time) {
7769 udp_rr_request->test_length = test_time;
7770 }
7771 else {
7772 udp_rr_request->test_length = test_trans * -1;
7773 }
7774 udp_rr_request->port = atoi(remote_data_port);
7775 udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
7776
7777 if (debug > 1) {
7778 fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n");
7779 }
7780
7781 send_request();
7782
7783 /* The response from the remote will contain all of the relevant
7784 socket parameters for this test type. We will put them back
7785 into the variables here so they can be displayed if desired.
7786 The remote will have calibrated CPU if necessary, and will
7787 have done all the needed set-up we will have calibrated the
7788 cpu locally before sending the request, and will grab the
7789 counter value right after the connect returns. The remote
7790 will grab the counter right after the accept call. This saves
7791 the hassle of extra messages being sent for the UDP
7792 tests. */
7793
7794 recv_response();
7795
7796 if (!netperf_response.content.serv_errno) {
7797 if (debug)
7798 fprintf(where,"remote listen done.\n");
7799 rsr_size = udp_rr_response->recv_buf_size;
7800 rss_size = udp_rr_response->send_buf_size;
7801 remote_cpu_usage = udp_rr_response->measure_cpu;
7802 remote_cpu_rate = udp_rr_response->cpu_rate;
7803 /* port numbers in proper order */
7804 set_port_number(remote_res,(short)udp_rr_response->data_port_number);
7805 }
7806 else {
7807 Set_errno(netperf_response.content.serv_errno);
7808 fprintf(where,
7809 "netperf: remote error %d",
7810 netperf_response.content.serv_errno);
7811 perror("");
7812 fflush(where);
7813 exit(1);
7814 }
7815 }
7816
7817 #ifdef WANT_DEMO
7818 demo_rr_setup(100);
7819 #endif
7820
7821 /* Connect up to the remote port on the data socket. This will set */
7822 /* the default destination address on this socket. With UDP, this */
7823 /* does make a performance difference as we may not have to do as */
7824 /* many routing lookups, however, I expect that a client would */
7825 /* behave this way. raj 1/94 */
7826
7827 if ( connect(send_socket,
7828 remote_res->ai_addr,
7829 remote_res->ai_addrlen) == INVALID_SOCKET ) {
7830 perror("netperf: data socket connect failed");
7831 exit(1);
7832 }
7833
7834 #ifdef WIN32
7835 /* this is used so the timer thread can close the socket out from */
7836 /* under us, which to date is the easiest/cleanest/least */
7837 /* Windows-specific way I can find to force the winsock calls to */
7838 /* return WSAEINTR with the test is over. anything that will run on */
7839 /* 95 and NT and is closer to what netperf expects from Unix signals */
7840 /* and such would be appreciated raj 1/96 */
7841 win_kludge_socket = send_socket;
7842 #endif /* WIN32 */
7843
7844 /* Data Socket set-up is finished. If there were problems, either the */
7845 /* connect would have failed, or the previous response would have */
7846 /* indicated a problem. I failed to see the value of the extra */
7847 /* message after the accept on the remote. If it failed, we'll see it */
7848 /* here. If it didn't, we might as well start pumping data. */
7849
7850 /* Set-up the test end conditions. For a request/response test, they */
7851 /* can be either time or transaction based. */
7852
7853 if (test_time) {
7854 /* The user wanted to end the test after a period of time. */
7855 times_up = 0;
7856 trans_remaining = 0;
7857 start_timer(test_time);
7858 }
7859 else {
7860 /* The tester wanted to send a number of bytes. */
7861 trans_remaining = test_bytes;
7862 times_up = 1;
7863 }
7864
7865 /* The cpu_start routine will grab the current time and possibly */
7866 /* value of the idle counter for later use in measuring cpu */
7867 /* utilization and/or service demand and thruput. */
7868
7869 cpu_start(local_cpu_usage);
7870
7871 #ifdef WANT_DEMO
7872 if (demo_mode) {
7873 demo_first_timestamp();
7874 }
7875 #endif
7876
7877 #ifdef WANT_INTERVALS
7878 INTERVALS_INIT();
7879 #endif /* WANT_INTERVALS */
7880
7881 /* We use an "OR" to control test execution. When the test is */
7882 /* controlled by time, the byte count check will always return */
7883 /* false. When the test is controlled by byte count, the time test */
7884 /* will always return false. When the test is finished, the whole */
7885 /* expression will go false and we will stop sending data. I think */
7886 /* I just arbitrarily decrement trans_remaining for the timed */
7887 /* test, but will not do that just yet... One other question is */
7888 /* whether or not the send buffer and the receive buffer should be */
7889 /* the same buffer. */
7890
7891 #ifdef WANT_FIRST_BURST
7892 {
7893 int i;
7894 for (i = 0; i < first_burst_size; i++) {
7895 if((len=send(send_socket,
7896 send_ring->buffer_ptr,
7897 req_size,
7898 0)) != req_size) {
7899 /* we should never hit the end of the test in the first burst */
7900 perror("send_udp_rr: initial burst data send error");
7901 exit(-1);
7902 }
7903 }
7904 }
7905 #endif /* WANT_FIRST_BURST */
7906
7907 while ((!times_up) || (trans_remaining > 0)) {
7908 /* send the request */
7909 #ifdef WANT_HISTOGRAM
7910 if (verbosity > 1) {
7911 HIST_timestamp(&time_one);
7912 }
7913 #endif
7914 if((len=send(send_socket,
7915 send_ring->buffer_ptr,
7916 req_size,
7917 0)) != req_size) {
7918 if (SOCKET_EINTR(len)) {
7919 /* We likely hit */
7920 /* test-end time. */
7921 break;
7922 }
7923 perror("send_udp_rr: data send error");
7924 exit(1);
7925 }
7926 send_ring = send_ring->next;
7927
7928 /* receive the response. with UDP we will get it all, or nothing */
7929
7930 if((rsp_bytes_recvd=recv(send_socket,
7931 recv_ring->buffer_ptr,
7932 rsp_size,
7933 0)) != rsp_size) {
7934 if (SOCKET_EINTR(rsp_bytes_recvd))
7935 {
7936 /* Again, we have likely hit test-end time */
7937 break;
7938 }
7939 perror("send_udp_rr: data recv error");
7940 exit(1);
7941 }
7942 recv_ring = recv_ring->next;
7943
7944 #ifdef WANT_HISTOGRAM
7945 if (verbosity > 1) {
7946 HIST_timestamp(&time_two);
7947 HIST_add(time_hist,delta_micro(&time_one,&time_two));
7948 }
7949
7950 #endif
7951
7952 /* at this point, we may wish to sleep for some period of */
7953 /* time, so we see how long that last transaction just took, */
7954 /* and sleep for the difference of that and the interval. We */
7955 /* will not sleep if the time would be less than a */
7956 /* millisecond. */
7957
7958 #ifdef WANT_DEMO
7959 demo_rr_interval(1);
7960 #endif
7961
7962 #ifdef WANT_INTERVALS
7963 INTERVALS_WAIT();
7964 #endif /* WANT_INTERVALS */
7965
7966 nummessages++;
7967 if (trans_remaining) {
7968 trans_remaining--;
7969 }
7970
7971 if (debug > 3) {
7972 if ((nummessages % 100) == 0) {
7973 fprintf(where,"Transaction %d completed\n",nummessages);
7974 fflush(where);
7975 }
7976 }
7977
7978 }
7979
7980 /* for some strange reason, I used to call shutdown on the UDP */
7981 /* data socket here. I'm not sure why, because it would not have */
7982 /* any effect... raj 11/94 */
7983
7984 /* this call will always give us the elapsed time for the test, and */
7985 /* will also store-away the necessaries for cpu utilization */
7986
7987 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
7988 /* measured? how long */
7989 /* did we really run? */
7990
7991 #if defined(WANT_INTERVALS)
7992 #ifdef WIN32
7993 stop_itimer();
7994 #endif
7995 #endif /* WANT_INTERVALS */
7996
7997 if (!no_control) {
7998 /* Get the statistics from the remote end. The remote will have
7999 calculated service demand and all those interesting
8000 things. If it wasn't supposed to care, it will return obvious
8001 values. */
8002
8003 recv_response();
8004 if (!netperf_response.content.serv_errno) {
8005 if (debug)
8006 fprintf(where,"remote results obtained\n");
8007 }
8008 else {
8009 Set_errno(netperf_response.content.serv_errno);
8010 fprintf(where,
8011 "netperf: remote error %d",
8012 netperf_response.content.serv_errno);
8013 perror("");
8014 fflush(where);
8015 exit(1);
8016 }
8017 }
8018
8019 /* We now calculate what our thruput was for the test. In the */
8020 /* future, we may want to include a calculation of the thruput */
8021 /* measured by the remote, but it should be the case that for a */
8022 /* UDP rr test, that the two numbers should be *very* close... */
8023 /* We calculate bytes_sent regardless of the way the test length */
8024 /* was controlled. */
8025
8026 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
8027 thruput = nummessages / elapsed_time;
8028
8029 if (local_cpu_usage || remote_cpu_usage) {
8030
8031 /* We must now do a little math for service demand and cpu */
8032 /* utilization for the system(s) Of course, some of the */
8033 /* information might be bogus because there was no idle counter */
8034 /* in the kernel(s). We need to make a note of this for the */
8035 /* user's benefit by placing a code for the metod used in the */
8036 /* test banner */
8037
8038 if (local_cpu_usage) {
8039 local_cpu_utilization = calc_cpu_util(0.0);
8040
8041 /* since calc_service demand is doing ms/Kunit we will */
8042 /* multiply the number of transaction by 1024 to get */
8043 /* "good" numbers */
8044
8045 local_service_demand = calc_service_demand((double) nummessages*1024,
8046 0.0,
8047 0.0,
8048 0);
8049 }
8050 else {
8051 local_cpu_utilization = (float) -1.0;
8052 local_service_demand = (float) -1.0;
8053 }
8054
8055 if (remote_cpu_usage) {
8056 remote_cpu_utilization = udp_rr_result->cpu_util;
8057
8058 /* since calc_service demand is doing ms/Kunit we will */
8059 /* multiply the number of transaction by 1024 to get */
8060 /* "good" numbers */
8061
8062 remote_service_demand = calc_service_demand((double) nummessages*1024,
8063 0.0,
8064 remote_cpu_utilization,
8065 udp_rr_result->num_cpus);
8066 }
8067 else {
8068 remote_cpu_utilization = (float) -1.0;
8069 remote_service_demand = (float) -1.0;
8070 }
8071 }
8072 else {
8073 /* we were not measuring cpu, for the confidence stuff, we */
8074 /* should make it -1.0 */
8075 local_cpu_utilization = (float) -1.0;
8076 local_service_demand = (float) -1.0;
8077 remote_cpu_utilization = (float) -1.0;
8078 remote_service_demand = (float) -1.0;
8079 }
8080
8081 /* at this point, we want to calculate the confidence information. */
8082 /* if debugging is on, calculate_confidence will print-out the */
8083 /* parameters we pass it */
8084
8085 calculate_confidence(confidence_iteration,
8086 elapsed_time,
8087 thruput,
8088 local_cpu_utilization,
8089 remote_cpu_utilization,
8090 local_service_demand,
8091 remote_service_demand);
8092
8093
8094 confidence_iteration++;
8095
8096 /* we are done with the socket */
8097 close(send_socket);
8098 }
8099
8100 /* at this point, we have made all the iterations we are going to */
8101 /* make. */
8102 retrieve_confident_values(&elapsed_time,
8103 &thruput,
8104 &local_cpu_utilization,
8105 &remote_cpu_utilization,
8106 &local_service_demand,
8107 &remote_service_demand);
8108
8109 /* We are now ready to print all the information. If the user */
8110 /* has specified zero-level verbosity, we will just print the */
8111 /* local service demand, or the remote service demand. If the */
8112 /* user has requested verbosity level 1, he will get the basic */
8113 /* "streamperf" numbers. If the user has specified a verbosity */
8114 /* of greater than 1, we will display a veritable plethora of */
8115 /* background information from outside of this block as it it */
8116 /* not cpu_measurement specific... */
8117
8118 if (confidence < 0) {
8119 /* we did not hit confidence, but were we asked to look for it? */
8120 if (iteration_max > 1) {
8121 display_confidence();
8122 }
8123 }
8124
8125 if (local_cpu_usage || remote_cpu_usage) {
8126 local_cpu_method = format_cpu_method(cpu_method);
8127 remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method);
8128
8129 switch (verbosity) {
8130 case 0:
8131 if (local_cpu_usage) {
8132 fprintf(where,
8133 cpu_fmt_0,
8134 local_service_demand,
8135 local_cpu_method,
8136 ((print_headers) ||
8137 (result_brand == NULL)) ? "" : result_brand);
8138
8139 }
8140 else {
8141 fprintf(where,
8142 cpu_fmt_0,
8143 remote_service_demand,
8144 remote_cpu_method,
8145 ((print_headers) ||
8146 (result_brand == NULL)) ? "" : result_brand);
8147
8148 }
8149 break;
8150 case 1:
8151 case 2:
8152 if (print_headers) {
8153 if ('x' == libfmt) {
8154 fprintf(where,
8155 cpu_title,
8156 local_cpu_method,
8157 remote_cpu_method);
8158 }
8159 else {
8160 fprintf(where,
8161 cpu_title_tput,
8162 format_units(),
8163 local_cpu_method,
8164 remote_cpu_method);
8165 }
8166 }
8167
8168 fprintf(where,
8169 cpu_fmt_1_line_1, /* the format string */
8170 lss_size, /* local sendbuf size */
8171 lsr_size,
8172 req_size, /* how large were the requests */
8173 rsp_size, /* guess */
8174 elapsed_time, /* how long was the test */
8175 ('x' == libfmt) ? thruput :
8176 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
8177 1.0),
8178 local_cpu_utilization, /* local cpu */
8179 remote_cpu_utilization, /* remote cpu */
8180 local_service_demand, /* local service demand */
8181 remote_service_demand, /* remote service demand */
8182 ((print_headers) ||
8183 (result_brand == NULL)) ? "" : result_brand);
8184 fprintf(where,
8185 cpu_fmt_1_line_2,
8186 rss_size,
8187 rsr_size);
8188 break;
8189 }
8190 }
8191 else {
8192 /* The tester did not wish to measure service demand. */
8193 switch (verbosity) {
8194 case 0:
8195 fprintf(where,
8196 tput_fmt_0,
8197 ('x' == libfmt) ? thruput :
8198 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
8199 1.0),
8200 ((print_headers) ||
8201 (result_brand == NULL)) ? "" : result_brand);
8202 break;
8203 case 1:
8204 case 2:
8205 if (print_headers) {
8206 fprintf(where,
8207 ('x' == libfmt) ? tput_title : tput_title_band,
8208 format_units());
8209 }
8210
8211 fprintf(where,
8212 tput_fmt_1_line_1, /* the format string */
8213 lss_size,
8214 lsr_size,
8215 req_size, /* how large were the requests */
8216 rsp_size, /* how large were the responses */
8217 elapsed_time, /* how long did it take */
8218 ('x' == libfmt) ? thruput :
8219 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
8220 1.0),
8221 ((print_headers) ||
8222 (result_brand == NULL)) ? "" : result_brand);
8223 fprintf(where,
8224 tput_fmt_1_line_2,
8225 rss_size, /* remote recvbuf size */
8226 rsr_size);
8227
8228 break;
8229 }
8230 }
8231 fflush(where);
8232
8233 /* it would be a good thing to include information about some of the */
8234 /* other parameters that may have been set for this test, but at the */
8235 /* moment, I do not wish to figure-out all the formatting, so I will */
8236 /* just put this comment here to help remind me that it is something */
8237 /* that should be done at a later time. */
8238
8239 /* how to handle the verbose information in the presence of */
8240 /* confidence intervals is yet to be determined... raj 11/94 */
8241
8242 if (verbosity > 1) {
8243 /* The user wanted to know it all, so we will give it to him. */
8244 /* This information will include as much as we can find about */
8245 /* UDP statistics, the alignments of the sends and receives */
8246 /* and all that sort of rot... */
8247
8248 #ifdef WANT_HISTOGRAM
8249 fprintf(where,"\nHistogram of request/reponse times.\n");
8250 fflush(where);
8251 HIST_report(time_hist);
8252 #endif /* WANT_HISTOGRAM */
8253 }
8254 }
8255 #endif /* WANT_MIGRATION */
8256
8257 /* this routine implements the receive side (netserver) of a UDP_RR */
8258 /* test. */
8259 void
recv_udp_rr()8260 recv_udp_rr()
8261 {
8262
8263 struct ring_elt *recv_ring;
8264 struct ring_elt *send_ring;
8265
8266 struct addrinfo *local_res;
8267 char local_name[BUFSIZ];
8268 char port_buffer[PORTBUFSIZE];
8269
8270 struct sockaddr_storage myaddr_in;
8271 struct sockaddr_storage peeraddr;
8272 SOCKET s_data;
8273 netperf_socklen_t addrlen;
8274 int trans_received;
8275 int trans_remaining;
8276 int request_bytes_recvd;
8277 int response_bytes_sent;
8278 float elapsed_time;
8279
8280 struct udp_rr_request_struct *udp_rr_request;
8281 struct udp_rr_response_struct *udp_rr_response;
8282 struct udp_rr_results_struct *udp_rr_results;
8283
8284 udp_rr_request =
8285 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
8286 udp_rr_response =
8287 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
8288 udp_rr_results =
8289 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
8290
8291 if (debug) {
8292 fprintf(where,"netserver: recv_udp_rr: entered...\n");
8293 fflush(where);
8294 }
8295
8296 /* We want to set-up the listen socket with all the desired */
8297 /* parameters and then let the initiator know that all is ready. If */
8298 /* socket size defaults are to be used, then the initiator will have */
8299 /* sent us 0's. If the socket sizes cannot be changed, then we will */
8300 /* send-back what they are. If that information cannot be determined, */
8301 /* then we send-back -1's for the sizes. If things go wrong for any */
8302 /* reason, we will drop back ten yards and punt. */
8303
8304 /* If anything goes wrong, we want the remote to know about it. It */
8305 /* would be best if the error that the remote reports to the user is */
8306 /* the actual error we encountered, rather than some bogus unexpected */
8307 /* response type message. */
8308
8309 if (debug) {
8310 fprintf(where,"recv_udp_rr: setting the response type...\n");
8311 fflush(where);
8312 }
8313
8314 netperf_response.content.response_type = UDP_RR_RESPONSE;
8315
8316 if (debug) {
8317 fprintf(where,"recv_udp_rr: the response type is set...\n");
8318 fflush(where);
8319 }
8320
8321 /* We now alter the message_ptr variables to be at the desired */
8322 /* alignments with the desired offsets. */
8323
8324 if (debug) {
8325 fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n",
8326 udp_rr_request->recv_alignment,
8327 udp_rr_request->recv_offset);
8328 fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n",
8329 udp_rr_request->send_alignment,
8330 udp_rr_request->send_offset);
8331 fflush(where);
8332 }
8333
8334 if (send_width == 0) send_width = 1;
8335 if (recv_width == 0) recv_width = 1;
8336
8337 recv_ring = allocate_buffer_ring(recv_width,
8338 udp_rr_request->request_size,
8339 udp_rr_request->recv_alignment,
8340 udp_rr_request->recv_offset);
8341
8342 send_ring = allocate_buffer_ring(send_width,
8343 udp_rr_request->response_size,
8344 udp_rr_request->send_alignment,
8345 udp_rr_request->send_offset);
8346
8347 if (debug) {
8348 fprintf(where,"recv_udp_rr: receive alignment and offset set...\n");
8349 fflush(where);
8350 }
8351
8352 /* Grab a socket to listen on, and then listen on it. */
8353
8354 if (debug) {
8355 fprintf(where,"recv_udp_rr: grabbing a socket...\n");
8356 fflush(where);
8357 }
8358
8359
8360 /* create_data_socket expects to find some things in the global */
8361 /* variables, so set the globals based on the values in the request. */
8362 /* once the socket has been created, we will set the response values */
8363 /* based on the updated value of those globals. raj 7/94 */
8364 lss_size_req = udp_rr_request->send_buf_size;
8365 lsr_size_req = udp_rr_request->recv_buf_size;
8366 loc_rcvavoid = udp_rr_request->so_rcvavoid;
8367 loc_sndavoid = udp_rr_request->so_sndavoid;
8368
8369 set_hostname_and_port(local_name,
8370 port_buffer,
8371 nf_to_af(udp_rr_request->ipfamily),
8372 udp_rr_request->port);
8373
8374 local_res = complete_addrinfo(local_name,
8375 local_name,
8376 port_buffer,
8377 nf_to_af(udp_rr_request->ipfamily),
8378 SOCK_DGRAM,
8379 IPPROTO_UDP,
8380 0);
8381
8382 s_data = create_data_socket(local_res);
8383
8384 if (s_data == INVALID_SOCKET) {
8385 netperf_response.content.serv_errno = errno;
8386 send_response();
8387
8388 exit(1);
8389 }
8390
8391 /* now get the port number assigned by the system */
8392 addrlen = sizeof(myaddr_in);
8393 if (getsockname(s_data,
8394 (struct sockaddr *)&myaddr_in,
8395 &addrlen) == SOCKET_ERROR){
8396 netperf_response.content.serv_errno = errno;
8397 close(s_data);
8398 send_response();
8399
8400 exit(1);
8401 }
8402
8403 /* Now myaddr_in contains the port and the internet address this is */
8404 /* returned to the sender also implicitly telling the sender that the */
8405 /* socket buffer sizing has been done. */
8406
8407 udp_rr_response->data_port_number =
8408 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
8409 netperf_response.content.serv_errno = 0;
8410
8411 if (debug) {
8412 fprintf(where,
8413 "recv port number %d\n",
8414 ((struct sockaddr_in *)&myaddr_in)->sin_port);
8415 fflush(where);
8416 }
8417
8418 /* But wait, there's more. If the initiator wanted cpu measurements, */
8419 /* then we must call the calibrate routine, which will return the max */
8420 /* rate back to the initiator. If the CPU was not to be measured, or */
8421 /* something went wrong with the calibration, we will return a 0.0 to */
8422 /* the initiator. */
8423
8424 udp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
8425 udp_rr_response->measure_cpu = 0;
8426 if (udp_rr_request->measure_cpu) {
8427 udp_rr_response->measure_cpu = 1;
8428 udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate);
8429 }
8430
8431 /* before we send the response back to the initiator, pull some of */
8432 /* the socket parms from the globals */
8433 udp_rr_response->send_buf_size = lss_size;
8434 udp_rr_response->recv_buf_size = lsr_size;
8435 udp_rr_response->so_rcvavoid = loc_rcvavoid;
8436 udp_rr_response->so_sndavoid = loc_sndavoid;
8437
8438 send_response();
8439
8440
8441 /* Now it's time to start receiving data on the connection. We will */
8442 /* first grab the apropriate counters and then start grabbing. */
8443
8444 cpu_start(udp_rr_request->measure_cpu);
8445
8446 #ifdef WIN32
8447 /* this is used so the timer thread can close the socket out from */
8448 /* under us, which to date is the easiest/cleanest/least */
8449 /* Windows-specific way I can find to force the winsock calls to */
8450 /* return WSAEINTR with the test is over. anything that will run on */
8451 /* 95 and NT and is closer to what netperf expects from Unix signals */
8452 /* and such would be appreciated raj 1/96 */
8453 win_kludge_socket = s_data;
8454 #endif /* WIN32 */
8455
8456 if (udp_rr_request->test_length > 0) {
8457 times_up = 0;
8458 trans_remaining = 0;
8459 start_timer(udp_rr_request->test_length + PAD_TIME);
8460 }
8461 else {
8462 times_up = 1;
8463 trans_remaining = udp_rr_request->test_length * -1;
8464 }
8465
8466 addrlen = sizeof(peeraddr);
8467 bzero((char *)&peeraddr, addrlen);
8468
8469 trans_received = 0;
8470
8471 while ((!times_up) || (trans_remaining > 0)) {
8472
8473 /* receive the request from the other side */
8474 if ((request_bytes_recvd = recvfrom(s_data,
8475 recv_ring->buffer_ptr,
8476 udp_rr_request->request_size,
8477 0,
8478 (struct sockaddr *)&peeraddr,
8479 &addrlen)) != udp_rr_request->request_size) {
8480 if ( SOCKET_EINTR(request_bytes_recvd) )
8481 {
8482 /* we must have hit the end of test time. */
8483 break;
8484 }
8485 netperf_response.content.serv_errno = errno;
8486 send_response();
8487 exit(1);
8488 }
8489 recv_ring = recv_ring->next;
8490
8491 /* Now, send the response to the remote */
8492 if ((response_bytes_sent = sendto(s_data,
8493 send_ring->buffer_ptr,
8494 udp_rr_request->response_size,
8495 0,
8496 (struct sockaddr *)&peeraddr,
8497 addrlen)) !=
8498 udp_rr_request->response_size) {
8499 if ( SOCKET_EINTR(response_bytes_sent) )
8500 {
8501 /* we have hit end of test time. */
8502 break;
8503 }
8504 netperf_response.content.serv_errno = errno;
8505 send_response();
8506 exit(1);
8507 }
8508 send_ring = send_ring->next;
8509
8510 trans_received++;
8511 if (trans_remaining) {
8512 trans_remaining--;
8513 }
8514
8515 if (debug) {
8516 fprintf(where,
8517 "recv_udp_rr: Transaction %d complete.\n",
8518 trans_received);
8519 fflush(where);
8520 }
8521
8522 }
8523
8524
8525 /* The loop now exits due to timeout or transaction count being */
8526 /* reached */
8527
8528 cpu_stop(udp_rr_request->measure_cpu,&elapsed_time);
8529
8530 if (times_up) {
8531 /* we ended the test by time, which was at least 2 seconds */
8532 /* longer than we wanted to run. so, we want to subtract */
8533 /* PAD_TIME from the elapsed_time. */
8534 elapsed_time -= PAD_TIME;
8535 }
8536 /* send the results to the sender */
8537
8538 if (debug) {
8539 fprintf(where,
8540 "recv_udp_rr: got %d transactions\n",
8541 trans_received);
8542 fflush(where);
8543 }
8544
8545 udp_rr_results->bytes_received = (trans_received *
8546 (udp_rr_request->request_size +
8547 udp_rr_request->response_size));
8548 udp_rr_results->trans_received = trans_received;
8549 udp_rr_results->elapsed_time = elapsed_time;
8550 udp_rr_results->cpu_method = cpu_method;
8551 udp_rr_results->num_cpus = lib_num_loc_cpus;
8552 if (udp_rr_request->measure_cpu) {
8553 udp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
8554 }
8555
8556 if (debug) {
8557 fprintf(where,
8558 "recv_udp_rr: test complete, sending results.\n");
8559 fflush(where);
8560 }
8561
8562 send_response();
8563
8564 /* we are done with the socket now */
8565 close(s_data);
8566
8567 }
8568
8569
8570 /* this routine implements the receive (netserver) side of a TCP_RR */
8571 /* test */
8572 void
recv_tcp_rr()8573 recv_tcp_rr()
8574 {
8575
8576 struct ring_elt *send_ring;
8577 struct ring_elt *recv_ring;
8578
8579 struct addrinfo *local_res;
8580 char local_name[BUFSIZ];
8581 char port_buffer[PORTBUFSIZE];
8582
8583 struct sockaddr_storage myaddr_in,
8584 peeraddr_in;
8585 SOCKET s_listen,s_data;
8586 netperf_socklen_t addrlen;
8587 char *temp_message_ptr;
8588 int trans_received;
8589 int trans_remaining;
8590 int bytes_sent;
8591 int request_bytes_recvd;
8592 int request_bytes_remaining;
8593 int timed_out = 0;
8594 int sock_closed = 0;
8595 float elapsed_time;
8596
8597 struct tcp_rr_request_struct *tcp_rr_request;
8598 struct tcp_rr_response_struct *tcp_rr_response;
8599 struct tcp_rr_results_struct *tcp_rr_results;
8600
8601 tcp_rr_request =
8602 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
8603 tcp_rr_response =
8604 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
8605 tcp_rr_results =
8606 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
8607
8608 if (debug) {
8609 fprintf(where,"netserver: recv_tcp_rr: entered...\n");
8610 fflush(where);
8611 }
8612
8613 /* We want to set-up the listen socket with all the desired */
8614 /* parameters and then let the initiator know that all is ready. If */
8615 /* socket size defaults are to be used, then the initiator will have */
8616 /* sent us 0's. If the socket sizes cannot be changed, then we will */
8617 /* send-back what they are. If that information cannot be determined, */
8618 /* then we send-back -1's for the sizes. If things go wrong for any */
8619 /* reason, we will drop back ten yards and punt. */
8620
8621 /* If anything goes wrong, we want the remote to know about it. It */
8622 /* would be best if the error that the remote reports to the user is */
8623 /* the actual error we encountered, rather than some bogus unexpected */
8624 /* response type message. */
8625
8626 if (debug) {
8627 fprintf(where,"recv_tcp_rr: setting the response type...\n");
8628 fflush(where);
8629 }
8630
8631 netperf_response.content.response_type = TCP_RR_RESPONSE;
8632
8633 if (debug) {
8634 fprintf(where,"recv_tcp_rr: the response type is set...\n");
8635 fflush(where);
8636 }
8637
8638 /* allocate the recv and send rings with the requested alignments */
8639 /* and offsets. raj 7/94 */
8640 if (debug) {
8641 fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n",
8642 tcp_rr_request->recv_alignment,
8643 tcp_rr_request->recv_offset);
8644 fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n",
8645 tcp_rr_request->send_alignment,
8646 tcp_rr_request->send_offset);
8647 fflush(where);
8648 }
8649
8650 /* at some point, these need to come to us from the remote system */
8651 if (send_width == 0) send_width = 1;
8652 if (recv_width == 0) recv_width = 1;
8653
8654 send_ring = allocate_buffer_ring(send_width,
8655 tcp_rr_request->response_size,
8656 tcp_rr_request->send_alignment,
8657 tcp_rr_request->send_offset);
8658
8659 recv_ring = allocate_buffer_ring(recv_width,
8660 tcp_rr_request->request_size,
8661 tcp_rr_request->recv_alignment,
8662 tcp_rr_request->recv_offset);
8663
8664
8665 /* Grab a socket to listen on, and then listen on it. */
8666
8667 if (debug) {
8668 fprintf(where,"recv_tcp_rr: grabbing a socket...\n");
8669 fflush(where);
8670 }
8671
8672 /* create_data_socket expects to find some things in the global */
8673 /* variables, so set the globals based on the values in the request. */
8674 /* once the socket has been created, we will set the response values */
8675 /* based on the updated value of those globals. raj 7/94 */
8676 lss_size_req = tcp_rr_request->send_buf_size;
8677 lsr_size_req = tcp_rr_request->recv_buf_size;
8678 loc_nodelay = tcp_rr_request->no_delay;
8679 loc_rcvavoid = tcp_rr_request->so_rcvavoid;
8680 loc_sndavoid = tcp_rr_request->so_sndavoid;
8681
8682 set_hostname_and_port(local_name,
8683 port_buffer,
8684 nf_to_af(tcp_rr_request->ipfamily),
8685 tcp_rr_request->port);
8686
8687 local_res = complete_addrinfo(local_name,
8688 local_name,
8689 port_buffer,
8690 nf_to_af(tcp_rr_request->ipfamily),
8691 SOCK_STREAM,
8692 IPPROTO_TCP,
8693 0);
8694
8695 s_listen = create_data_socket(local_res);
8696
8697 if (s_listen == INVALID_SOCKET) {
8698 netperf_response.content.serv_errno = errno;
8699 send_response();
8700
8701 exit(1);
8702 }
8703
8704
8705 #ifdef WIN32
8706 /* The test timer can fire during operations on the listening socket,
8707 so to make the start_timer below work we have to move
8708 it to close s_listen while we are blocked on accept. */
8709 win_kludge_socket2 = s_listen;
8710 #endif
8711
8712
8713 /* Now, let's set-up the socket to listen for connections */
8714 if (listen(s_listen, 5) == SOCKET_ERROR) {
8715 netperf_response.content.serv_errno = errno;
8716 close(s_listen);
8717 send_response();
8718
8719 exit(1);
8720 }
8721
8722
8723 /* now get the port number assigned by the system */
8724 addrlen = sizeof(myaddr_in);
8725 if (getsockname(s_listen,
8726 (struct sockaddr *)&myaddr_in,
8727 &addrlen) == SOCKET_ERROR) {
8728 netperf_response.content.serv_errno = errno;
8729 close(s_listen);
8730 send_response();
8731
8732 exit(1);
8733 }
8734
8735 /* Now myaddr_in contains the port and the internet address this is */
8736 /* returned to the sender also implicitly telling the sender that the */
8737 /* socket buffer sizing has been done. */
8738
8739 tcp_rr_response->data_port_number =
8740 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
8741 netperf_response.content.serv_errno = 0;
8742
8743 /* But wait, there's more. If the initiator wanted cpu measurements, */
8744 /* then we must call the calibrate routine, which will return the max */
8745 /* rate back to the initiator. If the CPU was not to be measured, or */
8746 /* something went wrong with the calibration, we will return a 0.0 to */
8747 /* the initiator. */
8748
8749 tcp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
8750 tcp_rr_response->measure_cpu = 0;
8751
8752 if (tcp_rr_request->measure_cpu) {
8753 tcp_rr_response->measure_cpu = 1;
8754 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
8755 }
8756
8757
8758 /* before we send the response back to the initiator, pull some of */
8759 /* the socket parms from the globals */
8760 tcp_rr_response->send_buf_size = lss_size;
8761 tcp_rr_response->recv_buf_size = lsr_size;
8762 tcp_rr_response->no_delay = loc_nodelay;
8763 tcp_rr_response->so_rcvavoid = loc_rcvavoid;
8764 tcp_rr_response->so_sndavoid = loc_sndavoid;
8765 tcp_rr_response->test_length = tcp_rr_request->test_length;
8766 send_response();
8767
8768 addrlen = sizeof(peeraddr_in);
8769
8770 if ((s_data = accept(s_listen,
8771 (struct sockaddr *)&peeraddr_in,
8772 &addrlen)) == INVALID_SOCKET) {
8773 /* Let's just punt. The remote will be given some information */
8774 close(s_listen);
8775
8776 exit(1);
8777 }
8778
8779 #ifdef KLUDGE_SOCKET_OPTIONS
8780 /* this is for those systems which *INCORRECTLY* fail to pass */
8781 /* attributes across an accept() call. Including this goes against */
8782 /* my better judgement :( raj 11/95 */
8783
8784 kludge_socket_options(s_data);
8785
8786 #endif /* KLUDGE_SOCKET_OPTIONS */
8787
8788 #ifdef WIN32
8789 /* this is used so the timer thread can close the socket out from */
8790 /* under us, which to date is the easiest/cleanest/least */
8791 /* Windows-specific way I can find to force the winsock calls to */
8792 /* return WSAEINTR with the test is over. anything that will run on */
8793 /* 95 and NT and is closer to what netperf expects from Unix signals */
8794 /* and such would be appreciated raj 1/96 */
8795 win_kludge_socket = s_data;
8796 win_kludge_socket2 = INVALID_SOCKET;
8797 #endif /* WIN32 */
8798
8799 if (debug) {
8800 fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n");
8801 fflush(where);
8802 }
8803
8804 /* Now it's time to start receiving data on the connection. We will */
8805 /* first grab the apropriate counters and then start grabbing. */
8806
8807 cpu_start(tcp_rr_request->measure_cpu);
8808
8809 /* The loop will exit when we hit the end of the test time, or when */
8810 /* we have exchanged the requested number of transactions. */
8811
8812 if (tcp_rr_request->test_length > 0) {
8813 times_up = 0;
8814 trans_remaining = 0;
8815 start_timer(tcp_rr_request->test_length + PAD_TIME);
8816 }
8817 else {
8818 times_up = 1;
8819 trans_remaining = tcp_rr_request->test_length * -1;
8820 }
8821
8822 trans_received = 0;
8823
8824 while ((!times_up) || (trans_remaining > 0)) {
8825 temp_message_ptr = recv_ring->buffer_ptr;
8826 request_bytes_remaining = tcp_rr_request->request_size;
8827 while(request_bytes_remaining > 0) {
8828 if((request_bytes_recvd=recv(s_data,
8829 temp_message_ptr,
8830 request_bytes_remaining,
8831 0)) == SOCKET_ERROR) {
8832 if (SOCKET_EINTR(request_bytes_recvd))
8833 {
8834 timed_out = 1;
8835 break;
8836 }
8837
8838 netperf_response.content.serv_errno = errno;
8839 send_response();
8840 exit(1);
8841 }
8842 else if( request_bytes_recvd == 0 ) {
8843 if (debug) {
8844 fprintf(where,"zero is my hero\n");
8845 fflush(where);
8846 }
8847 sock_closed = 1;
8848 break;
8849 }
8850 else {
8851 request_bytes_remaining -= request_bytes_recvd;
8852 temp_message_ptr += request_bytes_recvd;
8853 }
8854 }
8855
8856 recv_ring = recv_ring->next;
8857
8858 if ((timed_out) || (sock_closed)) {
8859 /* we hit the end of the test based on time - or the socket
8860 closed on us along the way. bail out of here now... */
8861 if (debug) {
8862 fprintf(where,"yo5\n");
8863 fflush(where);
8864 }
8865 break;
8866 }
8867
8868 /* Now, send the response to the remote */
8869 if((bytes_sent=send(s_data,
8870 send_ring->buffer_ptr,
8871 tcp_rr_request->response_size,
8872 0)) == SOCKET_ERROR) {
8873 if (SOCKET_EINTR(bytes_sent)) {
8874 /* the test timer has popped */
8875 timed_out = 1;
8876 fprintf(where,"yo6\n");
8877 fflush(where);
8878 break;
8879 }
8880 netperf_response.content.serv_errno = 992;
8881 send_response();
8882 exit(1);
8883 }
8884
8885 send_ring = send_ring->next;
8886
8887 trans_received++;
8888 if (trans_remaining) {
8889 trans_remaining--;
8890 }
8891 }
8892
8893
8894 /* The loop now exits due to timeout or transaction count being */
8895 /* reached */
8896
8897 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
8898
8899 stop_timer();
8900
8901 if (timed_out) {
8902 /* we ended the test by time, which was at least 2 seconds */
8903 /* longer than we wanted to run. so, we want to subtract */
8904 /* PAD_TIME from the elapsed_time. */
8905 elapsed_time -= PAD_TIME;
8906 }
8907
8908 /* send the results to the sender */
8909
8910 if (debug) {
8911 fprintf(where,
8912 "recv_tcp_rr: got %d transactions\n",
8913 trans_received);
8914 fflush(where);
8915 }
8916
8917 tcp_rr_results->bytes_received = (trans_received *
8918 (tcp_rr_request->request_size +
8919 tcp_rr_request->response_size));
8920 tcp_rr_results->trans_received = trans_received;
8921 tcp_rr_results->elapsed_time = elapsed_time;
8922 tcp_rr_results->cpu_method = cpu_method;
8923 tcp_rr_results->num_cpus = lib_num_loc_cpus;
8924 if (tcp_rr_request->measure_cpu) {
8925 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
8926 }
8927
8928 if (debug) {
8929 fprintf(where,
8930 "recv_tcp_rr: test complete, sending results.\n");
8931 fflush(where);
8932 }
8933
8934 /* we are now done with the sockets */
8935 close(s_data);
8936 close(s_listen);
8937
8938 send_response();
8939
8940 }
8941
8942
8943 void
loc_cpu_rate()8944 loc_cpu_rate()
8945 {
8946 #if defined(USE_LOOPER)
8947 float dummy;
8948 #endif
8949
8950 /* a rather simple little test - it merely calibrates the local cpu */
8951 /* and prints the results. There are no headers to allow someone to */
8952 /* find a rate and use it in other tests automagically by setting a */
8953 /* variable equal to the output of this test. We ignore any rates */
8954 /* that may have been specified. In fact, we ignore all of the */
8955 /* command line args! */
8956
8957 fprintf(where,
8958 "%g",
8959 calibrate_local_cpu(0.0));
8960
8961 if (verbosity > 1)
8962 fprintf(where,
8963 "\nThere %s %d local %s\n",
8964 (lib_num_loc_cpus > 1) ? "are" : "is",
8965 lib_num_loc_cpus,
8966 (lib_num_loc_cpus > 1) ? "cpus" : "cpu");
8967
8968 /* we need the cpu_start, cpu_stop in the looper case to kill the */
8969 /* child proceses raj 4/95 */
8970
8971 #ifdef USE_LOOPER
8972 cpu_start(1);
8973 cpu_stop(1,&dummy);
8974 #endif /* USE_LOOPER */
8975
8976 }
8977
8978 void
rem_cpu_rate()8979 rem_cpu_rate()
8980 {
8981 /* this test is much like the local variant, except that it works for */
8982 /* the remote system, so in this case, we do pay attention to the */
8983 /* value of the '-H' command line argument. */
8984
8985 fprintf(where,
8986 "%g",
8987 calibrate_remote_cpu());
8988
8989 if (verbosity > 1)
8990 fprintf(where,
8991 "\nThere %s %d remote %s\n",
8992 (lib_num_rem_cpus > 1) ? "are" : "is",
8993 lib_num_rem_cpus,
8994 (lib_num_rem_cpus > 1) ? "cpus" : "cpu");
8995
8996 }
8997
8998
8999 #ifndef WANT_MIGRATION
9000 /* this test is intended to test the performance of establishing a
9001 connection, exchanging a request/response pair, and repeating. it
9002 is expected that this would be a good starting-point for
9003 comparision of T/TCP with classic TCP for transactional workloads.
9004 it will also look (can look) much like the communication pattern
9005 of http for www access. */
9006
9007 void
send_tcp_conn_rr(char remote_host[])9008 send_tcp_conn_rr(char remote_host[])
9009 {
9010
9011 char *tput_title = "\
9012 Local /Remote\n\
9013 Socket Size Request Resp. Elapsed Trans.\n\
9014 Send Recv Size Size Time Rate \n\
9015 bytes Bytes bytes bytes secs. per sec \n\n";
9016
9017 char *tput_fmt_0 =
9018 "%7.2f\n";
9019
9020 char *tput_fmt_1_line_1 = "\
9021 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
9022 char *tput_fmt_1_line_2 = "\
9023 %-6d %-6d\n";
9024
9025 char *cpu_title = "\
9026 Local /Remote\n\
9027 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
9028 Send Recv Size Size Time Rate local remote local remote\n\
9029 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
9030
9031 char *cpu_fmt_0 =
9032 "%6.3f\n";
9033
9034 char *cpu_fmt_1_line_1 = "\
9035 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
9036
9037 char *cpu_fmt_1_line_2 = "\
9038 %-6d %-6d\n";
9039
9040 char *ksink_fmt = "\n\
9041 Alignment Offset\n\
9042 Local Remote Local Remote\n\
9043 Send Recv Send Recv\n\
9044 %5d %5d %5d %5d\n";
9045
9046
9047 int timed_out = 0;
9048 float elapsed_time;
9049
9050 int len;
9051 struct ring_elt *send_ring;
9052 struct ring_elt *recv_ring;
9053 char *temp_message_ptr;
9054 int nummessages;
9055 SOCKET send_socket;
9056 int trans_remaining;
9057 double bytes_xferd;
9058 int rsp_bytes_left;
9059 int rsp_bytes_recvd;
9060
9061 float local_cpu_utilization;
9062 float local_service_demand;
9063 float remote_cpu_utilization;
9064 float remote_service_demand;
9065 double thruput;
9066
9067 struct addrinfo *local_res;
9068 struct addrinfo *remote_res;
9069
9070 int myport;
9071 int ret;
9072
9073 struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
9074 struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
9075 struct tcp_conn_rr_results_struct *tcp_conn_rr_result;
9076
9077 tcp_conn_rr_request =
9078 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
9079 tcp_conn_rr_response =
9080 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
9081 tcp_conn_rr_result =
9082 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
9083
9084
9085 #ifdef WANT_HISTOGRAM
9086 if (verbosity > 1) {
9087 time_hist = HIST_new();
9088 }
9089 #endif /* WANT_HISTOGRAM */
9090
9091 /* since we are now disconnected from the code that established the */
9092 /* control socket, and since we want to be able to use different */
9093 /* protocols and such, we are passed the name of the remote host and */
9094 /* must turn that into the test specific addressing information. */
9095
9096 complete_addrinfos(&remote_res,
9097 &local_res,
9098 remote_host,
9099 SOCK_STREAM,
9100 IPPROTO_TCP,
9101 0);
9102
9103 if ( print_headers ) {
9104 print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res);
9105 }
9106
9107 /* initialize a few counters */
9108
9109 nummessages = 0;
9110 bytes_xferd = 0.0;
9111 times_up = 0;
9112
9113 /* set-up the data buffers with the requested alignment and offset */
9114 if (send_width == 0) send_width = 1;
9115 if (recv_width == 0) recv_width = 1;
9116
9117 send_ring = allocate_buffer_ring(send_width,
9118 req_size,
9119 local_send_align,
9120 local_send_offset);
9121
9122 recv_ring = allocate_buffer_ring(recv_width,
9123 rsp_size,
9124 local_recv_align,
9125 local_recv_offset);
9126
9127
9128 if (debug) {
9129 fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n");
9130 }
9131
9132 /* If the user has requested cpu utilization measurements, we must */
9133 /* calibrate the cpu(s). We will perform this task within the tests */
9134 /* themselves. If the user has specified the cpu rate, then */
9135 /* calibrate_local_cpu will return rather quickly as it will have */
9136 /* nothing to do. If local_cpu_rate is zero, then we will go through */
9137 /* all the "normal" calibration stuff and return the rate back.*/
9138
9139 if (local_cpu_usage) {
9140 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
9141 }
9142
9143 if (!no_control) {
9144
9145 /* Tell the remote end to do a listen. The server alters the
9146 socket paramters on the other side at this point, hence the
9147 reason for all the values being passed in the setup message. If
9148 the user did not specify any of the parameters, they will be
9149 passed as 0, which will indicate to the remote that no changes
9150 beyond the system's default should be used. Alignment is the
9151 exception, it will default to 8, which will be no alignment
9152 alterations. */
9153
9154 netperf_request.content.request_type = DO_TCP_CRR;
9155 tcp_conn_rr_request->recv_buf_size = rsr_size_req;
9156 tcp_conn_rr_request->send_buf_size = rss_size_req;
9157 tcp_conn_rr_request->recv_alignment = remote_recv_align;
9158 tcp_conn_rr_request->recv_offset = remote_recv_offset;
9159 tcp_conn_rr_request->send_alignment = remote_send_align;
9160 tcp_conn_rr_request->send_offset = remote_send_offset;
9161 tcp_conn_rr_request->request_size = req_size;
9162 tcp_conn_rr_request->response_size = rsp_size;
9163 tcp_conn_rr_request->no_delay = rem_nodelay;
9164 tcp_conn_rr_request->measure_cpu = remote_cpu_usage;
9165 tcp_conn_rr_request->cpu_rate = remote_cpu_rate;
9166 tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid;
9167 tcp_conn_rr_request->so_sndavoid = rem_sndavoid;
9168 if (test_time) {
9169 tcp_conn_rr_request->test_length = test_time;
9170 }
9171 else {
9172 tcp_conn_rr_request->test_length = test_trans * -1;
9173 }
9174 tcp_conn_rr_request->port = atoi(remote_data_port);
9175 tcp_conn_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
9176
9177 if (debug > 1) {
9178 fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n");
9179 }
9180
9181 send_request();
9182
9183 /* The response from the remote will contain all of the relevant
9184 socket parameters for this test type. We will put them back
9185 into the variables here so they can be displayed if desired.
9186 The remote will have calibrated CPU if necessary, and will have
9187 done all the needed set-up we will have calibrated the cpu
9188 locally before sending the request, and will grab the counter
9189 value right after the connect returns. The remote will grab the
9190 counter right after the accept call. This saves the hassle of
9191 extra messages being sent for the TCP tests. */
9192
9193 recv_response();
9194
9195 if (!netperf_response.content.serv_errno) {
9196 rsr_size = tcp_conn_rr_response->recv_buf_size;
9197 rss_size = tcp_conn_rr_response->send_buf_size;
9198 rem_nodelay = tcp_conn_rr_response->no_delay;
9199 remote_cpu_usage = tcp_conn_rr_response->measure_cpu;
9200 remote_cpu_rate = tcp_conn_rr_response->cpu_rate;
9201 /* make sure that port numbers are in network order */
9202 set_port_number(remote_res,
9203 (unsigned short)tcp_conn_rr_response->data_port_number);
9204
9205 if (debug) {
9206 fprintf(where,"remote listen done.\n");
9207 fprintf(where,"remote port is %u\n",get_port_number(remote_res));
9208 fflush(where);
9209 }
9210 }
9211 else {
9212 Set_errno(netperf_response.content.serv_errno);
9213 fprintf(where,
9214 "netperf: remote error %d",
9215 netperf_response.content.serv_errno);
9216 perror("");
9217 fflush(where);
9218 exit(1);
9219 }
9220 }
9221 #ifdef WANT_DEMO
9222 demo_rr_setup(100);
9223 #endif
9224
9225 /* pick a nice random spot between client_port_min and */
9226 /* client_port_max for our initial port number */
9227 srand(getpid());
9228 if (client_port_max - client_port_min) {
9229 myport = client_port_min +
9230 (rand() % (client_port_max - client_port_min));
9231 }
9232 else {
9233 myport = client_port_min;
9234 }
9235 /* there will be a ++ before the first call to bind, so subtract one */
9236 myport--;
9237 /* Set-up the test end conditions. For a request/response test, they */
9238 /* can be either time or transaction based. */
9239
9240 if (test_time) {
9241 /* The user wanted to end the test after a period of time. */
9242 times_up = 0;
9243 trans_remaining = 0;
9244 start_timer(test_time);
9245 }
9246 else {
9247 /* The tester wanted to send a number of bytes. */
9248 trans_remaining = test_bytes;
9249 times_up = 1;
9250 }
9251
9252 /* The cpu_start routine will grab the current time and possibly */
9253 /* value of the idle counter for later use in measuring cpu */
9254 /* utilization and/or service demand and thruput. */
9255
9256
9257 cpu_start(local_cpu_usage);
9258
9259 #ifdef WANT_DEMO
9260 if (demo_mode) {
9261 demo_first_timestamp();
9262 }
9263 #endif
9264
9265 /* We use an "OR" to control test execution. When the test is */
9266 /* controlled by time, the byte count check will always return false. */
9267 /* When the test is controlled by byte count, the time test will */
9268 /* always return false. When the test is finished, the whole */
9269 /* expression will go false and we will stop sending data. I think I */
9270 /* just arbitrarily decrement trans_remaining for the timed test, but */
9271 /* will not do that just yet... One other question is whether or not */
9272 /* the send buffer and the receive buffer should be the same buffer. */
9273
9274 while ((!times_up) || (trans_remaining > 0)) {
9275
9276 #ifdef WANT_HISTOGRAM
9277 if (verbosity > 1) {
9278 /* timestamp just before our call to create the socket, and then */
9279 /* again just after the receive raj 3/95 */
9280 HIST_timestamp(&time_one);
9281 }
9282 #endif /* WANT_HISTOGRAM */
9283
9284 newport:
9285 /* pick a new port number */
9286 myport++;
9287
9288 /* wrap the port number when we get to client_port_max. NOTE, some */
9289 /* broken TCP's might treat the port number as a signed 16 bit */
9290 /* quantity. we aren't interested in testing such broken */
9291 /* implementations :) so we won't make sure that it is below 32767 */
9292 /* raj 8/94 */
9293 if (myport >= client_port_max) {
9294 myport = client_port_min;
9295 }
9296
9297 /* we do not want to use the port number that the server is */
9298 /* sitting at - this would cause us to fail in a loopback test. we */
9299 /* could just rely on the failure of the bind to get us past this, */
9300 /* but I'm guessing that in this one case at least, it is much */
9301 /* faster, given that we *know* that port number is already in use */
9302 /* (or rather would be in a loopback test) */
9303
9304 if (myport == get_port_number(remote_res)) myport++;
9305
9306 if (debug) {
9307 if ((nummessages % 100) == 0) {
9308 printf("port %d\n",myport);
9309 }
9310 }
9311
9312 /* set up the data socket */
9313 set_port_number(local_res, (unsigned short)myport);
9314 send_socket = create_data_socket(local_res);
9315
9316 if (send_socket == INVALID_SOCKET) {
9317 perror("netperf: send_tcp_conn_rr: tcp stream data socket");
9318 exit(1);
9319 }
9320
9321
9322 /* we used to call bind here, but that is now taken-care-of by the
9323 create_data_socket routine. */
9324
9325 /* Connect up to the remote port on the data socket */
9326 if ((ret = connect(send_socket,
9327 remote_res->ai_addr,
9328 remote_res->ai_addrlen)) == INVALID_SOCKET){
9329 if (SOCKET_EINTR(ret))
9330 {
9331 /* we hit the end of a */
9332 /* timed test. */
9333 timed_out = 1;
9334 break;
9335 }
9336 if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) {
9337 /* likely something our explicit bind() would have caught in
9338 the past, so go get another port, via create_data_socket.
9339 yes, this is a bit more overhead than before, but the
9340 condition should be rather rare. raj 2005-02-08 */
9341 close(send_socket);
9342 goto newport;
9343 }
9344 perror("netperf: data socket connect failed");
9345 printf("\tattempted to connect on socket %d to port %d",
9346 send_socket,
9347 get_port_number(remote_res));
9348 printf(" from port %d \n",get_port_number(local_res));
9349 exit(1);
9350 }
9351
9352
9353 /* send the request */
9354 if((len=send(send_socket,
9355 send_ring->buffer_ptr,
9356 req_size,
9357 0)) != req_size) {
9358 if (SOCKET_EINTR(len))
9359 {
9360 /* we hit the end of a */
9361 /* timed test. */
9362 timed_out = 1;
9363 break;
9364 }
9365 perror("send_tcp_conn_rr: data send error");
9366 exit(1);
9367 }
9368 send_ring = send_ring->next;
9369
9370 /* receive the response */
9371 rsp_bytes_left = rsp_size;
9372 temp_message_ptr = recv_ring->buffer_ptr;
9373
9374
9375 do {
9376 rsp_bytes_recvd = recv(send_socket,
9377 temp_message_ptr,
9378 rsp_bytes_left,
9379 0);
9380 if (rsp_bytes_recvd > 0) {
9381 rsp_bytes_left -= rsp_bytes_recvd;
9382 temp_message_ptr += rsp_bytes_recvd;
9383 }
9384 else {
9385 break;
9386 }
9387 } while (rsp_bytes_left);
9388
9389
9390 /* OK, we are out of the loop - now what? */
9391 if (rsp_bytes_recvd < 0) {
9392 /* did the timer hit, or was there an error? */
9393 if (SOCKET_EINTR(rsp_bytes_recvd))
9394 {
9395 /* We hit the end of a timed test. */
9396 timed_out = 1;
9397 break;
9398 }
9399 perror("send_tcp_conn_rr: data recv error");
9400 exit(1);
9401 }
9402
9403 /* if this is a no_control test, we initiate connection close,
9404 otherwise the remote netserver does it to remain just like
9405 previous behaviour. raj 2007-27-08 */
9406 if (!no_control) {
9407 shutdown(send_socket,SHUT_WR);
9408 }
9409
9410 /* we are expecting to get either a return of zero indicating
9411 connection close, or an error. */
9412 rsp_bytes_recvd = recv(send_socket,
9413 temp_message_ptr,
9414 1,
9415 0);
9416
9417 /* our exit from the while loop should generally be when */
9418 /* tmp_bytes_recvd is equal to zero, which implies the connection */
9419 /* has been closed by the server side. By waiting until we get the */
9420 /* zero return we can avoid race conditions that stick us with the */
9421 /* TIME_WAIT connection and not the server. raj 8/96 */
9422
9423 #ifdef VMWARE_UW
9424 /* why this should be for VMware I'm not sure, but it was given as
9425 part of the patches, so we include it here, but put it under an
9426 ifdef VMWARE_UW. raj 2008-07-25 */
9427 if (sp_bytes_recvd < 0 && errno == ECONNRESET) {
9428 rsp_bytes_recvd = 0;
9429 }
9430 #endif /* VMWARE_UW */
9431
9432 if (rsp_bytes_recvd == 0) {
9433 /* connection close, call close. we assume that the requisite */
9434 /* number of bytes have been received */
9435 recv_ring = recv_ring->next;
9436
9437 #ifdef WANT_HISTOGRAM
9438 if (verbosity > 1) {
9439 HIST_timestamp(&time_two);
9440 HIST_add(time_hist,delta_micro(&time_one,&time_two));
9441 }
9442 #endif /* WANT_HISTOGRAM */
9443
9444 #ifdef WANT_DEMO
9445 demo_rr_interval(1);
9446 #endif
9447
9448 nummessages++;
9449 if (trans_remaining) {
9450 trans_remaining--;
9451 }
9452
9453 if (debug > 3) {
9454 fprintf(where,
9455 "Transaction %d completed on local port %d\n",
9456 nummessages,
9457 get_port_number(local_res));
9458 fflush(where);
9459 }
9460
9461 close(send_socket);
9462
9463 }
9464 else {
9465 /* it was less than zero - an error occured */
9466 if (SOCKET_EINTR(rsp_bytes_recvd))
9467 {
9468 /* We hit the end of a timed test. */
9469 timed_out = 1;
9470 break;
9471 }
9472 perror("send_tcp_conn_rr: data recv error");
9473 exit(1);
9474 }
9475
9476 }
9477
9478
9479 /* this call will always give us the elapsed time for the test, and */
9480 /* will also store-away the necessaries for cpu utilization */
9481
9482 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
9483 /* how long did we really run? */
9484
9485 if (!no_control) {
9486 /* Get the statistics from the remote end. The remote will have
9487 calculated service demand and all those interesting things. If
9488 it wasn't supposed to care, it will return obvious values. */
9489
9490 recv_response();
9491 if (!netperf_response.content.serv_errno) {
9492 if (debug)
9493 fprintf(where,"remote results obtained\n");
9494 }
9495 else {
9496 Set_errno(netperf_response.content.serv_errno);
9497 fprintf(where,
9498 "netperf: remote error %d",
9499 netperf_response.content.serv_errno);
9500 perror("");
9501 fflush(where);
9502
9503 exit(1);
9504 }
9505 }
9506
9507 /* We now calculate what our thruput was for the test. In the future, */
9508 /* we may want to include a calculation of the thruput measured by */
9509 /* the remote, but it should be the case that for a TCP stream test, */
9510 /* that the two numbers should be *very* close... We calculate */
9511 /* bytes_sent regardless of the way the test length was controlled. */
9512 /* If it was time, we needed to, and if it was by bytes, the user may */
9513 /* have specified a number of bytes that wasn't a multiple of the */
9514 /* send_size, so we really didn't send what he asked for ;-) We use */
9515 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
9516 /* 1024. A future enhancement *might* be to choose from a couple of */
9517 /* unit selections. */
9518
9519 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
9520 thruput = calc_thruput(bytes_xferd);
9521
9522 if (local_cpu_usage || remote_cpu_usage) {
9523 /* We must now do a little math for service demand and cpu */
9524 /* utilization for the system(s) */
9525 /* Of course, some of the information might be bogus because */
9526 /* there was no idle counter in the kernel(s). We need to make */
9527 /* a note of this for the user's benefit...*/
9528 if (local_cpu_usage) {
9529 if (local_cpu_rate == 0.0) {
9530 fprintf(where,
9531 "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
9532 fprintf(where,
9533 "Local CPU usage numbers based on process information only!\n");
9534 fflush(where);
9535 }
9536 local_cpu_utilization = calc_cpu_util(0.0);
9537 /* since calc_service demand is doing ms/Kunit we will */
9538 /* multiply the number of transaction by 1024 to get */
9539 /* "good" numbers */
9540 local_service_demand = calc_service_demand((double) nummessages*1024,
9541 0.0,
9542 0.0,
9543 0);
9544 }
9545 else {
9546 local_cpu_utilization = (float) -1.0;
9547 local_service_demand = (float) -1.0;
9548 }
9549
9550 if (remote_cpu_usage) {
9551 if (remote_cpu_rate == 0.0) {
9552 fprintf(where,
9553 "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
9554 fprintf(where,
9555 "Remote CPU usage numbers based on process information only!\n");
9556 fflush(where);
9557 }
9558 remote_cpu_utilization = tcp_conn_rr_result->cpu_util;
9559 /* since calc_service demand is doing ms/Kunit we will */
9560 /* multiply the number of transaction by 1024 to get */
9561 /* "good" numbers */
9562 remote_service_demand = calc_service_demand((double) nummessages*1024,
9563 0.0,
9564 remote_cpu_utilization,
9565 tcp_conn_rr_result->num_cpus);
9566 }
9567 else {
9568 remote_cpu_utilization = (float) -1.0;
9569 remote_service_demand = (float) -1.0;
9570 }
9571
9572 /* We are now ready to print all the information. If the user */
9573 /* has specified zero-level verbosity, we will just print the */
9574 /* local service demand, or the remote service demand. If the */
9575 /* user has requested verbosity level 1, he will get the basic */
9576 /* "streamperf" numbers. If the user has specified a verbosity */
9577 /* of greater than 1, we will display a veritable plethora of */
9578 /* background information from outside of this block as it it */
9579 /* not cpu_measurement specific... */
9580
9581 switch (verbosity) {
9582 case 0:
9583 if (local_cpu_usage) {
9584 fprintf(where,
9585 cpu_fmt_0,
9586 local_service_demand);
9587 }
9588 else {
9589 fprintf(where,
9590 cpu_fmt_0,
9591 remote_service_demand);
9592 }
9593 break;
9594 case 1:
9595 case 2:
9596
9597 if (print_headers) {
9598 fprintf(where,
9599 cpu_title,
9600 local_cpu_method,
9601 remote_cpu_method);
9602 }
9603
9604 fprintf(where,
9605 cpu_fmt_1_line_1, /* the format string */
9606 lss_size, /* local sendbuf size */
9607 lsr_size,
9608 req_size, /* how large were the requests */
9609 rsp_size, /* guess */
9610 elapsed_time, /* how long was the test */
9611 nummessages/elapsed_time,
9612 local_cpu_utilization, /* local cpu */
9613 remote_cpu_utilization, /* remote cpu */
9614 local_service_demand, /* local service demand */
9615 remote_service_demand); /* remote service demand */
9616 fprintf(where,
9617 cpu_fmt_1_line_2,
9618 rss_size,
9619 rsr_size);
9620 break;
9621 }
9622 }
9623 else {
9624 /* The tester did not wish to measure service demand. */
9625 switch (verbosity) {
9626 case 0:
9627 fprintf(where,
9628 tput_fmt_0,
9629 nummessages/elapsed_time);
9630 break;
9631 case 1:
9632 case 2:
9633 if (print_headers) {
9634 fprintf(where,tput_title,format_units());
9635 }
9636
9637 fprintf(where,
9638 tput_fmt_1_line_1, /* the format string */
9639 lss_size,
9640 lsr_size,
9641 req_size, /* how large were the requests */
9642 rsp_size, /* how large were the responses */
9643 elapsed_time, /* how long did it take */
9644 nummessages/elapsed_time);
9645 fprintf(where,
9646 tput_fmt_1_line_2,
9647 rss_size, /* remote recvbuf size */
9648 rsr_size);
9649
9650 break;
9651 }
9652 }
9653
9654 /* it would be a good thing to include information about some of the */
9655 /* other parameters that may have been set for this test, but at the */
9656 /* moment, I do not wish to figure-out all the formatting, so I will */
9657 /* just put this comment here to help remind me that it is something */
9658 /* that should be done at a later time. */
9659
9660 if (verbosity > 1) {
9661 /* The user wanted to know it all, so we will give it to him. */
9662 /* This information will include as much as we can find about */
9663 /* TCP statistics, the alignments of the sends and receives */
9664 /* and all that sort of rot... */
9665
9666 fprintf(where,
9667 ksink_fmt,
9668 local_send_align,
9669 remote_recv_offset,
9670 local_send_offset,
9671 remote_recv_offset);
9672
9673 #ifdef WANT_HISTOGRAM
9674 fprintf(where,"\nHistogram of request/response times\n");
9675 fflush(where);
9676 HIST_report(time_hist);
9677 #endif /* WANT_HISTOGRAM */
9678
9679 }
9680
9681 }
9682 #endif /* WANT_MIGRATION */
9683
9684 void
recv_tcp_conn_rr()9685 recv_tcp_conn_rr()
9686 {
9687
9688 char *message;
9689 struct addrinfo *local_res;
9690 char local_name[BUFSIZ];
9691 char port_buffer[PORTBUFSIZE];
9692
9693 struct sockaddr_storage myaddr_in, peeraddr_in;
9694 SOCKET s_listen,s_data;
9695 netperf_socklen_t addrlen;
9696 char *recv_message_ptr;
9697 char *send_message_ptr;
9698 char *temp_message_ptr;
9699 int trans_received;
9700 int trans_remaining;
9701 int bytes_sent;
9702 int request_bytes_recvd;
9703 int request_bytes_remaining;
9704 int timed_out = 0;
9705 float elapsed_time;
9706
9707 struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
9708 struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
9709 struct tcp_conn_rr_results_struct *tcp_conn_rr_results;
9710
9711 tcp_conn_rr_request =
9712 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
9713 tcp_conn_rr_response =
9714 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
9715 tcp_conn_rr_results =
9716 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
9717
9718 if (debug) {
9719 fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n");
9720 fflush(where);
9721 }
9722
9723 /* We want to set-up the listen socket with all the desired */
9724 /* parameters and then let the initiator know that all is ready. If */
9725 /* socket size defaults are to be used, then the initiator will have */
9726 /* sent us 0's. If the socket sizes cannot be changed, then we will */
9727 /* send-back what they are. If that information cannot be determined, */
9728 /* then we send-back -1's for the sizes. If things go wrong for any */
9729 /* reason, we will drop back ten yards and punt. */
9730
9731 /* If anything goes wrong, we want the remote to know about it. It */
9732 /* would be best if the error that the remote reports to the user is */
9733 /* the actual error we encountered, rather than some bogus unexpected */
9734 /* response type message. */
9735
9736 if (debug) {
9737 fprintf(where,"recv_tcp_conn_rr: setting the response type...\n");
9738 fflush(where);
9739 }
9740
9741 netperf_response.content.response_type = TCP_CRR_RESPONSE;
9742
9743 if (debug) {
9744 fprintf(where,"recv_tcp_conn_rr: the response type is set...\n");
9745 fflush(where);
9746 }
9747
9748 /* set-up the data buffer with the requested alignment and offset */
9749 message = (char *)malloc(DATABUFFERLEN);
9750 if (message == NULL) {
9751 printf("malloc(%d) failed!\n", DATABUFFERLEN);
9752 exit(1);
9753 }
9754
9755 /* We now alter the message_ptr variables to be at the desired */
9756 /* alignments with the desired offsets. */
9757
9758 if (debug) {
9759 fprintf(where,
9760 "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n",
9761 tcp_conn_rr_request->recv_alignment,
9762 tcp_conn_rr_request->recv_offset);
9763 fprintf(where,
9764 "recv_tcp_conn_rr: requested send alignment of %d offset %d\n",
9765 tcp_conn_rr_request->send_alignment,
9766 tcp_conn_rr_request->send_offset);
9767 fflush(where);
9768 }
9769
9770 recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset);
9771
9772 send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset);
9773
9774 if (debug) {
9775 fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n");
9776 fflush(where);
9777 }
9778
9779 /* Grab a socket to listen on, and then listen on it. */
9780
9781 if (debug) {
9782 fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n");
9783 fflush(where);
9784 }
9785
9786 /* create_data_socket expects to find some things in the global */
9787 /* variables, so set the globals based on the values in the request. */
9788 /* once the socket has been created, we will set the response values */
9789 /* based on the updated value of those globals. raj 7/94 */
9790 lss_size_req = tcp_conn_rr_request->send_buf_size;
9791 lsr_size_req = tcp_conn_rr_request->recv_buf_size;
9792 loc_nodelay = tcp_conn_rr_request->no_delay;
9793 loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid;
9794 loc_sndavoid = tcp_conn_rr_request->so_sndavoid;
9795
9796 set_hostname_and_port(local_name,
9797 port_buffer,
9798 nf_to_af(tcp_conn_rr_request->ipfamily),
9799 tcp_conn_rr_request->port);
9800
9801 local_res = complete_addrinfo(local_name,
9802 local_name,
9803 port_buffer,
9804 nf_to_af(tcp_conn_rr_request->ipfamily),
9805 SOCK_STREAM,
9806 IPPROTO_TCP,
9807 0);
9808
9809 s_listen = create_data_socket(local_res);
9810
9811 if (s_listen == INVALID_SOCKET) {
9812 netperf_response.content.serv_errno = errno;
9813 send_response();
9814 if (debug) {
9815 fprintf(where,"could not create data socket\n");
9816 fflush(where);
9817 }
9818 exit(1);
9819 }
9820
9821 #ifdef WIN32
9822 /* The test timer can fire during operations on the listening socket,
9823 so to make the start_timer below work we have to move
9824 it to close s_listen while we are blocked on accept. */
9825 win_kludge_socket2 = s_listen;
9826 #endif
9827
9828
9829 /* Now, let's set-up the socket to listen for connections */
9830 if (listen(s_listen, 128) == SOCKET_ERROR) {
9831 netperf_response.content.serv_errno = errno;
9832 close(s_listen);
9833 send_response();
9834 if (debug) {
9835 fprintf(where,"could not listen\n");
9836 fflush(where);
9837 }
9838 exit(1);
9839 }
9840
9841 /* now get the port number assigned by the system */
9842 addrlen = sizeof(myaddr_in);
9843 if (getsockname(s_listen,
9844 (struct sockaddr *)&myaddr_in,
9845 &addrlen) == SOCKET_ERROR){
9846 netperf_response.content.serv_errno = errno;
9847 close(s_listen);
9848 send_response();
9849 if (debug) {
9850 fprintf(where,"could not getsockname\n");
9851 fflush(where);
9852 }
9853 exit(1);
9854 }
9855
9856 /* Now myaddr_in contains the port and the internet address this is */
9857 /* returned to the sender also implicitly telling the sender that the */
9858 /* socket buffer sizing has been done. */
9859
9860 tcp_conn_rr_response->data_port_number =
9861 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
9862 if (debug) {
9863 fprintf(where,"telling the remote to call me at %d\n",
9864 tcp_conn_rr_response->data_port_number);
9865 fflush(where);
9866 }
9867 netperf_response.content.serv_errno = 0;
9868
9869 /* But wait, there's more. If the initiator wanted cpu measurements, */
9870 /* then we must call the calibrate routine, which will return the max */
9871 /* rate back to the initiator. If the CPU was not to be measured, or */
9872 /* something went wrong with the calibration, we will return a 0.0 to */
9873 /* the initiator. */
9874
9875 tcp_conn_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
9876 if (tcp_conn_rr_request->measure_cpu) {
9877 tcp_conn_rr_response->measure_cpu = 1;
9878 tcp_conn_rr_response->cpu_rate =
9879 calibrate_local_cpu(tcp_conn_rr_request->cpu_rate);
9880 }
9881
9882
9883
9884 /* before we send the response back to the initiator, pull some of */
9885 /* the socket parms from the globals */
9886 tcp_conn_rr_response->send_buf_size = lss_size;
9887 tcp_conn_rr_response->recv_buf_size = lsr_size;
9888 tcp_conn_rr_response->no_delay = loc_nodelay;
9889 tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
9890 tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
9891
9892 send_response();
9893
9894 addrlen = sizeof(peeraddr_in);
9895
9896 /* Now it's time to start receiving data on the connection. We will */
9897 /* first grab the apropriate counters and then start grabbing. */
9898
9899 cpu_start(tcp_conn_rr_request->measure_cpu);
9900
9901 /* The loop will exit when the sender does a shutdown, which will */
9902 /* return a length of zero */
9903
9904 if (tcp_conn_rr_request->test_length > 0) {
9905 times_up = 0;
9906 trans_remaining = 0;
9907 start_timer(tcp_conn_rr_request->test_length + PAD_TIME);
9908 }
9909 else {
9910 times_up = 1;
9911 trans_remaining = tcp_conn_rr_request->test_length * -1;
9912 }
9913
9914 trans_received = 0;
9915
9916 while ((!times_up) || (trans_remaining > 0)) {
9917
9918 /* accept a connection from the remote */
9919 #ifdef WIN32
9920 /* The test timer will probably fire during this accept,
9921 so to make the start_timer above work we have to move
9922 it to close s_listen while we are blocked on accept. */
9923 win_kludge_socket = s_listen;
9924 #endif
9925 if ((s_data=accept(s_listen,
9926 (struct sockaddr *)&peeraddr_in,
9927 &addrlen)) == INVALID_SOCKET) {
9928 if (errno == EINTR) {
9929 /* the timer popped */
9930 timed_out = 1;
9931 break;
9932 }
9933 fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno);
9934 fflush(where);
9935 close(s_listen);
9936
9937 exit(1);
9938 }
9939
9940 if (debug) {
9941 fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n");
9942 fflush(where);
9943 }
9944
9945 #ifdef WIN32
9946 /* this is used so the timer thread can close the socket out from */
9947 /* under us, which to date is the easiest/cleanest/least */
9948 /* Windows-specific way I can find to force the winsock calls to */
9949 /* return WSAEINTR with the test is over. anything that will run on */
9950 /* 95 and NT and is closer to what netperf expects from Unix signals */
9951 /* and such would be appreciated raj 1/96 */
9952 win_kludge_socket = s_data;
9953 #endif /* WIN32 */
9954
9955 #ifdef KLUDGE_SOCKET_OPTIONS
9956 /* this is for those systems which *INCORRECTLY* fail to pass */
9957 /* attributes across an accept() call. Including this goes against */
9958 /* my better judgement :( raj 11/95 */
9959
9960 kludge_socket_options(s_data);
9961
9962 #endif /* KLUDGE_SOCKET_OPTIONS */
9963
9964 temp_message_ptr = recv_message_ptr;
9965 request_bytes_remaining = tcp_conn_rr_request->request_size;
9966
9967 /* receive the request from the other side */
9968 while (!times_up && (request_bytes_remaining > 0)) {
9969 if((request_bytes_recvd=recv(s_data,
9970 temp_message_ptr,
9971 request_bytes_remaining,
9972 0)) == SOCKET_ERROR) {
9973 if (SOCKET_EINTR(request_bytes_recvd))
9974 {
9975 /* the timer popped */
9976 timed_out = 1;
9977 break;
9978 }
9979 netperf_response.content.serv_errno = errno;
9980 send_response();
9981 exit(1);
9982 }
9983 else if (request_bytes_recvd > 0) {
9984 request_bytes_remaining -= request_bytes_recvd;
9985 temp_message_ptr += request_bytes_recvd;
9986 }
9987 else {
9988 /* for some reason the remote closed the connection on
9989 * us and that is unexpected so we should just close the
9990 * socket and move-on. for that we will use an evil goto
9991 * neener neener raj 20090622 */
9992 goto bail;
9993 }
9994 }
9995
9996 if (timed_out) {
9997 /* we hit the end of the test based on time - lets */
9998 /* bail out of here now... */
9999 fprintf(where,"yo5\n");
10000 fflush(where);
10001 break;
10002 }
10003
10004 /* Now, send the response to the remote */
10005 if((bytes_sent=send(s_data,
10006 send_message_ptr,
10007 tcp_conn_rr_request->response_size,
10008 0)) == SOCKET_ERROR) {
10009 if (errno == EINTR) {
10010 /* the test timer has popped */
10011 timed_out = 1;
10012 fprintf(where,"yo6\n");
10013 fflush(where);
10014 break;
10015 }
10016 netperf_response.content.serv_errno = 99;
10017 send_response();
10018 exit(1);
10019 }
10020
10021 trans_received++;
10022 if (trans_remaining) {
10023 trans_remaining--;
10024 }
10025
10026 if (debug) {
10027 fprintf(where,
10028 "recv_tcp_conn_rr: Transaction %d complete\n",
10029 trans_received);
10030 fflush(where);
10031 }
10032
10033 /* close the connection. the server will likely do a graceful */
10034 /* close of the connection, insuring that all data has arrived at */
10035 /* the client. for this it will call shutdown(), and then recv() and */
10036 /* then close(). I'm reasonably confident that this is the */
10037 /* appropriate sequence of calls - I would like to hear of */
10038 /* examples in web servers to the contrary. raj 10/95*/
10039 #ifdef TCP_CRR_SHUTDOWN
10040 shutdown(s_data,SHUT_WR);
10041 recv(s_data,
10042 recv_message_ptr,
10043 1,
10044 0);
10045 bail:
10046 close(s_data);
10047 #else
10048 bail:
10049 close(s_data);
10050 #endif /* TCP_CRR_SHUTDOWN */
10051
10052 }
10053
10054
10055 /* The loop now exits due to timeout or transaction count being */
10056 /* reached */
10057
10058 cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time);
10059
10060 if (timed_out) {
10061 /* we ended the test by time, which was at least 2 seconds */
10062 /* longer than we wanted to run. so, we want to subtract */
10063 /* PAD_TIME from the elapsed_time. */
10064 elapsed_time -= PAD_TIME;
10065 }
10066 /* send the results to the sender */
10067
10068 if (debug) {
10069 fprintf(where,
10070 "recv_tcp_conn_rr: got %d transactions\n",
10071 trans_received);
10072 fflush(where);
10073 }
10074
10075 tcp_conn_rr_results->bytes_received = (trans_received *
10076 (tcp_conn_rr_request->request_size +
10077 tcp_conn_rr_request->response_size));
10078 tcp_conn_rr_results->trans_received = trans_received;
10079 tcp_conn_rr_results->elapsed_time = elapsed_time;
10080 if (tcp_conn_rr_request->measure_cpu) {
10081 tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time);
10082 }
10083
10084 if (debug) {
10085 fprintf(where,
10086 "recv_tcp_conn_rr: test complete, sending results.\n");
10087 fflush(where);
10088 }
10089
10090 send_response();
10091
10092 }
10093
10094
10095 #ifdef DO_1644
10096
10097 /* this test is intended to test the performance of establishing a */
10098 /* connection, exchanging a request/response pair, and repeating. it */
10099 /* is expected that this would be a good starting-point for */
10100 /* comparision of T/TCP with classic TCP for transactional workloads. */
10101 /* it will also look (can look) much like the communication pattern */
10102 /* of http for www access. */
10103
10104 int
send_tcp_tran_rr(char remote_host[])10105 send_tcp_tran_rr(char remote_host[])
10106 {
10107
10108 char *tput_title = "\
10109 Local /Remote\n\
10110 Socket Size Request Resp. Elapsed Trans.\n\
10111 Send Recv Size Size Time Rate \n\
10112 bytes Bytes bytes bytes secs. per sec \n\n";
10113
10114 char *tput_fmt_0 =
10115 "%7.2f\n";
10116
10117 char *tput_fmt_1_line_1 = "\
10118 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
10119 char *tput_fmt_1_line_2 = "\
10120 %-6d %-6d\n";
10121
10122 char *cpu_title = "\
10123 Local /Remote\n\
10124 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
10125 Send Recv Size Size Time Rate local remote local remote\n\
10126 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
10127
10128 char *cpu_fmt_0 =
10129 "%6.3f\n";
10130
10131 char *cpu_fmt_1_line_1 = "\
10132 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
10133
10134 char *cpu_fmt_1_line_2 = "\
10135 %-6d %-6d\n";
10136
10137 char *ksink_fmt = "\n\
10138 Alignment Offset\n\
10139 Local Remote Local Remote\n\
10140 Send Recv Send Recv\n\
10141 %5d %5d %5d %5d\n";
10142
10143
10144 int one = 1;
10145 int timed_out = 0;
10146 float elapsed_time;
10147
10148 int len;
10149 struct ring_elt *send_ring;
10150 struct ring_elt *recv_ring;
10151 char *temp_message_ptr;
10152 int nummessages;
10153 SOCKET send_socket;
10154 int trans_remaining;
10155 double bytes_xferd;
10156 int sock_opt_len = sizeof(int);
10157 int rsp_bytes_left;
10158 int rsp_bytes_recvd;
10159
10160 float local_cpu_utilization;
10161 float local_service_demand;
10162 float remote_cpu_utilization;
10163 float remote_service_demand;
10164 double thruput;
10165
10166 struct hostent *hp;
10167 struct sockaddr_in server;
10168 struct sockaddr_in *myaddr;
10169 unsigned int addr;
10170 int myport;
10171
10172 struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
10173 struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
10174 struct tcp_tran_rr_results_struct *tcp_tran_rr_result;
10175
10176 tcp_tran_rr_request =
10177 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
10178 tcp_tran_rr_response =
10179 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
10180 tcp_tran_rr_result =
10181 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
10182
10183
10184 #ifdef WANT_HISTOGRAM
10185 if (verbosity > 1) {
10186 time_hist = HIST_new();
10187 }
10188 #endif /* WANT_HISTOGRAM */
10189
10190 /* since we are now disconnected from the code that established the */
10191 /* control socket, and since we want to be able to use different */
10192 /* protocols and such, we are passed the name of the remote host and */
10193 /* must turn that into the test specific addressing information. */
10194
10195 myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
10196 if (myaddr == NULL) {
10197 printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage));
10198 exit(1);
10199 }
10200
10201 bzero((char *)&server,
10202 sizeof(server));
10203 bzero((char *)myaddr,
10204 sizeof(struct sockaddr_storage));
10205 myaddr->sin_family = AF_INET;
10206
10207 complete_addrinfos(&remote_res,
10208 &local_res,
10209 remote_host,
10210 SOCK_STREAM,
10211 IPPROTO_TCP,
10212 0);
10213
10214 if ( print_headers ) {
10215 print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res);
10216 }
10217
10218 /* initialize a few counters */
10219
10220 nummessages = 0;
10221 bytes_xferd = 0.0;
10222 times_up = 0;
10223
10224 /* set-up the data buffers with the requested alignment and offset */
10225 if (send_width == 0) send_width = 1;
10226 if (recv_width == 0) recv_width = 1;
10227
10228 send_ring = allocate_buffer_ring(send_width,
10229 req_size,
10230 local_send_align,
10231 local_send_offset);
10232
10233 recv_ring = allocate_buffer_ring(recv_width,
10234 rsp_size,
10235 local_recv_align,
10236 local_recv_offset);
10237
10238
10239 if (debug) {
10240 fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n");
10241 }
10242
10243 /* If the user has requested cpu utilization measurements, we must */
10244 /* calibrate the cpu(s). We will perform this task within the tests */
10245 /* themselves. If the user has specified the cpu rate, then */
10246 /* calibrate_local_cpu will return rather quickly as it will have */
10247 /* nothing to do. If local_cpu_rate is zero, then we will go through */
10248 /* all the "normal" calibration stuff and return the rate back.*/
10249
10250 if (local_cpu_usage) {
10251 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
10252 }
10253
10254 /* Tell the remote end to do a listen. The server alters the socket */
10255 /* paramters on the other side at this point, hence the reason for */
10256 /* all the values being passed in the setup message. If the user did */
10257 /* not specify any of the parameters, they will be passed as 0, which */
10258 /* will indicate to the remote that no changes beyond the system's */
10259 /* default should be used. Alignment is the exception, it will */
10260 /* default to 8, which will be no alignment alterations. */
10261
10262 netperf_request.content.request_type = DO_TCP_TRR;
10263 tcp_tran_rr_request->recv_buf_size = rsr_size_req;
10264 tcp_tran_rr_request->send_buf_size = rss_size_req;
10265 tcp_tran_rr_request->recv_alignment = remote_recv_align;
10266 tcp_tran_rr_request->recv_offset = remote_recv_offset;
10267 tcp_tran_rr_request->send_alignment = remote_send_align;
10268 tcp_tran_rr_request->send_offset = remote_send_offset;
10269 tcp_tran_rr_request->request_size = req_size;
10270 tcp_tran_rr_request->response_size = rsp_size;
10271 tcp_tran_rr_request->no_delay = rem_nodelay;
10272 tcp_tran_rr_request->measure_cpu = remote_cpu_usage;
10273 tcp_tran_rr_request->cpu_rate = remote_cpu_rate;
10274 tcp_tran_rr_request->so_rcvavoid = rem_rcvavoid;
10275 tcp_tran_rr_request->so_sndavoid = rem_sndavoid;
10276 if (test_time) {
10277 tcp_tran_rr_request->test_length = test_time;
10278 }
10279 else {
10280 tcp_tran_rr_request->test_length = test_trans * -1;
10281 }
10282 tcp_tran_rr_request->port = atoi(remote_data_port);
10283 tcp_tran_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
10284
10285 if (debug > 1) {
10286 fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n");
10287 }
10288
10289 send_request();
10290
10291 /* The response from the remote will contain all of the relevant */
10292 /* socket parameters for this test type. We will put them back into */
10293 /* the variables here so they can be displayed if desired. The */
10294 /* remote will have calibrated CPU if necessary, and will have done */
10295 /* all the needed set-up we will have calibrated the cpu locally */
10296 /* before sending the request, and will grab the counter value right */
10297 /* after the connect returns. The remote will grab the counter right */
10298 /* after the accept call. This saves the hassle of extra messages */
10299 /* being sent for the TCP tests. */
10300
10301 recv_response();
10302
10303 if (!netperf_response.content.serv_errno) {
10304 rsr_size = tcp_tran_rr_response->recv_buf_size;
10305 rss_size = tcp_tran_rr_response->send_buf_size;
10306 rem_nodelay = tcp_tran_rr_response->no_delay;
10307 remote_cpu_usage= tcp_tran_rr_response->measure_cpu;
10308 remote_cpu_rate = tcp_tran_rr_response->cpu_rate;
10309 /* make sure that port numbers are in network order */
10310 server.sin_port = tcp_tran_rr_response->data_port_number;
10311 server.sin_port = htons(server.sin_port);
10312 if (debug) {
10313 fprintf(where,"remote listen done.\n");
10314 fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
10315 fflush(where);
10316 }
10317 }
10318 else {
10319 Set_errno(netperf_response.content.serv_errno);
10320 fprintf(where,
10321 "netperf: remote error %d",
10322 netperf_response.content.serv_errno);
10323 perror("");
10324 fflush(where);
10325 exit(1);
10326 }
10327
10328 /* pick a nice random spot between client_port_min and */
10329 /* client_port_max for our initial port number. if they are the */
10330 /* same, then just set to _min */
10331 if (client_port_max - client_port_min) {
10332 srand(getpid());
10333 myport = client_port_min +
10334 (rand() % (client_port_max - client_port_min));
10335 }
10336 else {
10337 myport = client_port_min;
10338 }
10339
10340 /* there will be a ++ before the first call to bind, so subtract one */
10341 myport--;
10342 myaddr->sin_port = htons((unsigned short)myport);
10343
10344 /* Set-up the test end conditions. For a request/response test, they */
10345 /* can be either time or transaction based. */
10346
10347 if (test_time) {
10348 /* The user wanted to end the test after a period of time. */
10349 times_up = 0;
10350 trans_remaining = 0;
10351 start_timer(test_time);
10352 }
10353 else {
10354 /* The tester wanted to send a number of bytes. */
10355 trans_remaining = test_bytes;
10356 times_up = 1;
10357 }
10358
10359 /* The cpu_start routine will grab the current time and possibly */
10360 /* value of the idle counter for later use in measuring cpu */
10361 /* utilization and/or service demand and thruput. */
10362
10363 cpu_start(local_cpu_usage);
10364
10365 /* We use an "OR" to control test execution. When the test is */
10366 /* controlled by time, the byte count check will always return false. */
10367 /* When the test is controlled by byte count, the time test will */
10368 /* always return false. When the test is finished, the whole */
10369 /* expression will go false and we will stop sending data. I think I */
10370 /* just arbitrarily decrement trans_remaining for the timed test, but */
10371 /* will not do that just yet... One other question is whether or not */
10372 /* the send buffer and the receive buffer should be the same buffer. */
10373
10374 while ((!times_up) || (trans_remaining > 0)) {
10375
10376 #ifdef WANT_HISTOGRAM
10377 if (verbosity > 1) {
10378 /* timestamp just before our call to create the socket, and then */
10379 /* again just after the receive raj 3/95 */
10380 HIST_timestamp(&time_one);
10381 }
10382 #endif /* WANT_HISTOGRAM */
10383
10384 /* set up the data socket - is this really necessary or can I just */
10385 /* re-use the same socket and move this cal out of the while loop. */
10386 /* it does introcudea *boatload* of system calls. I guess that it */
10387 /* all depends on "reality of programming." keeping it this way is */
10388 /* a bit more conservative I imagine - raj 3/95 */
10389 send_socket = create_data_socket(local_res);
10390
10391 if (send_socket == INVALID_SOCKET) {
10392 perror("netperf: send_tcp_tran_rr: tcp stream data socket");
10393 exit(1);
10394 }
10395
10396 /* we set SO_REUSEADDR on the premis that no unreserved port */
10397 /* number on the local system is going to be already connected to */
10398 /* the remote netserver's port number. One thing that I might */
10399 /* try later is to have the remote actually allocate a couple of */
10400 /* port numbers and cycle through those as well. depends on if we */
10401 /* can get through all the unreserved port numbers in less than */
10402 /* the length of the TIME_WAIT state raj 8/94 */
10403 one = 1;
10404 if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
10405 (char *)&one, sock_opt_len) == SOCKET_ERROR) {
10406 perror("netperf: send_tcp_tran_rr: so_reuseaddr");
10407 exit(1);
10408 }
10409
10410 newport:
10411 /* pick a new port number */
10412 myport = ntohs(myaddr->sin_port);
10413 myport++;
10414
10415 /* we do not want to use the port number that the server is */
10416 /* sitting at - this would cause us to fail in a loopback test. we */
10417 /* could just rely on the failure of the bind to get us past this, */
10418 /* but I'm guessing that in this one case at least, it is much */
10419 /* faster, given that we *know* that port number is already in use */
10420 /* (or rather would be in a loopback test) */
10421
10422 if (myport == ntohs(server.sin_port)) myport++;
10423
10424 /* wrap the port number when we get to 65535. NOTE, some broken */
10425 /* TCP's might treat the port number as a signed 16 bit quantity. */
10426 /* we aren't interested in testing such broken implementations :) */
10427 /* raj 8/94 */
10428 if (myport >= client_port_max) {
10429 myport = client_port_min;
10430 }
10431 myaddr->sin_port = htons((unsigned short)myport);
10432
10433 if (debug) {
10434 if ((nummessages % 100) == 0) {
10435 printf("port %d\n",myport);
10436 }
10437 }
10438
10439 /* we want to bind our socket to a particular port number. */
10440 if (bind(send_socket,
10441 (struct sockaddr *)myaddr,
10442 sizeof(struct sockaddr_storage)) == SOCKET_ERROR) {
10443 /* if the bind failed, someone else must have that port number */
10444 /* - perhaps in the listen state. since we can't use it, skip to */
10445 /* the next port number. we may have to do this again later, but */
10446 /* that's just too bad :) */
10447 if (debug > 1) {
10448 fprintf(where,
10449 "send_tcp_tran_rr: tried to bind to port %d errno %d\n",
10450 ntohs(myaddr->sin_port),
10451 errno);
10452 fflush(where);
10453 }
10454 /* yes, goto's are supposed to be evil, but they do have their */
10455 /* uses from time to time. the real world doesn't always have */
10456 /* to code to ge tthe A in CS 101 :) raj 3/95 */
10457 goto newport;
10458 }
10459
10460 /* Connect up to the remote port on the data socket. Since this is */
10461 /* a test for RFC_1644-style transactional TCP, we can use the */
10462 /* sendto() call instead of calling connect and then send() */
10463
10464 /* send the request */
10465 if((len=sendto(send_socket,
10466 send_ring->buffer_ptr,
10467 req_size,
10468 MSG_EOF,
10469 (struct sockaddr *)&server,
10470 sizeof(server))) != req_size) {
10471 if (SOCKET_EINTR(len))
10472 {
10473 /* we hit the end of a */
10474 /* timed test. */
10475 timed_out = 1;
10476 break;
10477 }
10478 perror("send_tcp_tran_rr: data send error");
10479 exit(1);
10480 }
10481 send_ring = send_ring->next;
10482
10483 /* receive the response */
10484 rsp_bytes_left = rsp_size;
10485 temp_message_ptr = recv_ring->buffer_ptr;
10486 while(rsp_bytes_left > 0) {
10487 if((rsp_bytes_recvd=recv(send_socket,
10488 temp_message_ptr,
10489 rsp_bytes_left,
10490 0)) == SOCKET_ERROR) {
10491 if (SOCKET_EINTR(rsp_bytes_recvd))
10492 {
10493 /* We hit the end of a timed test. */
10494 timed_out = 1;
10495 break;
10496 }
10497 perror("send_tcp_tran_rr: data recv error");
10498 exit(1);
10499 }
10500 rsp_bytes_left -= rsp_bytes_recvd;
10501 temp_message_ptr += rsp_bytes_recvd;
10502 }
10503 recv_ring = recv_ring->next;
10504
10505 if (timed_out) {
10506 /* we may have been in a nested while loop - we need */
10507 /* another call to break. */
10508 break;
10509 }
10510
10511 close(send_socket);
10512
10513 #ifdef WANT_HISTOGRAM
10514 if (verbosity > 1) {
10515 HIST_timestamp(&time_two);
10516 HIST_add(time_hist,delta_micro(&time_one,&time_two));
10517 }
10518 #endif /* WANT_HISTOGRAM */
10519
10520 nummessages++;
10521 if (trans_remaining) {
10522 trans_remaining--;
10523 }
10524
10525 if (debug > 3) {
10526 fprintf(where,
10527 "Transaction %d completed on local port %d\n",
10528 nummessages,
10529 ntohs(myaddr->sin_port));
10530 fflush(where);
10531 }
10532
10533
10534 }
10535
10536 /* this call will always give us the elapsed time for the test, and */
10537 /* will also store-away the necessaries for cpu utilization */
10538
10539 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
10540 /* how long did we really run? */
10541
10542 /* Get the statistics from the remote end. The remote will have */
10543 /* calculated service demand and all those interesting things. If it */
10544 /* wasn't supposed to care, it will return obvious values. */
10545
10546 recv_response();
10547 if (!netperf_response.content.serv_errno) {
10548 if (debug)
10549 fprintf(where,"remote results obtained\n");
10550 }
10551 else {
10552 Set_errno(netperf_response.content.serv_errno);
10553 fprintf(where,
10554 "netperf: remote error %d",
10555 netperf_response.content.serv_errno);
10556 perror("");
10557 fflush(where);
10558 exit(1);
10559 }
10560
10561 /* We now calculate what our thruput was for the test. In the future, */
10562 /* we may want to include a calculation of the thruput measured by */
10563 /* the remote, but it should be the case that for a TCP stream test, */
10564 /* that the two numbers should be *very* close... We calculate */
10565 /* bytes_sent regardless of the way the test length was controlled. */
10566 /* If it was time, we needed to, and if it was by bytes, the user may */
10567 /* have specified a number of bytes that wasn't a multiple of the */
10568 /* send_size, so we really didn't send what he asked for ;-) We use */
10569 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
10570 /* 1024. A future enhancement *might* be to choose from a couple of */
10571 /* unit selections. */
10572
10573 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
10574 thruput = calc_thruput(bytes_xferd);
10575
10576 if (local_cpu_usage || remote_cpu_usage) {
10577 /* We must now do a little math for service demand and cpu */
10578 /* utilization for the system(s) */
10579 /* Of course, some of the information might be bogus because */
10580 /* there was no idle counter in the kernel(s). We need to make */
10581 /* a note of this for the user's benefit...*/
10582 if (local_cpu_usage) {
10583 if (local_cpu_rate == 0.0) {
10584 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
10585 fprintf(where,"Local CPU usage numbers based on process information only!\n");
10586 fflush(where);
10587 }
10588 local_cpu_utilization = calc_cpu_util(0.0);
10589 /* since calc_service demand is doing ms/Kunit we will */
10590 /* multiply the number of transaction by 1024 to get */
10591 /* "good" numbers */
10592 local_service_demand = calc_service_demand((double) nummessages*1024,
10593 0.0,
10594 0.0,
10595 0);
10596 }
10597 else {
10598 local_cpu_utilization = (float) -1.0;
10599 local_service_demand = (float) -1.0;
10600 }
10601
10602 if (remote_cpu_usage) {
10603 if (remote_cpu_rate == 0.0) {
10604 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
10605 fprintf(where,"Remote CPU usage numbers based on process information only!\n");
10606 fflush(where);
10607 }
10608 remote_cpu_utilization = tcp_tran_rr_result->cpu_util;
10609 /* since calc_service demand is doing ms/Kunit we will */
10610 /* multiply the number of transaction by 1024 to get */
10611 /* "good" numbers */
10612 remote_service_demand = calc_service_demand((double) nummessages*1024,
10613 0.0,
10614 remote_cpu_utilization,
10615 tcp_tran_rr_result->num_cpus);
10616 }
10617 else {
10618 remote_cpu_utilization = (float) -1.0;
10619 remote_service_demand = (float) -1.0;
10620 }
10621
10622 /* We are now ready to print all the information. If the user */
10623 /* has specified zero-level verbosity, we will just print the */
10624 /* local service demand, or the remote service demand. If the */
10625 /* user has requested verbosity level 1, he will get the basic */
10626 /* "streamperf" numbers. If the user has specified a verbosity */
10627 /* of greater than 1, we will display a veritable plethora of */
10628 /* background information from outside of this block as it it */
10629 /* not cpu_measurement specific... */
10630
10631 switch (verbosity) {
10632 case 0:
10633 if (local_cpu_usage) {
10634 fprintf(where,
10635 cpu_fmt_0,
10636 local_service_demand);
10637 }
10638 else {
10639 fprintf(where,
10640 cpu_fmt_0,
10641 remote_service_demand);
10642 }
10643 break;
10644 case 1:
10645 case 2:
10646
10647 if (print_headers) {
10648 fprintf(where,
10649 cpu_title,
10650 local_cpu_method,
10651 remote_cpu_method);
10652 }
10653
10654 fprintf(where,
10655 cpu_fmt_1_line_1, /* the format string */
10656 lss_size, /* local sendbuf size */
10657 lsr_size,
10658 req_size, /* how large were the requests */
10659 rsp_size, /* guess */
10660 elapsed_time, /* how long was the test */
10661 nummessages/elapsed_time,
10662 local_cpu_utilization, /* local cpu */
10663 remote_cpu_utilization, /* remote cpu */
10664 local_service_demand, /* local service demand */
10665 remote_service_demand); /* remote service demand */
10666 fprintf(where,
10667 cpu_fmt_1_line_2,
10668 rss_size,
10669 rsr_size);
10670 break;
10671 }
10672 }
10673 else {
10674 /* The tester did not wish to measure service demand. */
10675 switch (verbosity) {
10676 case 0:
10677 fprintf(where,
10678 tput_fmt_0,
10679 nummessages/elapsed_time);
10680 break;
10681 case 1:
10682 case 2:
10683 if (print_headers) {
10684 fprintf(where,tput_title,format_units());
10685 }
10686
10687 fprintf(where,
10688 tput_fmt_1_line_1, /* the format string */
10689 lss_size,
10690 lsr_size,
10691 req_size, /* how large were the requests */
10692 rsp_size, /* how large were the responses */
10693 elapsed_time, /* how long did it take */
10694 nummessages/elapsed_time);
10695 fprintf(where,
10696 tput_fmt_1_line_2,
10697 rss_size, /* remote recvbuf size */
10698 rsr_size);
10699
10700 break;
10701 }
10702 }
10703
10704 /* it would be a good thing to include information about some of the */
10705 /* other parameters that may have been set for this test, but at the */
10706 /* moment, I do not wish to figure-out all the formatting, so I will */
10707 /* just put this comment here to help remind me that it is something */
10708 /* that should be done at a later time. */
10709
10710 if (verbosity > 1) {
10711 /* The user wanted to know it all, so we will give it to him. */
10712 /* This information will include as much as we can find about */
10713 /* TCP statistics, the alignments of the sends and receives */
10714 /* and all that sort of rot... */
10715
10716 fprintf(where,
10717 ksink_fmt,
10718 local_send_align,
10719 remote_recv_offset,
10720 local_send_offset,
10721 remote_recv_offset);
10722
10723 #ifdef WANT_HISTOGRAM
10724 fprintf(where,"\nHistogram of request/response times\n");
10725 fflush(where);
10726 HIST_report(time_hist);
10727 #endif /* WANT_HISTOGRAM */
10728
10729 }
10730
10731 }
10732
10733
10734 int
recv_tcp_tran_rr()10735 recv_tcp_tran_rr()
10736 {
10737
10738 char *message;
10739 struct sockaddr_in myaddr_in,
10740 peeraddr_in;
10741 SOCKET s_listen,s_data;
10742 netperf_socklen_t addrlen;
10743 int NoPush = 1;
10744
10745 char *recv_message_ptr;
10746 char *send_message_ptr;
10747 char *temp_message_ptr;
10748 int trans_received;
10749 int trans_remaining;
10750 int bytes_sent;
10751 int request_bytes_recvd;
10752 int request_bytes_remaining;
10753 int timed_out = 0;
10754 float elapsed_time;
10755
10756 struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
10757 struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
10758 struct tcp_tran_rr_results_struct *tcp_tran_rr_results;
10759
10760 tcp_tran_rr_request =
10761 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
10762 tcp_tran_rr_response =
10763 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
10764 tcp_tran_rr_results =
10765 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
10766
10767 if (debug) {
10768 fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n");
10769 fflush(where);
10770 }
10771
10772 /* We want to set-up the listen socket with all the desired */
10773 /* parameters and then let the initiator know that all is ready. If */
10774 /* socket size defaults are to be used, then the initiator will have */
10775 /* sent us 0's. If the socket sizes cannot be changed, then we will */
10776 /* send-back what they are. If that information cannot be determined, */
10777 /* then we send-back -1's for the sizes. If things go wrong for any */
10778 /* reason, we will drop back ten yards and punt. */
10779
10780 /* If anything goes wrong, we want the remote to know about it. It */
10781 /* would be best if the error that the remote reports to the user is */
10782 /* the actual error we encountered, rather than some bogus unexpected */
10783 /* response type message. */
10784
10785 if (debug) {
10786 fprintf(where,"recv_tcp_tran_rr: setting the response type...\n");
10787 fflush(where);
10788 }
10789
10790 netperf_response.content.response_type = TCP_TRR_RESPONSE;
10791
10792 if (debug) {
10793 fprintf(where,"recv_tcp_tran_rr: the response type is set...\n");
10794 fflush(where);
10795 }
10796
10797 /* set-up the data buffer with the requested alignment and offset */
10798 message = (char *)malloc(DATABUFFERLEN);
10799 if (message == NULL) {
10800 printf("malloc(%d) failed!\n", DATABUFFERLEN);
10801 exit(1);
10802 }
10803
10804 /* We now alter the message_ptr variables to be at the desired */
10805 /* alignments with the desired offsets. */
10806
10807 if (debug) {
10808 fprintf(where,
10809 "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n",
10810 tcp_tran_rr_request->recv_alignment,
10811 tcp_tran_rr_request->recv_offset);
10812 fprintf(where,
10813 "recv_tcp_tran_rr: requested send alignment of %d offset %d\n",
10814 tcp_tran_rr_request->send_alignment,
10815 tcp_tran_rr_request->send_offset);
10816 fflush(where);
10817 }
10818
10819 recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset);
10820
10821 send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset);
10822
10823 if (debug) {
10824 fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n");
10825 fflush(where);
10826 }
10827
10828 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
10829 /* can put in OUR values !-) At some point, we may want to nail this */
10830 /* socket to a particular network-level address, but for now, */
10831 /* INADDR_ANY should be just fine. */
10832
10833 bzero((char *)&myaddr_in,
10834 sizeof(myaddr_in));
10835 myaddr_in.sin_family = AF_INET;
10836 myaddr_in.sin_addr.s_addr = INADDR_ANY;
10837 myaddr_in.sin_port = htons((unsigned short)tcp_tran_rr_request->port);
10838
10839 /* Grab a socket to listen on, and then listen on it. */
10840
10841 if (debug) {
10842 fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n");
10843 fflush(where);
10844 }
10845
10846 /* create_data_socket expects to find some things in the global */
10847 /* variables, so set the globals based on the values in the request. */
10848 /* once the socket has been created, we will set the response values */
10849 /* based on the updated value of those globals. raj 7/94 */
10850 lss_size_req = tcp_tran_rr_request->send_buf_size;
10851 lsr_size_req = tcp_tran_rr_request->recv_buf_size;
10852 loc_nodelay = tcp_tran_rr_request->no_delay;
10853 loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid;
10854 loc_sndavoid = tcp_tran_rr_request->so_sndavoid;
10855
10856 set_hostname_and_port(local_name,
10857 port_buffer,
10858 nf_to_af(tcp_tran_rr_request->ipfamily),
10859 tcp_tran_rr_request->port);
10860
10861 local_res = complete_addrinfo(local_name,
10862 local_name,
10863 port_buffer,
10864 nf_to_af(tcp_tran_rr_request->ipfamily),
10865 SOCK_STREAM,
10866 IPPROTO_TCP,
10867 0);
10868
10869 s_listen = create_data_socket(local_res);
10870
10871 if (s_listen == INVALID_SOCKET) {
10872 netperf_response.content.serv_errno = errno;
10873 send_response();
10874 if (debug) {
10875 fprintf(where,"could not create data socket\n");
10876 fflush(where);
10877 }
10878 exit(1);
10879 }
10880
10881 #ifdef WIN32
10882 /* The test timer can fire during operations on the listening socket,
10883 so to make the start_timer below work we have to move
10884 it to close s_listen while we are blocked on accept. */
10885 win_kludge_socket2 = s_listen;
10886 #endif
10887
10888
10889 /* Let's get an address assigned to this socket so we can tell the */
10890 /* initiator how to reach the data socket. There may be a desire to */
10891 /* nail this socket to a specific IP address in a multi-homed, */
10892 /* multi-connection situation, but for now, we'll ignore the issue */
10893 /* and concentrate on single connection testing. */
10894
10895 if (bind(s_listen,
10896 (struct sockaddr *)&myaddr_in,
10897 sizeof(myaddr_in)) == SOCKET_ERROR) {
10898 netperf_response.content.serv_errno = errno;
10899 close(s_listen);
10900 send_response();
10901 if (debug) {
10902 fprintf(where,"could not bind\n");
10903 fflush(where);
10904 }
10905 exit(1);
10906 }
10907
10908 /* we want to disable the implicit PUSH on all sends. at some point, */
10909 /* this might want to be a parm to the test raj 3/95 */
10910 if (setsockopt(s_listen,
10911 IPPROTO_TCP,
10912 TCP_NOPUSH,
10913 (const char *)&NoPush,
10914 sizeof(int)) == SOCKET_ERROR) {
10915 fprintf(where,
10916 "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n",
10917 errno);
10918 fflush(where);
10919 netperf_response.content.serv_errno = errno;
10920 close(s_listen);
10921 send_response();
10922 }
10923
10924 /* Now, let's set-up the socket to listen for connections */
10925 if (listen(s_listen, 5) == SOCKET_ERROR) {
10926 netperf_response.content.serv_errno = errno;
10927 close(s_listen);
10928 send_response();
10929 if (debug) {
10930 fprintf(where,"could not listen\n");
10931 fflush(where);
10932 }
10933 exit(1);
10934 }
10935
10936 /* now get the port number assigned by the system */
10937 addrlen = sizeof(myaddr_in);
10938 if (getsockname(s_listen,
10939 (struct sockaddr *)&myaddr_in,
10940 &addrlen) == SOCKET_ERROR){
10941 netperf_response.content.serv_errno = errno;
10942 close(s_listen);
10943 send_response();
10944 if (debug) {
10945 fprintf(where,"could not geetsockname\n");
10946 fflush(where);
10947 }
10948 exit(1);
10949 }
10950
10951 /* Now myaddr_in contains the port and the internet address this is */
10952 /* returned to the sender also implicitly telling the sender that the */
10953 /* socket buffer sizing has been done. */
10954
10955 tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
10956 if (debug) {
10957 fprintf(where,"telling the remote to call me at %d\n",
10958 tcp_tran_rr_response->data_port_number);
10959 fflush(where);
10960 }
10961 netperf_response.content.serv_errno = 0;
10962
10963 /* But wait, there's more. If the initiator wanted cpu measurements, */
10964 /* then we must call the calibrate routine, which will return the max */
10965 /* rate back to the initiator. If the CPU was not to be measured, or */
10966 /* something went wrong with the calibration, we will return a 0.0 to */
10967 /* the initiator. */
10968
10969 tcp_tran_rr_response->cpu_rate = 0.0; /* assume no cpu */
10970 if (tcp_tran_rr_request->measure_cpu) {
10971 tcp_tran_rr_response->measure_cpu = 1;
10972 tcp_tran_rr_response->cpu_rate =
10973 calibrate_local_cpu(tcp_tran_rr_request->cpu_rate);
10974 }
10975
10976
10977
10978 /* before we send the response back to the initiator, pull some of */
10979 /* the socket parms from the globals */
10980 tcp_tran_rr_response->send_buf_size = lss_size;
10981 tcp_tran_rr_response->recv_buf_size = lsr_size;
10982 tcp_tran_rr_response->no_delay = loc_nodelay;
10983 tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid;
10984 tcp_tran_rr_response->so_sndavoid = loc_sndavoid;
10985
10986 send_response();
10987
10988 addrlen = sizeof(peeraddr_in);
10989
10990 /* Now it's time to start receiving data on the connection. We will */
10991 /* first grab the apropriate counters and then start grabbing. */
10992
10993 cpu_start(tcp_tran_rr_request->measure_cpu);
10994
10995 /* The loop will exit when the sender does a shutdown, which will */
10996 /* return a length of zero */
10997
10998 if (tcp_tran_rr_request->test_length > 0) {
10999 times_up = 0;
11000 trans_remaining = 0;
11001 start_timer(tcp_tran_rr_request->test_length + PAD_TIME);
11002 }
11003 else {
11004 times_up = 1;
11005 trans_remaining = tcp_tran_rr_request->test_length * -1;
11006 }
11007
11008 trans_received = 0;
11009
11010 while ((!times_up) || (trans_remaining > 0)) {
11011
11012 /* accept a connection from the remote */
11013 if ((s_data=accept(s_listen,
11014 (struct sockaddr *)&peeraddr_in,
11015 &addrlen)) == INVALID_SOCKET) {
11016 if (errno == EINTR) {
11017 /* the timer popped */
11018 timed_out = 1;
11019 break;
11020 }
11021 fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno);
11022 fflush(where);
11023 close(s_listen);
11024
11025 exit(1);
11026 }
11027
11028 if (debug) {
11029 fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n");
11030 fflush(where);
11031 }
11032
11033 #ifdef WIN32
11034 /* this is used so the timer thread can close the socket out from */
11035 /* under us, which to date is the easiest/cleanest/least */
11036 /* Windows-specific way I can find to force the winsock calls to */
11037 /* return WSAEINTR with the test is over. anything that will run on */
11038 /* 95 and NT and is closer to what netperf expects from Unix signals */
11039 /* and such would be appreciated raj 1/96 */
11040 win_kludge_socket = s_data;
11041 #endif /* WIN32 */
11042
11043 #ifdef KLUDGE_SOCKET_OPTIONS
11044 /* this is for those systems which *INCORRECTLY* fail to pass */
11045 /* attributes across an accept() call. Including this goes against */
11046 /* my better judgement :( raj 11/95 */
11047
11048 kludge_socket_options(s_data);
11049
11050 #endif /* KLUDGE_SOCKET_OPTIONS */
11051
11052 temp_message_ptr = recv_message_ptr;
11053 request_bytes_remaining = tcp_tran_rr_request->request_size;
11054
11055 /* receive the request from the other side. we can just receive */
11056 /* until we get zero bytes, but that would be a slight structure */
11057 /* change in the code, with minimal perfomance effects. If */
11058 /* however, I has variable-length messages, I would want to do */
11059 /* this to avoid needing "double reads" - one for the message */
11060 /* length, and one for the rest of the message raj 3/95 */
11061 while(request_bytes_remaining > 0) {
11062 if((request_bytes_recvd=recv(s_data,
11063 temp_message_ptr,
11064 request_bytes_remaining,
11065 0)) == SOCKET_ERROR) {
11066 if ( SOCKET_EINTR(request_bytes_recvd) )
11067 {
11068 /* the timer popped */
11069 timed_out = 1;
11070 break;
11071 }
11072 netperf_response.content.serv_errno = errno;
11073 send_response();
11074 exit(1);
11075 }
11076 else {
11077 request_bytes_remaining -= request_bytes_recvd;
11078 temp_message_ptr += request_bytes_recvd;
11079 }
11080 }
11081
11082 if (timed_out) {
11083 /* we hit the end of the test based on time - lets */
11084 /* bail out of here now... */
11085 fprintf(where,"yo5\n");
11086 fflush(where);
11087 break;
11088 }
11089
11090 /* Now, send the response to the remote we can use sendto here to */
11091 /* help remind people that this is an rfc 1644 style of test */
11092 if((bytes_sent=sendto(s_data,
11093 send_message_ptr,
11094 tcp_tran_rr_request->response_size,
11095 MSG_EOF,
11096 (struct sockaddr *)&peeraddr_in,
11097 sizeof(struct sockaddr_storage))) == SOCKET_ERROR) {
11098 if (SOCKET_EINTR(bytes_sent)) {
11099 /* the test timer has popped */
11100 timed_out = 1;
11101 fprintf(where,"yo6\n");
11102 fflush(where);
11103 break;
11104 }
11105 netperf_response.content.serv_errno = 99;
11106 send_response();
11107 exit(1);
11108 }
11109
11110 trans_received++;
11111 if (trans_remaining) {
11112 trans_remaining--;
11113 }
11114
11115 if (debug) {
11116 fprintf(where,
11117 "recv_tcp_tran_rr: Transaction %d complete\n",
11118 trans_received);
11119 fflush(where);
11120 }
11121
11122 /* close the connection. since we have disable PUSH on sends, the */
11123 /* FIN should be tacked-onto our last send instead of being */
11124 /* standalone */
11125 close(s_data);
11126
11127 }
11128
11129
11130 /* The loop now exits due to timeout or transaction count being */
11131 /* reached */
11132
11133 cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time);
11134
11135 if (timed_out) {
11136 /* we ended the test by time, which was at least 2 seconds */
11137 /* longer than we wanted to run. so, we want to subtract */
11138 /* PAD_TIME from the elapsed_time. */
11139 elapsed_time -= PAD_TIME;
11140 }
11141 /* send the results to the sender */
11142
11143 if (debug) {
11144 fprintf(where,
11145 "recv_tcp_tran_rr: got %d transactions\n",
11146 trans_received);
11147 fflush(where);
11148 }
11149
11150 tcp_tran_rr_results->bytes_received = (trans_received *
11151 (tcp_tran_rr_request->request_size +
11152 tcp_tran_rr_request->response_size));
11153 tcp_tran_rr_results->trans_received = trans_received;
11154 tcp_tran_rr_results->elapsed_time = elapsed_time;
11155 if (tcp_tran_rr_request->measure_cpu) {
11156 tcp_tran_rr_results->cpu_util = calc_cpu_util(elapsed_time);
11157 }
11158
11159 if (debug) {
11160 fprintf(where,
11161 "recv_tcp_tran_rr: test complete, sending results.\n");
11162 fflush(where);
11163 }
11164
11165 send_response();
11166
11167 }
11168 #endif /* DO_1644 */
11169
11170 #ifdef DO_NBRR
11171 /* this routine implements the sending (netperf) side of the TCP_RR */
11172 /* test using POSIX-style non-blocking sockets. */
11173
11174 void
send_tcp_nbrr(char remote_host[])11175 send_tcp_nbrr(char remote_host[])
11176 {
11177
11178 char *tput_title = "\
11179 Local /Remote\n\
11180 Socket Size Request Resp. Elapsed Trans.\n\
11181 Send Recv Size Size Time Rate \n\
11182 bytes Bytes bytes bytes secs. per sec \n\n";
11183
11184 char *tput_fmt_0 =
11185 "%7.2f\n";
11186
11187 char *tput_fmt_1_line_1 = "\
11188 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
11189 char *tput_fmt_1_line_2 = "\
11190 %-6d %-6d\n";
11191
11192 char *cpu_title = "\
11193 Local /Remote\n\
11194 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
11195 Send Recv Size Size Time Rate local remote local remote\n\
11196 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
11197
11198 char *cpu_fmt_0 =
11199 "%6.3f %c\n";
11200
11201 char *cpu_fmt_1_line_1 = "\
11202 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
11203
11204 char *cpu_fmt_1_line_2 = "\
11205 %-6d %-6d\n";
11206
11207 char *ksink_fmt = "\
11208 Alignment Offset\n\
11209 Local Remote Local Remote\n\
11210 Send Recv Send Recv\n\
11211 %5d %5d %5d %5d\n";
11212
11213
11214 int timed_out = 0;
11215 float elapsed_time;
11216
11217 int len;
11218 char *temp_message_ptr;
11219 int nummessages;
11220 SOCKET send_socket;
11221 int trans_remaining;
11222 double bytes_xferd;
11223
11224 struct ring_elt *send_ring;
11225 struct ring_elt *recv_ring;
11226
11227 int rsp_bytes_left;
11228 int rsp_bytes_recvd;
11229
11230 float local_cpu_utilization;
11231 float local_service_demand;
11232 float remote_cpu_utilization;
11233 float remote_service_demand;
11234 double thruput;
11235
11236 struct hostent *hp;
11237 struct sockaddr_storage server;
11238 unsigned int addr;
11239
11240 struct tcp_rr_request_struct *tcp_rr_request;
11241 struct tcp_rr_response_struct *tcp_rr_response;
11242 struct tcp_rr_results_struct *tcp_rr_result;
11243
11244 struct addrinfo *remote_res;
11245 struct addrinfo *local_res;
11246
11247 tcp_rr_request =
11248 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
11249 tcp_rr_response=
11250 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
11251 tcp_rr_result =
11252 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
11253
11254 #ifdef WANT_HISTOGRAM
11255 if (verbosity > 1) {
11256 time_hist = HIST_new();
11257 }
11258 #endif /* WANT_HISTOGRAM */
11259
11260 /* since we are now disconnected from the code that established the */
11261 /* control socket, and since we want to be able to use different */
11262 /* protocols and such, we are passed the name of the remote host and */
11263 /* must turn that into the test specific addressing information. */
11264
11265 bzero((char *)&server,
11266 sizeof(server));
11267
11268 complete_addrinfos(&remote_res,
11269 &local_res,
11270 remote_host,
11271 SOCK_STREAM,
11272 IPPROTO_TCP,
11273 0);
11274
11275 if ( print_headers ) {
11276 print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res);
11277 }
11278
11279 /* initialize a few counters */
11280
11281 send_ring = NULL;
11282 recv_ring = NULL;
11283 confidence_iteration = 1;
11284 init_stat();
11285
11286 /* we have a great-big while loop which controls the number of times */
11287 /* we run a particular test. this is for the calculation of a */
11288 /* confidence interval (I really should have stayed awake during */
11289 /* probstats :). If the user did not request confidence measurement */
11290 /* (no confidence is the default) then we will only go though the */
11291 /* loop once. the confidence stuff originates from the folks at IBM */
11292
11293 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
11294 (confidence_iteration <= iteration_min)) {
11295
11296 /* initialize a few counters. we have to remember that we might be */
11297 /* going through the loop more than once. */
11298
11299 nummessages = 0;
11300 bytes_xferd = 0.0;
11301 times_up = 0;
11302 timed_out = 0;
11303 trans_remaining = 0;
11304
11305 /* set-up the data buffers with the requested alignment and offset. */
11306 /* since this is a request/response test, default the send_width and */
11307 /* recv_width to 1 and not two raj 7/94 */
11308
11309 if (send_width == 0) send_width = 1;
11310 if (recv_width == 0) recv_width = 1;
11311
11312 if (send_ring == NULL) {
11313 send_ring = allocate_buffer_ring(send_width,
11314 req_size,
11315 local_send_align,
11316 local_send_offset);
11317 }
11318
11319 if (recv_ring == NULL) {
11320 recv_ring = allocate_buffer_ring(recv_width,
11321 rsp_size,
11322 local_recv_align,
11323 local_recv_offset);
11324 }
11325
11326 /*set up the data socket */
11327 send_socket = create_data_socket(local_res);
11328
11329 if (send_socket == INVALID_SOCKET){
11330 perror("netperf: send_tcp_nbrr: tcp stream data socket");
11331 exit(1);
11332 }
11333
11334 if (debug) {
11335 fprintf(where,"send_tcp_nbrr: send_socket obtained...\n");
11336 }
11337
11338 /* If the user has requested cpu utilization measurements, we must */
11339 /* calibrate the cpu(s). We will perform this task within the tests */
11340 /* themselves. If the user has specified the cpu rate, then */
11341 /* calibrate_local_cpu will return rather quickly as it will have */
11342 /* nothing to do. If local_cpu_rate is zero, then we will go through */
11343 /* all the "normal" calibration stuff and return the rate back.*/
11344
11345 if (local_cpu_usage) {
11346 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
11347 }
11348
11349 /* Tell the remote end to do a listen. The server alters the socket */
11350 /* paramters on the other side at this point, hence the reason for */
11351 /* all the values being passed in the setup message. If the user did */
11352 /* not specify any of the parameters, they will be passed as 0, which */
11353 /* will indicate to the remote that no changes beyond the system's */
11354 /* default should be used. Alignment is the exception, it will */
11355 /* default to 8, which will be no alignment alterations. */
11356
11357 netperf_request.content.request_type = DO_TCP_NBRR;
11358 tcp_rr_request->recv_buf_size = rsr_size_req;
11359 tcp_rr_request->send_buf_size = rss_size_req;
11360 tcp_rr_request->recv_alignment = remote_recv_align;
11361 tcp_rr_request->recv_offset = remote_recv_offset;
11362 tcp_rr_request->send_alignment = remote_send_align;
11363 tcp_rr_request->send_offset = remote_send_offset;
11364 tcp_rr_request->request_size = req_size;
11365 tcp_rr_request->response_size = rsp_size;
11366 tcp_rr_request->no_delay = rem_nodelay;
11367 tcp_rr_request->measure_cpu = remote_cpu_usage;
11368 tcp_rr_request->cpu_rate = remote_cpu_rate;
11369 tcp_rr_request->so_rcvavoid = rem_rcvavoid;
11370 tcp_rr_request->so_sndavoid = rem_sndavoid;
11371 if (test_time) {
11372 tcp_rr_request->test_length = test_time;
11373 }
11374 else {
11375 tcp_rr_request->test_length = test_trans * -1;
11376 }
11377
11378 if (debug > 1) {
11379 fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n");
11380 }
11381
11382 send_request();
11383
11384 /* The response from the remote will contain all of the relevant */
11385 /* socket parameters for this test type. We will put them back into */
11386 /* the variables here so they can be displayed if desired. The */
11387 /* remote will have calibrated CPU if necessary, and will have done */
11388 /* all the needed set-up we will have calibrated the cpu locally */
11389 /* before sending the request, and will grab the counter value right*/
11390 /* after the connect returns. The remote will grab the counter right*/
11391 /* after the accept call. This saves the hassle of extra messages */
11392 /* being sent for the TCP tests. */
11393
11394 recv_response();
11395
11396 if (!netperf_response.content.serv_errno) {
11397 if (debug)
11398 fprintf(where,"remote listen done.\n");
11399 rsr_size = tcp_rr_response->recv_buf_size;
11400 rss_size = tcp_rr_response->send_buf_size;
11401 rem_nodelay = tcp_rr_response->no_delay;
11402 remote_cpu_usage = tcp_rr_response->measure_cpu;
11403 remote_cpu_rate = tcp_rr_response->cpu_rate;
11404 /* make sure that port numbers are in network order */
11405 server.sin_port = (unsigned short)tcp_rr_response->data_port_number;
11406 server.sin_port = htons(server.sin_port);
11407 }
11408 else {
11409 Set_errno(netperf_response.content.serv_errno);
11410 fprintf(where,
11411 "netperf: remote error %d",
11412 netperf_response.content.serv_errno);
11413 perror("");
11414 fflush(where);
11415 exit(1);
11416 }
11417
11418 /*Connect up to the remote port on the data socket */
11419 if (connect(send_socket,
11420 remote_res->ai_addr,
11421 remote_res->ai_addrlen) == INVALID_SOCKET){
11422 perror("netperf: data socket connect failed");
11423
11424 exit(1);
11425 }
11426
11427 /* now that we are connected, mark the socket as non-blocking */
11428 if (!set_nonblock(send_socket)) {
11429 perror("netperf: set_nonblock");
11430 exit(1);
11431 }
11432
11433 #ifdef WIN32
11434 /* this is used so the timer thread can close the socket out from */
11435 /* under us, which to date is the easiest/cleanest/least */
11436 /* Windows-specific way I can find to force the winsock calls to */
11437 /* return WSAEINTR with the test is over. anything that will run on */
11438 /* 95 and NT and is closer to what netperf expects from Unix signals */
11439 /* and such would be appreciated raj 1/96 */
11440 win_kludge_socket = send_socket;
11441 #endif /* WIN32 */
11442
11443 /* Data Socket set-up is finished. If there were problems, either the */
11444 /* connect would have failed, or the previous response would have */
11445 /* indicated a problem. I failed to see the value of the extra */
11446 /* message after the accept on the remote. If it failed, we'll see it */
11447 /* here. If it didn't, we might as well start pumping data. */
11448
11449 /* Set-up the test end conditions. For a request/response test, they */
11450 /* can be either time or transaction based. */
11451
11452 if (test_time) {
11453 /* The user wanted to end the test after a period of time. */
11454 times_up = 0;
11455 trans_remaining = 0;
11456 start_timer(test_time);
11457 }
11458 else {
11459 /* The tester wanted to send a number of bytes. */
11460 trans_remaining = test_bytes;
11461 times_up = 1;
11462 }
11463
11464 /* The cpu_start routine will grab the current time and possibly */
11465 /* value of the idle counter for later use in measuring cpu */
11466 /* utilization and/or service demand and thruput. */
11467
11468 cpu_start(local_cpu_usage);
11469
11470 #ifdef WANT_INTERVALS
11471 INTERVALS_INIT();
11472 #endif /* WANT_INTERVALS */
11473
11474 /* We use an "OR" to control test execution. When the test is */
11475 /* controlled by time, the byte count check will always return false. */
11476 /* When the test is controlled by byte count, the time test will */
11477 /* always return false. When the test is finished, the whole */
11478 /* expression will go false and we will stop sending data. I think I */
11479 /* just arbitrarily decrement trans_remaining for the timed test, but */
11480 /* will not do that just yet... One other question is whether or not */
11481 /* the send buffer and the receive buffer should be the same buffer. */
11482
11483 while ((!times_up) || (trans_remaining > 0)) {
11484 /* send the request. we assume that if we use a blocking socket, */
11485 /* the request will be sent at one shot. */
11486
11487 #ifdef WANT_HISTOGRAM
11488 if (verbosity > 1) {
11489 /* timestamp just before our call to send, and then again just */
11490 /* after the receive raj 8/94 */
11491 HIST_timestamp(&time_one);
11492 }
11493 #endif /* WANT_HISTOGRAM */
11494
11495 /* even though this is a non-blocking socket, we will assume for */
11496 /* the time being that we will be able to send an entire request */
11497 /* without getting an EAGAIN */
11498 if((len=send(send_socket,
11499 send_ring->buffer_ptr,
11500 req_size,
11501 0)) != req_size) {
11502 if (SOCKET_EINTR(len)) {
11503 /* we hit the end of a */
11504 /* timed test. */
11505 timed_out = 1;
11506 break;
11507 }
11508 perror("send_tcp_nbrr: data send error");
11509 exit(1);
11510 }
11511 send_ring = send_ring->next;
11512
11513 /* receive the response. since we are using non-blocking I/O, we */
11514 /* will "spin" on the recvs */
11515 rsp_bytes_left = rsp_size;
11516 temp_message_ptr = recv_ring->buffer_ptr;
11517 while(rsp_bytes_left > 0) {
11518 if((rsp_bytes_recvd=recv(send_socket,
11519 temp_message_ptr,
11520 rsp_bytes_left,
11521 0)) == SOCKET_ERROR) {
11522 if (SOCKET_EINTR(rsp_bytes_recvd))
11523 {
11524 /* We hit the end of a timed test. */
11525 timed_out = 1;
11526 break;
11527 }
11528 #ifndef WIN32 // But what does WinNT indicate in this situation...
11529 else if (errno == EAGAIN) {
11530 Set_errno(0);
11531 continue;
11532 }
11533 #endif
11534 else {
11535 perror("send_tcp_nbrr: data recv error");
11536 exit(1);
11537 }
11538 }
11539 rsp_bytes_left -= rsp_bytes_recvd;
11540 temp_message_ptr += rsp_bytes_recvd;
11541 }
11542 recv_ring = recv_ring->next;
11543
11544 if (timed_out) {
11545 /* we may have been in a nested while loop - we need */
11546 /* another call to break. */
11547 break;
11548 }
11549
11550 #ifdef WANT_HISTOGRAM
11551 if (verbosity > 1) {
11552 HIST_timestamp(&time_two);
11553 HIST_add(time_hist,delta_micro(&time_one,&time_two));
11554 }
11555 #endif /* WANT_HISTOGRAM */
11556 #ifdef WANT_INTERVALS
11557 INTERVALS_WAIT();
11558 #endif /* WANT_INTERVALS */
11559
11560 nummessages++;
11561 if (trans_remaining) {
11562 trans_remaining--;
11563 }
11564
11565 if (debug > 3) {
11566 if ((nummessages % 100) == 0) {
11567 fprintf(where,
11568 "Transaction %d completed\n",
11569 nummessages);
11570 fflush(where);
11571 }
11572 }
11573 }
11574
11575 /* At this point we used to call shutdown on the data socket to be */
11576 /* sure all the data was delivered, but this was not germane in a */
11577 /* request/response test, and it was causing the tests to "hang" when */
11578 /* they were being controlled by time. So, I have replaced this */
11579 /* shutdown call with a call to close that can be found later in the */
11580 /* procedure. */
11581
11582 /* this call will always give us the elapsed time for the test, and */
11583 /* will also store-away the necessaries for cpu utilization */
11584
11585 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
11586 /* measured? how long */
11587 /* did we really run? */
11588
11589 /* Get the statistics from the remote end. The remote will have */
11590 /* calculated service demand and all those interesting things. If it */
11591 /* wasn't supposed to care, it will return obvious values. */
11592
11593 #if defined(WANT_INTERVALS)
11594 #ifdef WIN32
11595 stop_itimer();
11596 #endif
11597 #endif /* WANT_INTERVALS */
11598
11599 recv_response();
11600 if (!netperf_response.content.serv_errno) {
11601 if (debug)
11602 fprintf(where,"remote results obtained\n");
11603 }
11604 else {
11605 Set_errno(netperf_response.content.serv_errno);
11606 fprintf(where,
11607 "netperf: remote error %d",
11608 netperf_response.content.serv_errno);
11609 perror("");
11610 fflush(where);
11611
11612 exit(1);
11613 }
11614
11615 /* We now calculate what our thruput was for the test. */
11616
11617 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
11618 thruput = nummessages/elapsed_time;
11619
11620 if (local_cpu_usage || remote_cpu_usage) {
11621 /* We must now do a little math for service demand and cpu */
11622 /* utilization for the system(s) */
11623 /* Of course, some of the information might be bogus because */
11624 /* there was no idle counter in the kernel(s). We need to make */
11625 /* a note of this for the user's benefit...*/
11626 if (local_cpu_usage) {
11627 local_cpu_utilization = calc_cpu_util(0.0);
11628 /* since calc_service demand is doing ms/Kunit we will */
11629 /* multiply the number of transaction by 1024 to get */
11630 /* "good" numbers */
11631 local_service_demand = calc_service_demand((double) nummessages*1024,
11632 0.0,
11633 0.0,
11634 0);
11635 }
11636 else {
11637 local_cpu_utilization = (float) -1.0;
11638 local_service_demand = (float) -1.0;
11639 }
11640
11641 if (remote_cpu_usage) {
11642 remote_cpu_utilization = tcp_rr_result->cpu_util;
11643 /* since calc_service demand is doing ms/Kunit we will */
11644 /* multiply the number of transaction by 1024 to get */
11645 /* "good" numbers */
11646 remote_service_demand = calc_service_demand((double) nummessages*1024,
11647 0.0,
11648 remote_cpu_utilization,
11649 tcp_rr_result->num_cpus);
11650 }
11651 else {
11652 remote_cpu_utilization = (float) -1.0;
11653 remote_service_demand = (float) -1.0;
11654 }
11655
11656 }
11657 else {
11658 /* we were not measuring cpu, for the confidence stuff, we */
11659 /* should make it -1.0 */
11660 local_cpu_utilization = (float) -1.0;
11661 local_service_demand = (float) -1.0;
11662 remote_cpu_utilization = (float) -1.0;
11663 remote_service_demand = (float) -1.0;
11664 }
11665
11666 /* at this point, we want to calculate the confidence information. */
11667 /* if debugging is on, calculate_confidence will print-out the */
11668 /* parameters we pass it */
11669
11670 calculate_confidence(confidence_iteration,
11671 elapsed_time,
11672 thruput,
11673 local_cpu_utilization,
11674 remote_cpu_utilization,
11675 local_service_demand,
11676 remote_service_demand);
11677
11678
11679 confidence_iteration++;
11680
11681 /* we are now done with the socket, so close it */
11682 close(send_socket);
11683
11684 }
11685
11686 retrieve_confident_values(&elapsed_time,
11687 &thruput,
11688 &local_cpu_utilization,
11689 &remote_cpu_utilization,
11690 &local_service_demand,
11691 &remote_service_demand);
11692
11693 /* We are now ready to print all the information. If the user */
11694 /* has specified zero-level verbosity, we will just print the */
11695 /* local service demand, or the remote service demand. If the */
11696 /* user has requested verbosity level 1, he will get the basic */
11697 /* "streamperf" numbers. If the user has specified a verbosity */
11698 /* of greater than 1, we will display a veritable plethora of */
11699 /* background information from outside of this block as it it */
11700 /* not cpu_measurement specific... */
11701
11702 if (confidence < 0) {
11703 /* we did not hit confidence, but were we asked to look for it? */
11704 if (iteration_max > 1) {
11705 display_confidence();
11706 }
11707 }
11708
11709 if (local_cpu_usage || remote_cpu_usage) {
11710 local_cpu_method = format_cpu_method(cpu_method);
11711 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
11712
11713 switch (verbosity) {
11714 case 0:
11715 if (local_cpu_usage) {
11716 fprintf(where,
11717 cpu_fmt_0,
11718 local_service_demand,
11719 local_cpu_method);
11720 }
11721 else {
11722 fprintf(where,
11723 cpu_fmt_0,
11724 remote_service_demand,
11725 remote_cpu_method);
11726 }
11727 break;
11728 case 1:
11729 case 2:
11730 if (print_headers) {
11731 fprintf(where,
11732 cpu_title,
11733 local_cpu_method,
11734 remote_cpu_method);
11735 }
11736
11737 fprintf(where,
11738 cpu_fmt_1_line_1, /* the format string */
11739 lss_size, /* local sendbuf size */
11740 lsr_size,
11741 req_size, /* how large were the requests */
11742 rsp_size, /* guess */
11743 elapsed_time, /* how long was the test */
11744 thruput,
11745 local_cpu_utilization, /* local cpu */
11746 remote_cpu_utilization, /* remote cpu */
11747 local_service_demand, /* local service demand */
11748 remote_service_demand); /* remote service demand */
11749 fprintf(where,
11750 cpu_fmt_1_line_2,
11751 rss_size,
11752 rsr_size);
11753 break;
11754 }
11755 }
11756 else {
11757 /* The tester did not wish to measure service demand. */
11758
11759 switch (verbosity) {
11760 case 0:
11761 fprintf(where,
11762 tput_fmt_0,
11763 thruput);
11764 break;
11765 case 1:
11766 case 2:
11767 if (print_headers) {
11768 fprintf(where,tput_title,format_units());
11769 }
11770
11771 fprintf(where,
11772 tput_fmt_1_line_1, /* the format string */
11773 lss_size,
11774 lsr_size,
11775 req_size, /* how large were the requests */
11776 rsp_size, /* how large were the responses */
11777 elapsed_time, /* how long did it take */
11778 thruput);
11779 fprintf(where,
11780 tput_fmt_1_line_2,
11781 rss_size, /* remote recvbuf size */
11782 rsr_size);
11783
11784 break;
11785 }
11786 }
11787
11788 /* it would be a good thing to include information about some of the */
11789 /* other parameters that may have been set for this test, but at the */
11790 /* moment, I do not wish to figure-out all the formatting, so I will */
11791 /* just put this comment here to help remind me that it is something */
11792 /* that should be done at a later time. */
11793
11794 /* how to handle the verbose information in the presence of */
11795 /* confidence intervals is yet to be determined... raj 11/94 */
11796 if (verbosity > 1) {
11797 /* The user wanted to know it all, so we will give it to him. */
11798 /* This information will include as much as we can find about */
11799 /* TCP statistics, the alignments of the sends and receives */
11800 /* and all that sort of rot... */
11801
11802 fprintf(where,
11803 ksink_fmt,
11804 local_send_align,
11805 remote_recv_offset,
11806 local_send_offset,
11807 remote_recv_offset);
11808
11809 #ifdef WANT_HISTOGRAM
11810 fprintf(where,"\nHistogram of request/response times\n");
11811 fflush(where);
11812 HIST_report(time_hist);
11813 #endif /* WANT_HISTOGRAM */
11814
11815 }
11816
11817 }
11818
11819 /* this routine implements the receive (netserver) side of a TCP_RR */
11820 /* test */
11821 void
recv_tcp_nbrr()11822 recv_tcp_nbrr()
11823 {
11824
11825 struct ring_elt *send_ring;
11826 struct ring_elt *recv_ring;
11827
11828 struct sockaddr_in myaddr_in,
11829 peeraddr_in;
11830 SOCKET s_listen,s_data;
11831 netperf_socklen_t addrlen;
11832 char *temp_message_ptr;
11833 int trans_received;
11834 int trans_remaining;
11835 int bytes_sent;
11836 int request_bytes_recvd;
11837 int request_bytes_remaining;
11838 int timed_out = 0;
11839 float elapsed_time;
11840
11841 struct addrinfo *local_res;
11842 char local_name[BUFSIZ];
11843 char port_buffer[PORTBUFSIZE];
11844
11845 struct tcp_rr_request_struct *tcp_rr_request;
11846 struct tcp_rr_response_struct *tcp_rr_response;
11847 struct tcp_rr_results_struct *tcp_rr_results;
11848
11849 tcp_rr_request =
11850 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
11851 tcp_rr_response =
11852 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
11853 tcp_rr_results =
11854 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
11855
11856 if (debug) {
11857 fprintf(where,"netserver: recv_tcp_nbrr: entered...\n");
11858 fflush(where);
11859 }
11860
11861 /* We want to set-up the listen socket with all the desired */
11862 /* parameters and then let the initiator know that all is ready. If */
11863 /* socket size defaults are to be used, then the initiator will have */
11864 /* sent us 0's. If the socket sizes cannot be changed, then we will */
11865 /* send-back what they are. If that information cannot be determined, */
11866 /* then we send-back -1's for the sizes. If things go wrong for any */
11867 /* reason, we will drop back ten yards and punt. */
11868
11869 /* If anything goes wrong, we want the remote to know about it. It */
11870 /* would be best if the error that the remote reports to the user is */
11871 /* the actual error we encountered, rather than some bogus unexpected */
11872 /* response type message. */
11873
11874 if (debug) {
11875 fprintf(where,"recv_tcp_nbrr: setting the response type...\n");
11876 fflush(where);
11877 }
11878
11879 netperf_response.content.response_type = TCP_RR_RESPONSE;
11880
11881 if (debug) {
11882 fprintf(where,"recv_tcp_nbrr: the response type is set...\n");
11883 fflush(where);
11884 }
11885
11886 /* allocate the recv and send rings with the requested alignments */
11887 /* and offsets. raj 7/94 */
11888 if (debug) {
11889 fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n",
11890 tcp_rr_request->recv_alignment,
11891 tcp_rr_request->recv_offset);
11892 fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n",
11893 tcp_rr_request->send_alignment,
11894 tcp_rr_request->send_offset);
11895 fflush(where);
11896 }
11897
11898 /* at some point, these need to come to us from the remote system */
11899 if (send_width == 0) send_width = 1;
11900 if (recv_width == 0) recv_width = 1;
11901
11902 send_ring = allocate_buffer_ring(send_width,
11903 tcp_rr_request->response_size,
11904 tcp_rr_request->send_alignment,
11905 tcp_rr_request->send_offset);
11906
11907 recv_ring = allocate_buffer_ring(recv_width,
11908 tcp_rr_request->request_size,
11909 tcp_rr_request->recv_alignment,
11910 tcp_rr_request->recv_offset);
11911
11912
11913 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
11914 /* can put in OUR values !-) At some point, we may want to nail this */
11915 /* socket to a particular network-level address, but for now, */
11916 /* INADDR_ANY should be just fine. */
11917
11918 bzero((char *)&myaddr_in,
11919 sizeof(myaddr_in));
11920 myaddr_in.sin_family = AF_INET;
11921 myaddr_in.sin_addr.s_addr = INADDR_ANY;
11922 myaddr_in.sin_port = htons((unsigned short)tcp_rr_request->port);
11923
11924 /* Grab a socket to listen on, and then listen on it. */
11925
11926 if (debug) {
11927 fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n");
11928 fflush(where);
11929 }
11930
11931 /* create_data_socket expects to find some things in the global */
11932 /* variables, so set the globals based on the values in the request. */
11933 /* once the socket has been created, we will set the response values */
11934 /* based on the updated value of those globals. raj 7/94 */
11935 lss_size_req = tcp_rr_request->send_buf_size;
11936 lsr_size_req = tcp_rr_request->recv_buf_size;
11937 loc_nodelay = tcp_rr_request->no_delay;
11938 loc_rcvavoid = tcp_rr_request->so_rcvavoid;
11939 loc_sndavoid = tcp_rr_request->so_sndavoid;
11940
11941 set_hostname_and_port(local_name,
11942 port_buffer,
11943 nf_to_af(tcp_rr_request->ipfamily),
11944 tcp_rr_request->port);
11945
11946 local_res = complete_addrinfo(local_name,
11947 local_name,
11948 port_buffer,
11949 nf_to_af(tcp_rr_request->ipfamily),
11950 SOCK_STREAM,
11951 IPPROTO_TCP,
11952 0);
11953
11954 s_listen = create_data_socket(local_res);
11955
11956 if (s_listen == INVALID_SOCKET) {
11957 netperf_response.content.serv_errno = errno;
11958 send_response();
11959
11960 exit(1);
11961 }
11962
11963 /* Let's get an address assigned to this socket so we can tell the */
11964 /* initiator how to reach the data socket. There may be a desire to */
11965 /* nail this socket to a specific IP address in a multi-homed, */
11966 /* multi-connection situation, but for now, we'll ignore the issue */
11967 /* and concentrate on single connection testing. */
11968
11969 if (bind(s_listen,
11970 (struct sockaddr *)&myaddr_in,
11971 sizeof(myaddr_in)) == SOCKET_ERROR) {
11972 netperf_response.content.serv_errno = errno;
11973 close(s_listen);
11974 send_response();
11975
11976 exit(1);
11977 }
11978
11979 /* Now, let's set-up the socket to listen for connections */
11980 if (listen(s_listen, 5) == SOCKET_ERROR) {
11981 netperf_response.content.serv_errno = errno;
11982 close(s_listen);
11983 send_response();
11984
11985 exit(1);
11986 }
11987
11988
11989 /* now get the port number assigned by the system */
11990 addrlen = sizeof(myaddr_in);
11991 if (getsockname(s_listen,
11992 (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){
11993 netperf_response.content.serv_errno = errno;
11994 close(s_listen);
11995 send_response();
11996
11997 exit(1);
11998 }
11999
12000 /* Now myaddr_in contains the port and the internet address this is */
12001 /* returned to the sender also implicitly telling the sender that the */
12002 /* socket buffer sizing has been done. */
12003
12004 tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
12005 netperf_response.content.serv_errno = 0;
12006
12007 /* But wait, there's more. If the initiator wanted cpu measurements, */
12008 /* then we must call the calibrate routine, which will return the max */
12009 /* rate back to the initiator. If the CPU was not to be measured, or */
12010 /* something went wrong with the calibration, we will return a 0.0 to */
12011 /* the initiator. */
12012
12013 tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */
12014 tcp_rr_response->measure_cpu = 0;
12015
12016 if (tcp_rr_request->measure_cpu) {
12017 tcp_rr_response->measure_cpu = 1;
12018 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
12019 }
12020
12021
12022 /* before we send the response back to the initiator, pull some of */
12023 /* the socket parms from the globals */
12024 tcp_rr_response->send_buf_size = lss_size;
12025 tcp_rr_response->recv_buf_size = lsr_size;
12026 tcp_rr_response->no_delay = loc_nodelay;
12027 tcp_rr_response->so_rcvavoid = loc_rcvavoid;
12028 tcp_rr_response->so_sndavoid = loc_sndavoid;
12029 tcp_rr_response->test_length = tcp_rr_request->test_length;
12030 send_response();
12031
12032 addrlen = sizeof(peeraddr_in);
12033
12034 if ((s_data = accept(s_listen,
12035 (struct sockaddr *)&peeraddr_in,
12036 &addrlen)) == INVALID_SOCKET) {
12037 /* Let's just punt. The remote will be given some information */
12038 close(s_listen);
12039 exit(1);
12040 }
12041
12042 if (debug) {
12043 fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n");
12044 fflush(where);
12045 }
12046
12047 #ifdef KLUDGE_SOCKET_OPTIONS
12048 /* this is for those systems which *INCORRECTLY* fail to pass */
12049 /* attributes across an accept() call. Including this goes against */
12050 /* my better judgement :( raj 11/95 */
12051
12052 kludge_socket_options(s_data);
12053
12054 #endif /* KLUDGE_SOCKET_OPTIONS */
12055
12056 /* now that we are connected, mark the socket as non-blocking */
12057 if (!set_nonblock(s_data)) {
12058 close(s_data);
12059 exit(1);
12060 }
12061
12062
12063 /* Now it's time to start receiving data on the connection. We will */
12064 /* first grab the apropriate counters and then start grabbing. */
12065
12066 cpu_start(tcp_rr_request->measure_cpu);
12067
12068 #ifdef WIN32
12069 /* this is used so the timer thread can close the socket out from */
12070 /* under us, which to date is the easiest/cleanest/least */
12071 /* Windows-specific way I can find to force the winsock calls to */
12072 /* return WSAEINTR with the test is over. anything that will run on */
12073 /* 95 and NT and is closer to what netperf expects from Unix signals */
12074 /* and such would be appreciated raj 1/96 */
12075 win_kludge_socket = s_data;
12076 #endif /* WIN32 */
12077
12078 /* The loop will exit when the sender does a shutdown, which will */
12079 /* return a length of zero */
12080
12081 if (tcp_rr_request->test_length > 0) {
12082 times_up = 0;
12083 trans_remaining = 0;
12084 start_timer(tcp_rr_request->test_length + PAD_TIME);
12085 }
12086 else {
12087 times_up = 1;
12088 trans_remaining = tcp_rr_request->test_length * -1;
12089 }
12090
12091 trans_received = 0;
12092
12093 while ((!times_up) || (trans_remaining > 0)) {
12094 temp_message_ptr = recv_ring->buffer_ptr;
12095 request_bytes_remaining = tcp_rr_request->request_size;
12096 while(request_bytes_remaining > 0) {
12097 if((request_bytes_recvd=recv(s_data,
12098 temp_message_ptr,
12099 request_bytes_remaining,
12100 0)) == SOCKET_ERROR) {
12101 if ( SOCKET_EINTR(request_bytes_recvd))
12102 {
12103 /* the timer popped */
12104 timed_out = 1;
12105 break;
12106 }
12107 #ifndef WIN32 // But what does WinNT indicate in this situation...
12108 else if (errno == EAGAIN) {
12109 Set_errno(0);
12110 if (times_up) {
12111 timed_out = 1;
12112 break;
12113 }
12114 continue;
12115 }
12116 #endif
12117 else {
12118 netperf_response.content.serv_errno = errno;
12119 send_response();
12120 exit(1);
12121 }
12122 }
12123 else {
12124 request_bytes_remaining -= request_bytes_recvd;
12125 temp_message_ptr += request_bytes_recvd;
12126 }
12127 }
12128
12129 recv_ring = recv_ring->next;
12130
12131 if (timed_out) {
12132 /* we hit the end of the test based on time - lets */
12133 /* bail out of here now... */
12134 fprintf(where,"yo5\n");
12135 fflush(where);
12136 break;
12137 }
12138
12139 /* Now, send the response to the remote */
12140 if((bytes_sent=send(s_data,
12141 send_ring->buffer_ptr,
12142 tcp_rr_request->response_size,
12143 0)) == SOCKET_ERROR) {
12144 if (SOCKET_EINTR(bytes_sent)) {
12145 /* the test timer has popped */
12146 timed_out = 1;
12147 fprintf(where,"yo6\n");
12148 fflush(where);
12149 break;
12150 }
12151 netperf_response.content.serv_errno = 992;
12152 send_response();
12153 exit(1);
12154 }
12155
12156 send_ring = send_ring->next;
12157
12158 trans_received++;
12159 if (trans_remaining) {
12160 trans_remaining--;
12161 }
12162 }
12163
12164
12165 /* The loop now exits due to timeout or transaction count being */
12166 /* reached */
12167
12168 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
12169
12170 stop_timer();
12171
12172 if (timed_out) {
12173 /* we ended the test by time, which was at least 2 seconds */
12174 /* longer than we wanted to run. so, we want to subtract */
12175 /* PAD_TIME from the elapsed_time. */
12176 elapsed_time -= PAD_TIME;
12177 }
12178
12179 /* send the results to the sender */
12180
12181 if (debug) {
12182 fprintf(where,
12183 "recv_tcp_nbrr: got %d transactions\n",
12184 trans_received);
12185 fflush(where);
12186 }
12187
12188 tcp_rr_results->bytes_received = (trans_received *
12189 (tcp_rr_request->request_size +
12190 tcp_rr_request->response_size));
12191 tcp_rr_results->trans_received = trans_received;
12192 tcp_rr_results->elapsed_time = elapsed_time;
12193 tcp_rr_results->cpu_method = cpu_method;
12194 tcp_rr_results->num_cpus = lib_num_loc_cpus;
12195 if (tcp_rr_request->measure_cpu) {
12196 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
12197 }
12198
12199 if (debug) {
12200 fprintf(where,
12201 "recv_tcp_nbrr: test complete, sending results.\n");
12202 fflush(where);
12203 }
12204
12205 /* we are done with the socket, free it */
12206 close(s_data);
12207
12208 send_response();
12209
12210 }
12211
12212 #endif /* DO_NBRR */
12213
12214
12215 /* this test is intended to test the performance of establishing a */
12216 /* connection, and then closing it again. this test is of somewhat */
12217 /* arcane interest since no packets are exchanged between the */
12218 /* user-space processes, but it will show the raw overhead of */
12219 /* establishing a TCP connection. that service demand could then be */
12220 /* compared with the sum of the service demands of a TCP_CRR and */
12221 /* TCP_RR test - presumeably, they would all relate */
12222
12223 void
send_tcp_cc(char remote_host[])12224 send_tcp_cc(char remote_host[])
12225 {
12226
12227 char *tput_title = "\
12228 Local /Remote\n\
12229 Socket Size Request Resp. Elapsed Trans.\n\
12230 Send Recv Size Size Time Rate \n\
12231 bytes Bytes bytes bytes secs. per sec \n\n";
12232
12233 char *tput_fmt_0 =
12234 "%7.2f\n";
12235
12236 char *tput_fmt_1_line_1 = "\
12237 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
12238 char *tput_fmt_1_line_2 = "\
12239 %-6d %-6d\n";
12240
12241 char *cpu_title = "\
12242 Local /Remote\n\
12243 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
12244 Send Recv Size Size Time Rate local remote local remote\n\
12245 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
12246
12247 char *cpu_fmt_0 =
12248 "%6.3f\n";
12249
12250 char *cpu_fmt_1_line_1 = "\
12251 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
12252
12253 char *cpu_fmt_1_line_2 = "\
12254 %-6d %-6d\n";
12255
12256 char *ksink_fmt = "\n\
12257 Alignment Offset\n\
12258 Local Remote Local Remote\n\
12259 Send Recv Send Recv\n\
12260 %5d %5d %5d %5d\n";
12261
12262
12263 int timed_out = 0;
12264 float elapsed_time;
12265
12266 char temp_message_ptr[1];
12267 int nummessages;
12268 SOCKET send_socket;
12269 int trans_remaining;
12270 double bytes_xferd;
12271 int rsp_bytes_left = 1;
12272 int rsp_bytes_recvd;
12273
12274 float local_cpu_utilization;
12275 float local_service_demand;
12276 float remote_cpu_utilization;
12277 float remote_service_demand;
12278 double thruput;
12279
12280 struct addrinfo *local_res;
12281 struct addrinfo *remote_res;
12282
12283 int myport;
12284 int ret;
12285
12286 struct tcp_cc_request_struct *tcp_cc_request;
12287 struct tcp_cc_response_struct *tcp_cc_response;
12288 struct tcp_cc_results_struct *tcp_cc_result;
12289
12290 tcp_cc_request =
12291 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
12292 tcp_cc_response =
12293 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
12294 tcp_cc_result =
12295 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
12296
12297
12298 #ifdef WANT_HISTOGRAM
12299 if (verbosity > 1) {
12300 time_hist = HIST_new();
12301 }
12302 #endif /* WANT_HISTOGRAM */
12303
12304 /* since we are now disconnected from the code that established the */
12305 /* control socket, and since we want to be able to use different */
12306 /* protocols and such, we are passed the name of the remote host and */
12307 /* must turn that into the test specific addressing information. */
12308
12309 complete_addrinfos(&remote_res,
12310 &local_res,
12311 remote_host,
12312 SOCK_STREAM,
12313 IPPROTO_TCP,
12314 0);
12315
12316 if ( print_headers ) {
12317 print_top_test_header("TCP Connect/Close TEST",local_res,remote_res);
12318 }
12319
12320 /* initialize a few counters */
12321
12322 nummessages = 0;
12323 bytes_xferd = 0.0;
12324 times_up = 0;
12325
12326 /* since there are no data buffers in this test, we need no send or */
12327 /* recv rings */
12328
12329 if (debug) {
12330 fprintf(where,"send_tcp_cc: send_socket obtained...\n");
12331 }
12332
12333 /* If the user has requested cpu utilization measurements, we must */
12334 /* calibrate the cpu(s). We will perform this task within the tests */
12335 /* themselves. If the user has specified the cpu rate, then */
12336 /* calibrate_local_cpu will return rather quickly as it will have */
12337 /* nothing to do. If local_cpu_rate is zero, then we will go through */
12338 /* all the "normal" calibration stuff and return the rate back.*/
12339
12340 if (local_cpu_usage) {
12341 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
12342 }
12343
12344 /* Tell the remote end to do a listen. The server alters the socket */
12345 /* paramters on the other side at this point, hence the reason for */
12346 /* all the values being passed in the setup message. If the user did */
12347 /* not specify any of the parameters, they will be passed as 0, which */
12348 /* will indicate to the remote that no changes beyond the system's */
12349 /* default should be used. Alignment is the exception, it will */
12350 /* default to 8, which will be no alignment alterations. */
12351
12352 netperf_request.content.request_type = DO_TCP_CC;
12353 tcp_cc_request->recv_buf_size = rsr_size_req;
12354 tcp_cc_request->send_buf_size = rss_size_req;
12355 tcp_cc_request->recv_alignment = remote_recv_align;
12356 tcp_cc_request->recv_offset = remote_recv_offset;
12357 tcp_cc_request->send_alignment = remote_send_align;
12358 tcp_cc_request->send_offset = remote_send_offset;
12359 tcp_cc_request->request_size = req_size;
12360 tcp_cc_request->response_size = rsp_size;
12361 tcp_cc_request->no_delay = rem_nodelay;
12362 tcp_cc_request->measure_cpu = remote_cpu_usage;
12363 tcp_cc_request->cpu_rate = remote_cpu_rate;
12364 tcp_cc_request->so_rcvavoid = rem_rcvavoid;
12365 tcp_cc_request->so_sndavoid = rem_sndavoid;
12366 if (test_time) {
12367 tcp_cc_request->test_length = test_time;
12368 }
12369 else {
12370 tcp_cc_request->test_length = test_trans * -1;
12371 }
12372 tcp_cc_request->port = atoi(remote_data_port);
12373 tcp_cc_request->ipfamily = af_to_nf(remote_res->ai_family);
12374
12375 if (debug > 1) {
12376 fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n");
12377 }
12378
12379 send_request();
12380
12381 /* The response from the remote will contain all of the relevant */
12382 /* socket parameters for this test type. We will put them back into */
12383 /* the variables here so they can be displayed if desired. The */
12384 /* remote will have calibrated CPU if necessary, and will have done */
12385 /* all the needed set-up we will have calibrated the cpu locally */
12386 /* before sending the request, and will grab the counter value right */
12387 /* after the connect returns. The remote will grab the counter right */
12388 /* after the accept call. This saves the hassle of extra messages */
12389 /* being sent for the TCP tests. */
12390
12391 recv_response();
12392
12393 if (!netperf_response.content.serv_errno) {
12394 rsr_size = tcp_cc_response->recv_buf_size;
12395 rss_size = tcp_cc_response->send_buf_size;
12396 rem_nodelay = tcp_cc_response->no_delay;
12397 remote_cpu_usage= tcp_cc_response->measure_cpu;
12398 remote_cpu_rate = tcp_cc_response->cpu_rate;
12399 /* make sure that port numbers are in network order */
12400 set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number);
12401
12402 if (debug) {
12403 fprintf(where,"remote listen done.\n");
12404 fprintf(where,"remote port is %d\n",get_port_number(remote_res));
12405 fflush(where);
12406 }
12407 }
12408 else {
12409 Set_errno(netperf_response.content.serv_errno);
12410 fprintf(where,
12411 "netperf: remote error %d",
12412 netperf_response.content.serv_errno);
12413 perror("");
12414 fflush(where);
12415 exit(1);
12416 }
12417
12418 #ifdef WANT_DEMO
12419 demo_rr_setup(100);
12420 #endif
12421
12422 /* pick a nice random spot between client_port_min and */
12423 /* client_port_max for our initial port number */
12424 srand(getpid());
12425 if (client_port_max - client_port_min) {
12426 myport = client_port_min +
12427 (rand() % (client_port_max - client_port_min));
12428 }
12429 else {
12430 myport = client_port_min;
12431 }
12432 /* there will be a ++ before the first call to bind, so subtract one */
12433 myport--;
12434
12435 /* Set-up the test end conditions. For a request/response test, they */
12436 /* can be either time or transaction based. */
12437
12438 if (test_time) {
12439 /* The user wanted to end the test after a period of time. */
12440 times_up = 0;
12441 trans_remaining = 0;
12442 start_timer(test_time);
12443 }
12444 else {
12445 /* The tester wanted to send a number of bytes. */
12446 trans_remaining = test_bytes;
12447 times_up = 1;
12448 }
12449
12450 /* The cpu_start routine will grab the current time and possibly */
12451 /* value of the idle counter for later use in measuring cpu */
12452 /* utilization and/or service demand and thruput. */
12453
12454 cpu_start(local_cpu_usage);
12455
12456 #ifdef WANT_DEMO
12457 if (demo_mode) {
12458 demo_first_timestamp();
12459 }
12460 #endif
12461
12462 /* We use an "OR" to control test execution. When the test is */
12463 /* controlled by time, the byte count check will always return false. */
12464 /* When the test is controlled by byte count, the time test will */
12465 /* always return false. When the test is finished, the whole */
12466 /* expression will go false and we will stop sending data. I think I */
12467 /* just arbitrarily decrement trans_remaining for the timed test, but */
12468 /* will not do that just yet... One other question is whether or not */
12469 /* the send buffer and the receive buffer should be the same buffer. */
12470
12471 while ((!times_up) || (trans_remaining > 0)) {
12472
12473 #ifdef WANT_HISTOGRAM
12474 if (verbosity > 1) {
12475 /* timestamp just before our call to create the socket, and then */
12476 /* again just after the receive raj 3/95 */
12477 HIST_timestamp(&time_one);
12478 }
12479 #endif /* WANT_HISTOGRAM */
12480
12481 /* set up the data socket */
12482 /* newport: is this label really required any longer? */
12483 /* pick a new port number */
12484 myport++;
12485
12486 /* wrap the port number when we get to client_port_max. NOTE, some */
12487 /* broken TCP's might treat the port number as a signed 16 bit */
12488 /* quantity. we aren't interested in testing such broken */
12489 /* implementations :) so we won't make sure that it is below 32767 */
12490 /* raj 8/94 */
12491 if (myport >= client_port_max) {
12492 myport = client_port_min;
12493 }
12494
12495 /* we do not want to use the port number that the server is */
12496 /* sitting at - this would cause us to fail in a loopback test. we */
12497 /* could just rely on the failure of the bind to get us past this, */
12498 /* but I'm guessing that in this one case at least, it is much */
12499 /* faster, given that we *know* that port number is already in use */
12500 /* (or rather would be in a loopback test) */
12501
12502 if (myport == get_port_number(remote_res)) myport++;
12503
12504 if (debug) {
12505 if ((nummessages % 100) == 0) {
12506 printf("port %d\n",myport);
12507 }
12508 }
12509 set_port_number(local_res, (unsigned short)myport);
12510 send_socket = create_data_socket(local_res);
12511
12512 if (send_socket == INVALID_SOCKET) {
12513 perror("netperf: send_tcp_cc: tcp stream data socket");
12514 exit(1);
12515 }
12516
12517 #ifdef WIN32
12518 /* this is used so the timer thread can close the socket out from */
12519 /* under us, which to date is the easiest/cleanest/least */
12520 /* Windows-specific way I can find to force the winsock calls to */
12521 /* return WSAEINTR with the test is over. anything that will run on */
12522 /* 95 and NT and is closer to what netperf expects from Unix signals */
12523 /* and such would be appreciated raj 1/96 */
12524 win_kludge_socket = send_socket;
12525 #endif /* WIN32 */
12526
12527 /* we used to have a call to bind() here, but that is being
12528 taken care of by create_data_socket(). raj 2005-02-08 */
12529
12530 /* Connect up to the remote port on the data socket */
12531 if ((ret = connect(send_socket,
12532 remote_res->ai_addr,
12533 remote_res->ai_addrlen)) == INVALID_SOCKET){
12534 if (SOCKET_EINTR(ret))
12535 {
12536 /* we hit the end of a */
12537 /* timed test. */
12538 timed_out = 1;
12539 break;
12540 }
12541 perror("netperf: data socket connect failed");
12542 printf("\tattempted to connect on socket %d to port %d",
12543 send_socket,
12544 get_port_number(remote_res));
12545 printf(" from port %u \n",get_port_number(local_res));
12546 exit(1);
12547 }
12548
12549 /* we hang in a recv() to get the remote's close indication */
12550
12551 rsp_bytes_recvd=recv(send_socket,
12552 temp_message_ptr,
12553 rsp_bytes_left,
12554 0);
12555
12556
12557 if (rsp_bytes_recvd == 0) {
12558 /* connection close, call close. we assume that the requisite */
12559 /* number of bytes have been received */
12560
12561 #ifdef WANT_HISTOGRAM
12562 if (verbosity > 1) {
12563 HIST_timestamp(&time_two);
12564 HIST_add(time_hist,delta_micro(&time_one,&time_two));
12565 }
12566 #endif /* WANT_HISTOGRAM */
12567
12568 #ifdef WANT_DEMO
12569 demo_rr_interval(1);
12570 #endif
12571
12572 nummessages++;
12573 if (trans_remaining) {
12574 trans_remaining--;
12575 }
12576
12577 if (debug > 3) {
12578 fprintf(where,
12579 "Transaction %d completed on local port %u\n",
12580 nummessages,
12581 get_port_number(local_res));
12582 fflush(where);
12583 }
12584
12585 close(send_socket);
12586
12587 }
12588 else {
12589 /* it was less than zero - an error occured */
12590 if (SOCKET_EINTR(rsp_bytes_recvd))
12591 {
12592 /* We hit the end of a timed test. */
12593 timed_out = 1;
12594 break;
12595 }
12596 perror("send_tcp_cc: data recv error");
12597 exit(1);
12598 }
12599
12600 }
12601
12602
12603 /* this call will always give us the elapsed time for the test, and */
12604 /* will also store-away the necessaries for cpu utilization */
12605
12606 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
12607 /* how long did we really run? */
12608
12609 /* Get the statistics from the remote end. The remote will have */
12610 /* calculated service demand and all those interesting things. If it */
12611 /* wasn't supposed to care, it will return obvious values. */
12612
12613 recv_response();
12614 if (!netperf_response.content.serv_errno) {
12615 if (debug)
12616 fprintf(where,"remote results obtained\n");
12617 }
12618 else {
12619 Set_errno(netperf_response.content.serv_errno);
12620 fprintf(where,
12621 "netperf: remote error %d",
12622 netperf_response.content.serv_errno);
12623 perror("");
12624 fflush(where);
12625
12626 exit(1);
12627 }
12628
12629 /* We now calculate what our thruput was for the test. In the future, */
12630 /* we may want to include a calculation of the thruput measured by */
12631 /* the remote, but it should be the case that for a TCP stream test, */
12632 /* that the two numbers should be *very* close... We calculate */
12633 /* bytes_sent regardless of the way the test length was controlled. */
12634 /* If it was time, we needed to, and if it was by bytes, the user may */
12635 /* have specified a number of bytes that wasn't a multiple of the */
12636 /* send_size, so we really didn't send what he asked for ;-) We use */
12637 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
12638 /* 1024. A future enhancement *might* be to choose from a couple of */
12639 /* unit selections. */
12640
12641 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
12642 thruput = calc_thruput(bytes_xferd);
12643
12644 if (local_cpu_usage || remote_cpu_usage) {
12645 /* We must now do a little math for service demand and cpu */
12646 /* utilization for the system(s) */
12647 /* Of course, some of the information might be bogus because */
12648 /* there was no idle counter in the kernel(s). We need to make */
12649 /* a note of this for the user's benefit...*/
12650 if (local_cpu_usage) {
12651 if (local_cpu_rate == 0.0) {
12652 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
12653 fprintf(where,"Local CPU usage numbers based on process information only!\n");
12654 fflush(where);
12655 }
12656 local_cpu_utilization = calc_cpu_util(0.0);
12657 /* since calc_service demand is doing ms/Kunit we will */
12658 /* multiply the number of transaction by 1024 to get */
12659 /* "good" numbers */
12660 local_service_demand = calc_service_demand((double) nummessages*1024,
12661 0.0,
12662 0.0,
12663 0);
12664 }
12665 else {
12666 local_cpu_utilization = (float) -1.0;
12667 local_service_demand = (float) -1.0;
12668 }
12669
12670 if (remote_cpu_usage) {
12671 if (remote_cpu_rate == 0.0) {
12672 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
12673 fprintf(where,"Remote CPU usage numbers based on process information only!\n");
12674 fflush(where);
12675 }
12676 remote_cpu_utilization = tcp_cc_result->cpu_util;
12677 /* since calc_service demand is doing ms/Kunit we will */
12678 /* multiply the number of transaction by 1024 to get */
12679 /* "good" numbers */
12680 remote_service_demand = calc_service_demand((double) nummessages*1024,
12681 0.0,
12682 remote_cpu_utilization,
12683 tcp_cc_result->num_cpus);
12684 }
12685 else {
12686 remote_cpu_utilization = (float) -1.0;
12687 remote_service_demand = (float) -1.0;
12688 }
12689
12690 /* We are now ready to print all the information. If the user */
12691 /* has specified zero-level verbosity, we will just print the */
12692 /* local service demand, or the remote service demand. If the */
12693 /* user has requested verbosity level 1, he will get the basic */
12694 /* "streamperf" numbers. If the user has specified a verbosity */
12695 /* of greater than 1, we will display a veritable plethora of */
12696 /* background information from outside of this block as it it */
12697 /* not cpu_measurement specific... */
12698
12699 switch (verbosity) {
12700 case 0:
12701 if (local_cpu_usage) {
12702 fprintf(where,
12703 cpu_fmt_0,
12704 local_service_demand);
12705 }
12706 else {
12707 fprintf(where,
12708 cpu_fmt_0,
12709 remote_service_demand);
12710 }
12711 break;
12712 case 1:
12713 case 2:
12714
12715 if (print_headers) {
12716 fprintf(where,
12717 cpu_title,
12718 local_cpu_method,
12719 remote_cpu_method);
12720 }
12721
12722 fprintf(where,
12723 cpu_fmt_1_line_1, /* the format string */
12724 lss_size, /* local sendbuf size */
12725 lsr_size,
12726 req_size, /* how large were the requests */
12727 rsp_size, /* guess */
12728 elapsed_time, /* how long was the test */
12729 nummessages/elapsed_time,
12730 local_cpu_utilization, /* local cpu */
12731 remote_cpu_utilization, /* remote cpu */
12732 local_service_demand, /* local service demand */
12733 remote_service_demand); /* remote service demand */
12734 fprintf(where,
12735 cpu_fmt_1_line_2,
12736 rss_size,
12737 rsr_size);
12738 break;
12739 }
12740 }
12741 else {
12742 /* The tester did not wish to measure service demand. */
12743 switch (verbosity) {
12744 case 0:
12745 fprintf(where,
12746 tput_fmt_0,
12747 nummessages/elapsed_time);
12748 break;
12749 case 1:
12750 case 2:
12751 if (print_headers) {
12752 fprintf(where,tput_title,format_units());
12753 }
12754
12755 fprintf(where,
12756 tput_fmt_1_line_1, /* the format string */
12757 lss_size,
12758 lsr_size,
12759 req_size, /* how large were the requests */
12760 rsp_size, /* how large were the responses */
12761 elapsed_time, /* how long did it take */
12762 nummessages/elapsed_time);
12763 fprintf(where,
12764 tput_fmt_1_line_2,
12765 rss_size, /* remote recvbuf size */
12766 rsr_size);
12767
12768 break;
12769 }
12770 }
12771
12772 /* it would be a good thing to include information about some of the */
12773 /* other parameters that may have been set for this test, but at the */
12774 /* moment, I do not wish to figure-out all the formatting, so I will */
12775 /* just put this comment here to help remind me that it is something */
12776 /* that should be done at a later time. */
12777
12778 if (verbosity > 1) {
12779 /* The user wanted to know it all, so we will give it to him. */
12780 /* This information will include as much as we can find about */
12781 /* TCP statistics, the alignments of the sends and receives */
12782 /* and all that sort of rot... */
12783
12784 fprintf(where,
12785 ksink_fmt,
12786 local_send_align,
12787 remote_recv_offset,
12788 local_send_offset,
12789 remote_recv_offset);
12790
12791 #ifdef WANT_HISTOGRAM
12792 fprintf(where,"\nHistogram of request/response times\n");
12793 fflush(where);
12794 HIST_report(time_hist);
12795 #endif /* WANT_HISTOGRAM */
12796
12797 }
12798
12799 }
12800
12801
12802 void
recv_tcp_cc()12803 recv_tcp_cc()
12804 {
12805
12806 char *message;
12807
12808 struct addrinfo *local_res;
12809 char local_name[BUFSIZ];
12810 char port_buffer[PORTBUFSIZE];
12811
12812 struct sockaddr_storage myaddr_in, peeraddr_in;
12813 SOCKET s_listen,s_data;
12814 netperf_socklen_t addrlen;
12815 char *recv_message_ptr;
12816 char *send_message_ptr;
12817 int trans_received;
12818 int trans_remaining;
12819 int timed_out = 0;
12820 float elapsed_time;
12821
12822 struct tcp_cc_request_struct *tcp_cc_request;
12823 struct tcp_cc_response_struct *tcp_cc_response;
12824 struct tcp_cc_results_struct *tcp_cc_results;
12825
12826 tcp_cc_request =
12827 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
12828 tcp_cc_response =
12829 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
12830 tcp_cc_results =
12831 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
12832
12833 if (debug) {
12834 fprintf(where,"netserver: recv_tcp_cc: entered...\n");
12835 fflush(where);
12836 }
12837
12838 /* We want to set-up the listen socket with all the desired */
12839 /* parameters and then let the initiator know that all is ready. If */
12840 /* socket size defaults are to be used, then the initiator will have */
12841 /* sent us 0's. If the socket sizes cannot be changed, then we will */
12842 /* send-back what they are. If that information cannot be determined, */
12843 /* then we send-back -1's for the sizes. If things go wrong for any */
12844 /* reason, we will drop back ten yards and punt. */
12845
12846 /* If anything goes wrong, we want the remote to know about it. It */
12847 /* would be best if the error that the remote reports to the user is */
12848 /* the actual error we encountered, rather than some bogus unexpected */
12849 /* response type message. */
12850
12851 if (debug) {
12852 fprintf(where,"recv_tcp_cc: setting the response type...\n");
12853 fflush(where);
12854 }
12855
12856 netperf_response.content.response_type = TCP_CC_RESPONSE;
12857
12858 if (debug) {
12859 fprintf(where,"recv_tcp_cc: the response type is set...\n");
12860 fflush(where);
12861 }
12862
12863 /* set-up the data buffer with the requested alignment and offset */
12864 message = (char *)malloc(DATABUFFERLEN);
12865 if (message == NULL) {
12866 printf("malloc(%d) failed!\n", DATABUFFERLEN);
12867 exit(1);
12868 }
12869
12870 /* We now alter the message_ptr variables to be at the desired */
12871 /* alignments with the desired offsets. */
12872
12873 if (debug) {
12874 fprintf(where,
12875 "recv_tcp_cc: requested recv alignment of %d offset %d\n",
12876 tcp_cc_request->recv_alignment,
12877 tcp_cc_request->recv_offset);
12878 fprintf(where,
12879 "recv_tcp_cc: requested send alignment of %d offset %d\n",
12880 tcp_cc_request->send_alignment,
12881 tcp_cc_request->send_offset);
12882 fflush(where);
12883 }
12884
12885 recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset);
12886
12887 send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset);
12888
12889 if (debug) {
12890 fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n");
12891 fflush(where);
12892 }
12893
12894 /* Grab a socket to listen on, and then listen on it. */
12895
12896 if (debug) {
12897 fprintf(where,"recv_tcp_cc: grabbing a socket...\n");
12898 fflush(where);
12899 }
12900
12901 /* create_data_socket expects to find some things in the global */
12902 /* variables, so set the globals based on the values in the request. */
12903 /* once the socket has been created, we will set the response values */
12904 /* based on the updated value of those globals. raj 7/94 */
12905 lss_size_req = tcp_cc_request->send_buf_size;
12906 lsr_size_req = tcp_cc_request->recv_buf_size;
12907 loc_nodelay = tcp_cc_request->no_delay;
12908 loc_rcvavoid = tcp_cc_request->so_rcvavoid;
12909 loc_sndavoid = tcp_cc_request->so_sndavoid;
12910
12911 set_hostname_and_port(local_name,
12912 port_buffer,
12913 nf_to_af(tcp_cc_request->ipfamily),
12914 tcp_cc_request->port);
12915
12916 local_res = complete_addrinfo(local_name,
12917 local_name,
12918 port_buffer,
12919 nf_to_af(tcp_cc_request->ipfamily),
12920 SOCK_STREAM,
12921 IPPROTO_TCP,
12922 0);
12923
12924 s_listen = create_data_socket(local_res);
12925
12926 if (s_listen == INVALID_SOCKET) {
12927 netperf_response.content.serv_errno = errno;
12928 send_response();
12929 if (debug) {
12930 fprintf(where,"could not create data socket\n");
12931 fflush(where);
12932 }
12933 exit(1);
12934 }
12935
12936 #ifdef WIN32
12937 /* The test timer can fire during operations on the listening socket,
12938 so to make the start_timer below work we have to move
12939 it to close s_listen while we are blocked on accept. */
12940 win_kludge_socket2 = s_listen;
12941 #endif
12942
12943
12944 /* Now, let's set-up the socket to listen for connections */
12945 if (listen(s_listen, 5) == SOCKET_ERROR) {
12946 netperf_response.content.serv_errno = errno;
12947 close(s_listen);
12948 send_response();
12949 if (debug) {
12950 fprintf(where,"could not listen\n");
12951 fflush(where);
12952 }
12953 exit(1);
12954 }
12955
12956 /* now get the port number assigned by the system */
12957 addrlen = sizeof(myaddr_in);
12958 if (getsockname(s_listen,
12959 (struct sockaddr *)&myaddr_in,
12960 &addrlen) == SOCKET_ERROR){
12961 netperf_response.content.serv_errno = errno;
12962 close(s_listen);
12963 send_response();
12964 if (debug) {
12965 fprintf(where,"could not geetsockname\n");
12966 fflush(where);
12967 }
12968 exit(1);
12969 }
12970
12971 /* Now myaddr_in contains the port and the internet address this is */
12972 /* returned to the sender also implicitly telling the sender that the */
12973 /* socket buffer sizing has been done. */
12974
12975 tcp_cc_response->data_port_number =
12976 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
12977 if (debug) {
12978 fprintf(where,"telling the remote to call me at %d\n",
12979 tcp_cc_response->data_port_number);
12980 fflush(where);
12981 }
12982 netperf_response.content.serv_errno = 0;
12983
12984 /* But wait, there's more. If the initiator wanted cpu measurements, */
12985 /* then we must call the calibrate routine, which will return the max */
12986 /* rate back to the initiator. If the CPU was not to be measured, or */
12987 /* something went wrong with the calibration, we will return a 0.0 to */
12988 /* the initiator. */
12989
12990 tcp_cc_response->cpu_rate = (float)0.0; /* assume no cpu */
12991 if (tcp_cc_request->measure_cpu) {
12992 tcp_cc_response->measure_cpu = 1;
12993 tcp_cc_response->cpu_rate =
12994 calibrate_local_cpu(tcp_cc_request->cpu_rate);
12995 }
12996
12997
12998
12999 /* before we send the response back to the initiator, pull some of */
13000 /* the socket parms from the globals */
13001 tcp_cc_response->send_buf_size = lss_size;
13002 tcp_cc_response->recv_buf_size = lsr_size;
13003 tcp_cc_response->no_delay = loc_nodelay;
13004 tcp_cc_response->so_rcvavoid = loc_rcvavoid;
13005 tcp_cc_response->so_sndavoid = loc_sndavoid;
13006
13007 send_response();
13008
13009 addrlen = sizeof(peeraddr_in);
13010
13011 /* Now it's time to start receiving data on the connection. We will */
13012 /* first grab the apropriate counters and then start grabbing. */
13013
13014 cpu_start(tcp_cc_request->measure_cpu);
13015
13016 /* The loop will exit when the sender does a shutdown, which will */
13017 /* return a length of zero */
13018
13019 if (tcp_cc_request->test_length > 0) {
13020 times_up = 0;
13021 trans_remaining = 0;
13022 start_timer(tcp_cc_request->test_length + PAD_TIME);
13023 }
13024 else {
13025 times_up = 1;
13026 trans_remaining = tcp_cc_request->test_length * -1;
13027 }
13028
13029 trans_received = 0;
13030
13031 while ((!times_up) || (trans_remaining > 0)) {
13032 #ifdef WIN32
13033 /* The test timer will probably fire during this accept,
13034 so to make the start_timer above work we have to move
13035 it to close s_listen while we are blocked on accept. */
13036 win_kludge_socket = s_listen;
13037 #endif
13038 /* accept a connection from the remote */
13039 if ((s_data=accept(s_listen,
13040 (struct sockaddr *)&peeraddr_in,
13041 &addrlen)) == INVALID_SOCKET) {
13042 if (errno == EINTR) {
13043 /* the timer popped */
13044 timed_out = 1;
13045 break;
13046 }
13047 fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno);
13048 fflush(where);
13049 close(s_listen);
13050
13051 exit(1);
13052 }
13053
13054 #ifdef KLUDGE_SOCKET_OPTIONS
13055 /* this is for those systems which *INCORRECTLY* fail to pass */
13056 /* attributes across an accept() call. Including this goes against */
13057 /* my better judgement :( raj 11/95 */
13058
13059 kludge_socket_options(s_data);
13060
13061 #endif /* KLUDGE_SOCKET_OPTIONS */
13062
13063 #ifdef WIN32
13064 /* this is used so the timer thread can close the socket out from */
13065 /* under us, which to date is the easiest/cleanest/least */
13066 /* Windows-specific way I can find to force the winsock calls to */
13067 /* return WSAEINTR with the test is over. anything that will run on */
13068 /* 95 and NT and is closer to what netperf expects from Unix signals */
13069 /* and such would be appreciated raj 1/96 */
13070 win_kludge_socket = s_data;
13071 #endif /* WIN32 */
13072
13073 if (debug) {
13074 fprintf(where,"recv_tcp_cc: accepted data connection.\n");
13075 fflush(where);
13076 }
13077
13078
13079 /* close the connection. the server will likely do a graceful */
13080 /* close of the connection, insuring that all data has arrived at */
13081 /* the client. for this it will call shutdown(), and then recv() and */
13082 /* then close(). I'm reasonably confident that this is the */
13083 /* appropriate sequence of calls - I would like to hear of */
13084 /* examples in web servers to the contrary. raj 10/95*/
13085 close(s_data);
13086
13087 trans_received++;
13088 if (trans_remaining) {
13089 trans_remaining--;
13090 }
13091
13092 if (debug) {
13093 fprintf(where,
13094 "recv_tcp_cc: Transaction %d complete\n",
13095 trans_received);
13096 fflush(where);
13097 }
13098
13099 }
13100
13101
13102 /* The loop now exits due to timeout or transaction count being */
13103 /* reached */
13104
13105 cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time);
13106
13107 if (timed_out) {
13108 /* we ended the test by time, which was at least 2 seconds */
13109 /* longer than we wanted to run. so, we want to subtract */
13110 /* PAD_TIME from the elapsed_time. */
13111 elapsed_time -= PAD_TIME;
13112 }
13113 /* send the results to the sender */
13114
13115 if (debug) {
13116 fprintf(where,
13117 "recv_tcp_cc: got %d transactions\n",
13118 trans_received);
13119 fflush(where);
13120 }
13121
13122 tcp_cc_results->bytes_received = (trans_received *
13123 (tcp_cc_request->request_size +
13124 tcp_cc_request->response_size));
13125 tcp_cc_results->trans_received = trans_received;
13126 tcp_cc_results->elapsed_time = elapsed_time;
13127 tcp_cc_results->num_cpus = lib_num_loc_cpus;
13128 if (tcp_cc_request->measure_cpu) {
13129 tcp_cc_results->cpu_util = calc_cpu_util(elapsed_time);
13130 }
13131
13132 if (debug) {
13133 fprintf(where,
13134 "recv_tcp_cc: test complete, sending results.\n");
13135 fflush(where);
13136 }
13137
13138 send_response();
13139
13140 }
13141
13142 void
print_sockets_usage()13143 print_sockets_usage()
13144 {
13145
13146 fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout);
13147 exit(1);
13148
13149 }
13150
13151 void
scan_sockets_args(int argc,char * argv[])13152 scan_sockets_args(int argc, char *argv[])
13153
13154 {
13155
13156 #define SOCKETS_ARGS "aAb:CDnNhH:L:m:M:p:P:r:R:s:S:T:Vw:W:z46"
13157
13158 extern char *optarg; /* pointer to option string */
13159
13160 int c;
13161
13162 char
13163 arg1[BUFSIZ], /* argument holders */
13164 arg2[BUFSIZ];
13165
13166 if (debug) {
13167 int i;
13168 printf("%s called with the following argument vector\n",
13169 #if _MSC_VER <= 1200
13170 "scan_sockets_args");
13171 #else
13172 __func__);
13173 #endif
13174 for (i = 0; i< argc; i++) {
13175 printf("%s ",argv[i]);
13176 }
13177 printf("\n");
13178 }
13179
13180 strncpy(local_data_port,"0",sizeof(local_data_port));
13181 strncpy(remote_data_port,"0",sizeof(remote_data_port));
13182
13183 /* by default, only a UDP_STREAM test disallows routing, to cover
13184 the backsides of incompetent testers who have bogus setups */
13185 if (strcasecmp(test_name,"UDP_STREAM") == 0) {
13186 routing_allowed = 0;
13187 }
13188
13189 /* Go through all the command line arguments and break them */
13190 /* out. For those options that take two parms, specifying only */
13191 /* the first will set both to that value. Specifying only the */
13192 /* second will leave the first untouched. To change only the */
13193 /* first, use the form "first," (see the routine break_args.. */
13194
13195 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
13196 switch (c) {
13197 case '?':
13198 case '4':
13199 remote_data_family = AF_INET;
13200 local_data_family = AF_INET;
13201 break;
13202 case '6':
13203 #if defined(AF_INET6)
13204 remote_data_family = AF_INET6;
13205 local_data_family = AF_INET6;
13206 #else
13207 fprintf(stderr,
13208 "This netperf was not compiled on an IPv6 capable host!\n");
13209 fflush(stderr);
13210 exit(-1);
13211 #endif
13212 break;
13213 case 'h':
13214 print_sockets_usage();
13215 exit(1);
13216 case 'a':
13217 #ifdef HAVE_AIO
13218 loc_sndaio = 1;
13219 #else
13220 fprintf(stderr, "Asynchronous I/O not available on this platform\n");
13221 #endif
13222 break;
13223 case 'A':
13224 #ifdef HAVE_AIO
13225 rem_rcvaio = 1;
13226 #else
13227 fprintf(stderr, "Asynchronous I/O not available on this platform\n");
13228 #endif
13229 break;
13230 case 'b':
13231 #ifdef WANT_FIRST_BURST
13232 first_burst_size = atoi(optarg);
13233 #else /* WANT_FIRST_BURST */
13234 printf("Initial request burst functionality not compiled-in!\n");
13235 #endif /* WANT_FIRST_BURST */
13236 break;
13237 case 'C':
13238 #ifdef TCP_CORK
13239 /* set TCP_CORK */
13240 loc_tcpcork = 1;
13241 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */
13242 #else
13243 printf("WARNING: TCP_CORK not available on this platform!\n");
13244 #endif /* TCP_CORK */
13245 break;
13246 case 'D':
13247 /* set the TCP nodelay flag */
13248 loc_nodelay = 1;
13249 rem_nodelay = 1;
13250 break;
13251 case 'H':
13252 break_args_explicit(optarg,arg1,arg2);
13253 if (arg1[0]) {
13254 /* make sure we leave room for the NULL termination boys and
13255 girls. raj 2005-02-82 */
13256 remote_data_address = malloc(strlen(arg1)+1);
13257 strncpy(remote_data_address,arg1,strlen(arg1));
13258 }
13259 if (arg2[0])
13260 remote_data_family = parse_address_family(arg2);
13261 break;
13262 case 'L':
13263 break_args_explicit(optarg,arg1,arg2);
13264 if (arg1[0]) {
13265 /* make sure we leave room for the NULL termination boys and
13266 girls. raj 2005-02-82 */
13267 local_data_address = malloc(strlen(arg1)+1);
13268 strncpy(local_data_address,arg1,strlen(arg1));
13269 }
13270 if (arg2[0])
13271 local_data_family = parse_address_family(arg2);
13272 break;
13273 case 's':
13274 /* set local socket sizes */
13275 break_args(optarg,arg1,arg2);
13276 if (arg1[0])
13277 lss_size_req = convert(arg1);
13278 if (arg2[0])
13279 lsr_size_req = convert(arg2);
13280 break;
13281 case 'S':
13282 /* set remote socket sizes */
13283 break_args(optarg,arg1,arg2);
13284 if (arg1[0])
13285 rss_size_req = convert(arg1);
13286 if (arg2[0])
13287 rsr_size_req = convert(arg2);
13288 break;
13289 case 'r':
13290 /* set the request/response sizes */
13291 break_args(optarg,arg1,arg2);
13292 if (arg1[0])
13293 req_size = convert(arg1);
13294 if (arg2[0])
13295 rsp_size = convert(arg2);
13296 break;
13297 case 'R':
13298 /* enable/disable routing on the data connection*/
13299 routing_allowed = atoi(optarg);
13300 break;
13301 case 'm':
13302 /* set the send size */
13303 send_size = convert(optarg);
13304 break;
13305 case 'M':
13306 /* set the recv size */
13307 recv_size = convert(optarg);
13308 break;
13309 case 'n':
13310 /* set the local socket type*/
13311 local_connected = 1;
13312 break;
13313 case 'N':
13314 /* set the remote socket type*/
13315 remote_connected = 1;
13316 break;
13317 case 'p':
13318 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */
13319 /* tests. */
13320 break_args(optarg,arg1,arg2);
13321 if (arg1[0])
13322 client_port_min = atoi(arg1);
13323 if (arg2[0])
13324 client_port_max = atoi(arg2);
13325 break;
13326 case 'P':
13327 /* set the local and remote data port numbers for the tests to
13328 allow them to run through those blankety blank end-to-end
13329 breaking firewalls. raj 2004-06-15 */
13330 break_args(optarg,arg1,arg2);
13331 if (arg1[0])
13332 strncpy(local_data_port,arg1,sizeof(local_data_port));
13333 if (arg2[0])
13334 strncpy(remote_data_port,arg2,sizeof(remote_data_port));
13335 break;
13336 case 't':
13337 /* set the test name */
13338 strcpy(test_name,optarg);
13339 break;
13340 case 'W':
13341 /* set the "width" of the user space data */
13342 /* buffer. This will be the number of */
13343 /* send_size buffers malloc'd in the */
13344 /* *_STREAM test. It may be enhanced to set */
13345 /* both send and receive "widths" but for now */
13346 /* it is just the sending *_STREAM. */
13347 send_width = convert(optarg);
13348 break;
13349 case 'V' :
13350 /* we want to do copy avoidance and will set */
13351 /* it for everything, everywhere, if we really */
13352 /* can. of course, we don't know anything */
13353 /* about the remote... */
13354 #ifdef SO_SND_COPYAVOID
13355 loc_sndavoid = 1;
13356 #else
13357 loc_sndavoid = 0;
13358 printf("Local send copy avoidance not available.\n");
13359 #endif
13360 #ifdef SO_RCV_COPYAVOID
13361 loc_rcvavoid = 1;
13362 #else
13363 loc_rcvavoid = 0;
13364 printf("Local recv copy avoidance not available.\n");
13365 #endif
13366 rem_sndavoid = 1;
13367 rem_rcvavoid = 1;
13368 break;
13369 };
13370 }
13371
13372 #if defined(WANT_FIRST_BURST)
13373 #if defined(WANT_HISTOGRAM)
13374 /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user
13375 indeed wants a non-zero first burst size, and we would emit a
13376 histogram, then we should emit a warning that the two are not
13377 compatible. raj 2006-01-31 */
13378 if ((first_burst_size > 0) && (verbosity >= 2)) {
13379 fprintf(stderr,
13380 "WARNING! Histograms and first bursts are incompatible!\n");
13381 fflush(stderr);
13382 }
13383 #endif
13384 #endif
13385
13386 /* we do not want to make remote_data_address non-NULL because if
13387 the user has not specified a remote adata address, we want to
13388 take it from the hostname in the -H global option. raj
13389 2005-02-08 */
13390
13391 /* so, if there is to be no control connection, we want to have some
13392 different settings for a few things */
13393
13394 if (no_control) {
13395
13396 if (strcmp(remote_data_port,"0") == 0) {
13397 /* we need to select either the discard port, echo port or
13398 chargen port dedepending on the test name. raj 2007-02-08 */
13399 if (strstr(test_name,"STREAM") ||
13400 strstr(test_name,"SENDFILE")) {
13401 strncpy(remote_data_port,"discard",sizeof(remote_data_port));
13402 }
13403 else if (strstr(test_name,"RR")) {
13404 strncpy(remote_data_port,"echo",sizeof(remote_data_port));
13405 }
13406 else if (strstr(test_name,"MAERTS")) {
13407 strncpy(remote_data_port,"chargen",sizeof(remote_data_port));
13408 }
13409 else {
13410 printf("No default port known for the %s test, please set one yourself\n",test_name);
13411 exit(-1);
13412 }
13413 }
13414 remote_data_port[sizeof(remote_data_port) - 1] = '\0';
13415
13416 /* I go back and forth on whether these should become -1 or if
13417 they should become 0 for a no_control test. what do you think?
13418 raj 2006-02-08 */
13419
13420 rem_rcvavoid = -1;
13421 rem_sndavoid = -1;
13422 rss_size_req = -1;
13423 rsr_size_req = -1;
13424 rem_nodelay = -1;
13425
13426 if (strstr(test_name,"STREAM") ||
13427 strstr(test_name,"SENDFILE")) {
13428 recv_size = -1;
13429 }
13430 else if (strstr(test_name,"MAERTS")) {
13431 send_size = -1;
13432 }
13433 }
13434 }
13435