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
78 #include <fcntl.h>
79 #ifndef WIN32
80 #include <errno.h>
81 #include <signal.h>
82 #endif
83
84 #if TIME_WITH_SYS_TIME
85 # include <sys/time.h>
86 # include <time.h>
87 #else
88 # if HAVE_SYS_TIME_H
89 # include <sys/time.h>
90 # else
91 # include <time.h>
92 # endif
93 #endif
94
95 #ifdef NOSTDLIBH
96 #include <malloc.h>
97 #endif /* NOSTDLIBH */
98
99
100 #ifndef WIN32
101 #if !defined(__VMS)
102 #include <sys/ipc.h>
103 #endif /* !__VMS */
104 #include <sys/socket.h>
105 #include <netinet/in.h>
106 #include <netinet/tcp.h>
107
108 #ifdef HAVE_NETINET_SCTP_H
109 #include <netinet/sctp.h>
110 #endif
111
112 #include <arpa/inet.h>
113 #include <netdb.h>
114 #else /* WIN32 */
115 #include <process.h>
116 #define netperf_socklen_t socklen_t
117 #include <winsock2.h>
118 #include "missing\stdint.h"
119 /* while it is unlikely that anyone running Windows 2000 or NT 4 is
120 going to be trying to compile this, if they are they will want to
121 define DONT_IPV6 in the sources file */
122 #ifndef DONT_IPV6
123 #include <ws2tcpip.h>
124 #endif
125 #include <windows.h>
126
127 #define sleep(x) Sleep((x)*1000)
128
129 #define __func__ __FUNCTION__
130 #endif /* WIN32 */
131
132 /* We don't want to use bare constants in the shutdown() call. In the
133 extremely unlikely event that SHUT_WR isn't defined, we will define
134 it to the value we used to be passing to shutdown() anyway. raj
135 2007-02-08 */
136 #if !defined(SHUT_WR)
137 #define SHUT_WR 1
138 #endif
139
140 #if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO)
141 # include "missing/getaddrinfo.h"
142 #endif
143
144 #include "netlib.h"
145 #include "netsh.h"
146 #include "nettest_bsd.h"
147
148 #if defined(WANT_HISTOGRAM) || defined(WANT_DEMO)
149 #include "hist.h"
150 #endif /* WANT_HISTOGRAM */
151
152
153 /* make first_burst_size unconditional so we can use it easily enough
154 when calculating transaction latency for the TCP_RR test. raj
155 2007-06-08 however, change its default value so one can tell in
156 "omni" output whether or not WANT_BURST was enabled. raj
157 2008-01-28 */
158 #if defined(WANT_FIRST_BURST)
159 int first_burst_size=0;
160 #else
161 int first_burst_size=-1;
162 #endif
163
164 #if defined(HAVE_SENDFILE) && (defined(__linux) || defined(__sun))
165 #include <sys/sendfile.h>
166 #endif /* HAVE_SENDFILE && (__linux || __sun) */
167
168
169
170 /* these variables are specific to the BSD sockets tests, but can
171 * be used elsewhere if needed. They are externed through nettest_bsd.h
172 */
173
174 int
175 socket_type, /* used initially by the "omni" tests */
176 rss_size_req = -1, /* requested remote socket send buffer size */
177 rsr_size_req = -1, /* requested remote socket recv buffer size */
178 rss_size, /* initial remote socket send buffer size */
179 rsr_size, /* initial remote socket recv buffer size */
180 rss_size_end = -1, /* final remote socket send buffer size */
181 rsr_size_end = -1, /* final remote socket recv buffer size */
182 lss_size_req = -1, /* requested local socket send buffer size */
183 lsr_size_req = -1, /* requested local socket recv buffer size */
184 lss_size, /* local socket send buffer size */
185 lsr_size, /* local socket recv buffer size */
186 lss_size_end = -1, /* final local socket send buffer size */
187 lsr_size_end = -1, /* final local socket recv buffer size */
188 req_size = 1, /* request size */
189 rsp_size = 1, /* response size */
190 send_size, /* how big are individual sends */
191 recv_size, /* how big are individual receives */
192 transport_mss_req = -1; /* what maximum segment size is wanted */
193
194 static int confidence_iteration;
195 static char local_cpu_method;
196 static char remote_cpu_method;
197
198 /* these will control the width of port numbers we try to use in the */
199 /* TCP_CRR and/or TCP_TRR tests. raj 3/95 */
200 static int client_port_min = 5000;
201 static int client_port_max = 65535;
202
203 /* different options for the sockets */
204
205 int
206 loc_nodelay, /* don't/do use NODELAY locally */
207 rem_nodelay, /* don't/do use NODELAY remotely */
208 #ifdef TCP_CORK
209 loc_tcpcork=0, /* don't/do use TCP_CORK locally */
210 rem_tcpcork=0, /* don't/do use TCP_CORK remotely */
211 #else
212 loc_tcpcork=-1,
213 rem_tcpcork=-1,
214 #endif /* TCP_CORK */
215 loc_sndavoid, /* avoid send copies locally */
216 loc_rcvavoid, /* avoid recv copies locally */
217 rem_sndavoid, /* avoid send copies remotely */
218 rem_rcvavoid, /* avoid recv_copies remotely */
219 local_connected = 0, /* local socket type, connected/non-connected */
220 remote_connected = 0, /* remote socket type, connected/non-connected */
221 routing_allowed = 1; /* set/clear SO_DONTROUTE on data socket */
222
223 int multicast_ttl = -1; /* should we set the multicast TTL to a value? */
224
225 int want_keepalive = 0;
226
227 #ifdef WANT_HISTOGRAM
228 #ifdef HAVE_GETHRTIME
229 static hrtime_t time_one;
230 static hrtime_t time_two;
231 #elif HAVE_GET_HRT
232 #include "hrt.h"
233 static hrt_t time_one;
234 static hrt_t time_two;
235 #elif defined(WIN32)
236 static LARGE_INTEGER time_one;
237 static LARGE_INTEGER time_two;
238 #else
239 static struct timeval time_one;
240 static struct timeval time_two;
241 #endif /* HAVE_GETHRTIME */
242 static HIST time_hist;
243 #endif /* WANT_HISTOGRAM */
244
245 #ifdef WANT_INTERVALS
246 int interval_count;
247 #ifndef WANT_SPIN
248 #ifdef WIN32
249 #define INTERVALS_INIT() \
250 if (interval_burst) { \
251 /* zero means that we never pause, so we never should need the \
252 interval timer. we used to use it for demo mode, but we deal \
253 with that with a variant on watching the clock rather than \
254 waiting for a timer. raj 2006-02-06 */ \
255 start_itimer(interval_wate); \
256 } \
257 interval_count = interval_burst;
258 #else
259 sigset_t signal_set;
260 #define INTERVALS_INIT() \
261 if (interval_burst) { \
262 /* zero means that we never pause, so we never should need the \
263 interval timer. we used to use it for demo mode, but we deal \
264 with that with a variant on watching the clock rather than \
265 waiting for a timer. raj 2006-02-06 */ \
266 start_itimer(interval_wate); \
267 } \
268 interval_count = interval_burst; \
269 /* get the signal set for the call to sigsuspend */ \
270 if (sigprocmask(SIG_BLOCK, (sigset_t *)NULL, &signal_set) != 0) { \
271 fprintf(where, \
272 "%s: unable to get sigmask errno %d\n", \
273 __func__, \
274 errno); \
275 fflush(where); \
276 exit(1); \
277 }
278 #endif /* WIN32 */
279
280 #ifdef WIN32
281 #define INTERVALS_WAIT() \
282 /* in this case, the interval count is the count-down counter \
283 to decide to sleep for a little bit */ \
284 if ((interval_burst) && (--interval_count == 0)) { \
285 /* call WaitForSingleObject and wait for the interval timer to get us \
286 out */ \
287 if (debug > 1) { \
288 fprintf(where,"about to suspend\n"); \
289 fflush(where); \
290 } \
291 if (WaitForSingleObject(WinTimer, INFINITE) != WAIT_OBJECT_0) { \
292 fprintf(where, "WaitForSingleObject failed (%d)\n", GetLastError()); \
293 fflush(where); \
294 exit(1); \
295 } \
296 interval_count = interval_burst; \
297 }
298 #else
299 #define INTERVALS_WAIT() \
300 /* in this case, the interval count is the count-down couter \
301 to decide to sleep for a little bit */ \
302 if ((interval_burst) && (--interval_count == 0)) { \
303 /* call sigsuspend and wait for the interval timer to get us \
304 out */ \
305 if (debug > 1) { \
306 fprintf(where,"about to suspend\n"); \
307 fflush(where); \
308 } \
309 if (sigsuspend(&signal_set) == EFAULT) { \
310 fprintf(where, \
311 "%s: fault with sigsuspend.\n", \
312 __func__); \
313 fflush(where); \
314 exit(1); \
315 } \
316 interval_count = interval_burst; \
317 }
318 #endif /* WIN32 */
319 #else
320 /* first out timestamp */
321 #ifdef HAVE_GETHRTIME
322 static hrtime_t intvl_one;
323 static hrtime_t intvl_two;
324 static hrtime_t *intvl_one_ptr = &intvl_one;
325 static hrtime_t *intvl_two_ptr = &intvl_two;
326 static hrtime_t *temp_intvl_ptr = &intvl_one;
327 #elif defined(WIN32)
328 static LARGE_INTEGER intvl_one;
329 static LARGE_INTEGER intvl_two;
330 static LARGE_INTEGER *intvl_one_ptr = &intvl_one;
331 static LARGE_INTEGER *intvl_two_ptr = &intvl_two;
332 static LARGE_INTEGER *temp_intvl_ptr = &intvl_one;
333 #else
334 static struct timeval intvl_one;
335 static struct timeval intvl_two;
336 static struct timeval *intvl_one_ptr = &intvl_one;
337 static struct timeval *intvl_two_ptr = &intvl_two;
338 static struct timeval *temp_intvl_ptr = &intvl_one;
339 #endif
340
341 #define INTERVALS_INIT() \
342 if (interval_burst) { \
343 HIST_timestamp(intvl_one_ptr); \
344 } \
345 interval_count = interval_burst; \
346
347 #define INTERVALS_WAIT() \
348 /* in this case, the interval count is the count-down couter \
349 to decide to sleep for a little bit */ \
350 if ((interval_burst) && (--interval_count == 0)) { \
351 /* call sigsuspend and wait for the interval timer to get us \
352 out */ \
353 if (debug > 1) { \
354 fprintf(where,"about to spin suspend\n"); \
355 fflush(where); \
356 } \
357 HIST_timestamp(intvl_two_ptr); \
358 while(delta_micro(intvl_one_ptr,intvl_two_ptr) < interval_usecs) { \
359 HIST_timestamp(intvl_two_ptr); \
360 } \
361 temp_intvl_ptr = intvl_one_ptr; \
362 intvl_one_ptr = intvl_two_ptr; \
363 intvl_two_ptr = temp_intvl_ptr; \
364 interval_count = interval_burst; \
365 }
366 #endif
367 #endif
368
369
370 char sockets_usage[] = "\n\
371 Usage: netperf [global options] -- [test options] \n\
372 \n\
373 TCP/UDP BSD Sockets Test Options:\n\
374 -b number Send number requests at start of _RR tests\n\
375 -C Set TCP_CORK when available\n\
376 -D [L][,R] Set TCP_NODELAY locally and/or remotely (TCP_*)\n\
377 -h Display this text\n\
378 -H name,fam Use name (or IP) and family as target of data connection\n\
379 -L name,fam Use name (or IP) and family as source of data connection\n\
380 -m bytes Set the send size (TCP_STREAM, UDP_STREAM)\n\
381 -M bytes Set the recv size (TCP_STREAM, UDP_STREAM)\n\
382 -n Use the connected socket for UDP locally\n\
383 -N Use the connected socket for UDP remotely\n\
384 -p min[,max] Set the min/max port numbers for TCP_CRR, TCP_TRR\n\
385 -P local[,remote] Set the local/remote port for the data socket\n\
386 -r req,[rsp] Set request/response sizes (TCP_RR, UDP_RR)\n\
387 -s send[,recv] Set local socket send/recv buffer sizes\n\
388 -S send[,recv] Set remote socket send/recv buffer sizes\n\
389 -4 Use AF_INET (eg IPv4) on both ends of the data conn\n\
390 -6 Use AF_INET6 (eg IPv6) on both ends of the data conn\n\
391 \n\
392 For those options taking two parms, at least one must be specified;\n\
393 specifying one value without a comma will set both parms to that\n\
394 value, specifying a value with a leading comma will set just the second\n\
395 parm, a value with a trailing comma will set just the first. To set\n\
396 each parm to unique values, specify both and separate them with a\n\
397 comma.\n";
398
399
400
401 /* these routines convert between the AF address space and the NF
402 address space since the numeric values of AF_mumble are not the
403 same across the platforms. raj 2005-02-08 */
404
405 int
nf_to_af(int nf)406 nf_to_af(int nf) {
407 switch(nf) {
408 case NF_INET:
409 return AF_INET;
410 case NF_UNSPEC:
411 return AF_UNSPEC;
412 case NF_INET6:
413 #if defined(AF_INET6)
414 return AF_INET6;
415 #else
416 return AF_UNSPEC;
417 #endif
418 case NF_RDS:
419 #if defined(AF_RDS)
420 return AF_RDS;
421 #else
422 return AF_UNSPEC;
423 #endif
424 default:
425 return AF_UNSPEC;
426 }
427 }
428
429 int
af_to_nf(int af)430 af_to_nf(int af) {
431
432 switch(af) {
433 case AF_INET:
434 return NF_INET;
435 case AF_UNSPEC:
436 return NF_UNSPEC;
437 #if defined(AF_INET6)
438 case AF_INET6:
439 return NF_INET6;
440 #endif
441 #if defined(AF_RDS)
442 case AF_RDS:
443 return NF_RDS;
444 #endif
445 default:
446 return NF_UNSPEC;
447 }
448 }
449
450
451 /* these routines will convert between the hosts' socket types and
452 those netperf uses. we need this because different platforms can
453 have different values for SOCK_STREAM, SOCK_DGRAM and the
454 like... */
455
456 int
nst_to_hst(int nst)457 nst_to_hst(int nst) {
458 switch(nst) {
459 #ifdef SOCK_STREAM
460 case NST_STREAM:
461 return SOCK_STREAM;
462 break; /* ok, this may not be necessary :) */
463 #endif
464 #ifdef SOCK_DGRAM
465 case NST_DGRAM:
466 return SOCK_DGRAM;
467 break;
468 #endif
469 #ifdef SOCK_DCCP
470 case NST_DCCP:
471 return SOCK_DCCP;
472 break;
473 #endif
474 #ifdef SOCK_SEQPACKET
475 case NST_SEQPACKET:
476 return NST_SEQPACKET;
477 #endif
478 default:
479 return -1;
480 }
481 }
482
483 int
hst_to_nst(int hst)484 hst_to_nst(int hst) {
485
486 switch(hst) {
487 #ifdef SOCK_STREAM
488 case SOCK_STREAM:
489 return NST_STREAM;
490 break;
491 #endif
492 #ifdef SOCK_DGRAM
493 case SOCK_DGRAM:
494 return NST_DGRAM;
495 break;
496 #endif
497 #ifdef SOCK_DCCP
498 case SOCK_DCCP:
499 return NST_DCCP;
500 break;
501 #endif
502 #ifdef SOCK_SEQPACKET
503 case SOCK_SEQPACKET:
504 return NST_SEQPACKET;
505 #endif
506 default:
507 return NST_UNKN;
508 }
509 }
510 char *
hst_to_str(int hst)511 hst_to_str(int hst) {
512
513 switch(hst) {
514 #ifdef SOCK_STREAM
515 case SOCK_STREAM:
516 return "Stream";
517 break;
518 #endif
519 #ifdef SOCK_DGRAM
520 case SOCK_DGRAM:
521 return "Datagram";
522 break;
523 #endif
524 #ifdef SOCK_DCCP
525 case SOCK_DCCP:
526 return "DCCP";
527 break;
528 #endif
529 #ifdef SOCK_SEQPACKET
530 case SOCK_SEQPACKET:
531 return "Seqpacket";
532 #endif
533 default:
534 return "Unknown";
535 }
536 }
537
538 char *
protocol_to_str(int protocol)539 protocol_to_str(int protocol) {
540 switch(protocol) {
541 /* ass-u-me that everyone has IPPROTO_TCP and IPPROTO_UDP */
542 case IPPROTO_TCP:
543 return "TCP";
544 case IPPROTO_UDP:
545 return "UDP";
546 /* but do not assume that everyone has the others */
547 #ifdef IPPROTO_UDPLITE
548 case IPPROTO_UDPLITE:
549 return "UDPLite";
550 #endif
551 #ifdef IPPROTO_SCTP
552 case IPPROTO_SCTP:
553 return "SCTP";
554 #endif
555 #ifdef IPPROTO_DCCP
556 case IPPROTO_DCCP:
557 return "DCCP";
558 #endif
559 #ifdef IPPROTO_SDP
560 case IPPROTO_SDP:
561 return "SDP";
562 #endif
563 #ifdef IPPROTO_IP
564 case IPPROTO_IP:
565 return "IP Default";
566 #endif
567 default:
568 return "Unknown Protocol";
569 }
570 }
571
572
573 /* This routine is intended to retrieve interesting aspects of tcp */
574 /* for the data connection. at first, it attempts to retrieve the */
575 /* maximum segment size. later, it might be modified to retrieve */
576 /* other information, but it must be information that can be */
577 /* retrieved quickly as it is called during the timing of the test. */
578 /* for that reason, a second routine may be created that can be */
579 /* called outside of the timing loop */
580 static
581 void
get_tcp_info(SOCKET socket,int * mss)582 get_tcp_info(SOCKET socket, int *mss)
583 {
584
585 #ifdef TCP_MAXSEG
586 netperf_socklen_t sock_opt_len;
587
588 sock_opt_len = sizeof(int);
589 if (getsockopt(socket,
590 getprotobyname("tcp")->p_proto,
591 TCP_MAXSEG,
592 (char *)mss,
593 &sock_opt_len) == SOCKET_ERROR) {
594 fprintf(where,
595 "netperf: get_tcp_info: getsockopt TCP_MAXSEG: errno %d\n",
596 errno);
597 fflush(where);
598 *mss = -1;
599 }
600 #else
601 *mss = -1;
602 #endif /* TCP_MAXSEG */
603 }
604
605 static
606 void
set_tcp_mss(SOCKET socket,int mss)607 set_tcp_mss(SOCKET socket, int mss) {
608 #ifdef TCP_MAXSEG
609 netperf_socklen_t sock_opt_len;
610
611 sock_opt_len = sizeof(int);
612 if ((setsockopt(socket,
613 getprotobyname("tcp")->p_proto,
614 TCP_MAXSEG,
615 (const char *)&mss,
616 sock_opt_len) == SOCKET_ERROR) && (debug)) {
617 fprintf(where,
618 "netperf: %s: setsockopt TCP_MAXSEG: %s (errno %d)\n",
619 __FUNCTION__,
620 strerror(errno),
621 errno);
622 fflush(where);
623 }
624 #else
625 if (debug) {
626 fprintf(where,
627 "netperf: %s platform does not know how to set TCP segment size\n",
628 __FUNCTION__);
629 fflush(where);
630 }
631
632 #endif /* TCP_MAXSEG */
633 }
634
635
636
637 /* return a pointer to a completed addrinfo chain - prefer
638 data_address to controlhost and utilize the specified address
639 family */
640
641 struct addrinfo *
complete_addrinfo(char * controlhost,char * data_address,char * port,int family,int type,int protocol,int flags)642 complete_addrinfo(char *controlhost, char *data_address, char *port, int family, int type, int protocol, int flags)
643 {
644 struct addrinfo hints;
645 struct addrinfo *res;
646 struct addrinfo *temp_res;
647
648 #define CHANGED_SOCK_TYPE 0x1
649 #define CHANGED_PROTOCOL 0x2
650 #define CHANGED_SCTP 0x4
651 #define CHANGED_DCCP 0x8
652 #define CHANGED_DCCP_SOCK 0x10
653
654 int change_info = 0;
655 static int change_warning_displayed = 0;
656
657 int count = 0;
658 int error = 0;
659
660 char *hostname;
661
662 /* take data-address over controlhost */
663 if (data_address)
664 hostname = data_address;
665 else
666 hostname = controlhost;
667
668 if (debug) {
669 fprintf(where,
670 "complete_addrinfo using hostname %s port %s family %s type %s prot %s flags 0x%x\n",
671 hostname,
672 port,
673 inet_ftos(family),
674 inet_ttos(type),
675 inet_ptos(protocol),
676 flags);
677 fflush(where);
678 }
679
680 memset(&hints, 0, sizeof(hints));
681 hints.ai_family = family;
682 hints.ai_socktype = type;
683 hints.ai_protocol = protocol;
684 hints.ai_flags = flags|AI_CANONNAME|AI_ADDRCONFIG;
685
686 count = 0;
687 do {
688 error = getaddrinfo((char *)hostname,
689 (char *)port,
690 &hints,
691 &res);
692 count += 1;
693 if (error == EAI_AGAIN) {
694 if (debug) {
695 fprintf(where,"Sleeping on getaddrinfo EAI_AGAIN\n");
696 fflush(where);
697 }
698 sleep(1);
699 }
700 /* while you see this kludge first, it is actually the second, the
701 first being the one for Solaris below. The need for this kludge
702 came after implementing the Solaris broken getaddrinfo kludge -
703 now we see a kludge in Linux getaddrinfo where if it is given
704 SOCK_STREAM and IPPROTO_SCTP it barfs with a -7
705 EAI_SOCKTYPE. so, we check if the error was EAI_SOCKTYPE and if
706 we were asking for IPPROTO_SCTP and if so, kludge, again... raj
707 200?-10-13 and of course, requiring the kludge for SCTP, it is
708 no surprise that linux needs a kludge for DCCP...actually not
709 only does it need the ai_protocol kludge, it needs an
710 ai_socktype kludge too... sigh raj 2008-02-01 */
711 #if defined(IPPROTO_SCTP) || defined (IPPROTO_DCCP)
712 if (EAI_SOCKTYPE == error
713 #ifdef EAI_BADHINTS
714 || EAI_BADHINTS == error
715 #endif
716 ) {
717 /* we ass-u-me this is the Linux getaddrinfo bug, clear the
718 hints.ai_protocol field, and set some state "remembering"
719 that we did this so the code for the Solaris kludge can do
720 the fix-up for us. also flip error over to EAI_AGAIN and
721 make sure we don't "count" this time around the loop. */
722 #if defined(IPPROTO_DCCP) && defined(SOCK_DCCP)
723 /* only tweak on this one the second time around, after we've
724 kludged the ai_protocol field */
725 if ((hints.ai_socktype == SOCK_DCCP) &&
726 (hints.ai_protocol == 0)) {
727 change_info |= CHANGED_DCCP_SOCK;
728 hints.ai_socktype = 0;
729 /* we need to give it some sort of IPPROTO or it gets unhappy,
730 so for now, pick one from deep within the colon and use
731 IPPROTO_TCP */
732 hints.ai_protocol = IPPROTO_TCP;
733 }
734
735 if (hints.ai_protocol == IPPROTO_DCCP) {
736 change_info |= CHANGED_DCCP;
737 hints.ai_protocol = 0;
738 }
739
740 #endif
741 #if defined(IPPROTO_SCTP)
742 if (hints.ai_protocol == IPPROTO_SCTP) {
743 change_info |= CHANGED_SCTP;
744 hints.ai_protocol = 0;
745 }
746 #endif
747
748 error = EAI_AGAIN;
749 count -= 1;
750 }
751 #endif
752 } while ((error == EAI_AGAIN) && (count <= 5));
753
754 if (error) {
755 fprintf(where,
756 "complete_addrinfo: could not resolve '%s' port '%s' af %d"
757 "\n\tgetaddrinfo returned %d %s\n",
758 hostname,
759 port,
760 family,
761 error,
762 gai_strerror(error));
763 fflush(where);
764 exit(-1);
765 }
766
767 /* there exists at least one platform - Solaris 10 - that does not
768 seem to completely honor the ai_protocol and/or ai_socktype one
769 sets in the hints parm to the getaddrinfo call. so, we need to
770 walk the list of entries returned and if either of those do not
771 match what we asked for, we need to go ahead and set them
772 "correctly" this is based in part on some earlier SCTP-only code
773 from previous revisions. raj 2006-10-09 */
774
775 temp_res = res;
776
777 while (temp_res) {
778
779 if ((type) &&
780 (temp_res->ai_socktype != type)) {
781 change_info |= CHANGED_SOCK_TYPE;
782 if (debug) {
783 fprintf(where,
784 "WARNING! Changed bogus getaddrinfo socket type %d to %d\n",
785 temp_res->ai_socktype,
786 type);
787 fflush(where);
788 }
789 temp_res->ai_socktype = type;
790 }
791
792 if ((protocol) &&
793 (temp_res->ai_protocol != protocol)) {
794 change_info |= CHANGED_PROTOCOL;
795 if (debug) {
796 fprintf(where,
797 "WARNING! Changed bogus getaddrinfo protocol %d to %d\n",
798 temp_res->ai_protocol,
799 protocol);
800 fflush(where);
801 }
802 temp_res->ai_protocol = protocol;
803 }
804 temp_res = temp_res->ai_next;
805 }
806
807 if ((change_info & CHANGED_SOCK_TYPE) &&
808 !(change_warning_displayed & CHANGED_SOCK_TYPE)) {
809 change_warning_displayed |= CHANGED_SOCK_TYPE;
810 fprintf(where,
811 "WARNING! getaddrinfo returned a socket type which did not\n"
812 "match the requested type. Please contact your vendor for\n"
813 "a fix to this bug in getaddrinfo()\n");
814 fflush(where);
815 }
816
817 /* if we dropped the protocol hint, it would be for a protocol that
818 getaddrinfo() wasn't supporting yet, not for the bug that it took
819 our hint and still returned zero. raj 2006-10-16 */
820 /* as there is now an open bug against (Open)Solaris (id 6847733) on
821 this behaviour we will only emit this warning if debug is set
822 under Solaris and will continue to emit it under any circumstance
823 on other platforms should it arise. raj 2009-06-03 */
824 /* since it has now been two years since that bug was filed, it
825 should be resolved by now, so the "out" given to Sun should no
826 longer be necessary. either folks are running with the fix or
827 they need to get the fix. raj 2011-07-06 */
828 if ((change_info & CHANGED_PROTOCOL) &&
829 !(change_warning_displayed & CHANGED_PROTOCOL) &&
830 (hints.ai_protocol != 0)) {
831 change_warning_displayed |= CHANGED_PROTOCOL;
832 fprintf(where,
833 "WARNING! getaddrinfo returned a protocol other than the\n"
834 "requested protocol. Please contact your vendor for\n"
835 "a fix to this bug in getaddrinfo()\n");
836 fflush(where);
837 }
838
839 if ((change_info & CHANGED_SCTP) &&
840 !(change_warning_displayed & CHANGED_SCTP)) {
841 change_warning_displayed |= CHANGED_SCTP;
842 fprintf(where,
843 "WARNING! getaddrinfo on this platform does not accept IPPROTO_SCTP!\n"
844 "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
845 fflush(where);
846 }
847
848 if ((change_info & CHANGED_DCCP) &&
849 !(change_warning_displayed & CHANGED_DCCP)) {
850 change_warning_displayed |= CHANGED_DCCP;
851 fprintf(where,
852 "WARNING! getaddrinfo on this platform does not accept IPPROTO_DCCP!\n"
853 "Please contact your vendor for a fix to this bug in getaddrinfo().\n");
854 fflush(where);
855 }
856
857
858 if (debug) {
859 dump_addrinfo(where, res, hostname, port, family);
860 }
861
862 return(res);
863 }
864
865 void
complete_addrinfos(struct addrinfo ** remote,struct addrinfo ** local,char remote_host[],int type,int protocol,int flags)866 complete_addrinfos(struct addrinfo **remote,struct addrinfo **local, char remote_host[], int type, int protocol, int flags) {
867
868 if (remote_data_family == AF_UNSPEC) {
869 remote_data_family = control_family;
870 }
871
872 *remote = complete_addrinfo(remote_host,
873 remote_data_address,
874 remote_data_port,
875 remote_data_family,
876 type,
877 protocol,
878 flags);
879
880 /* OK, if the user has not specified a local data endpoint address
881 (test-specific -L), pick the local data endpoint address based on
882 the remote data family info (test-specific -H or -4 or -6
883 option). if the user has not specified remote data addressing
884 info (test-specific -H, -4 -6) pick something based on the local
885 control connection address (ie the global -L option). */
886
887 if (NULL == local_data_address) {
888 local_data_address = malloc(HOSTNAMESIZE);
889 if (NULL == remote_data_address) {
890 if (debug) {
891 fprintf(where,
892 "local_data_address not set, using local_host_name of '%s'\n",
893 local_host_name);
894 fflush(where);
895 }
896 strcpy(local_data_address,local_host_name);
897 }
898 else {
899 if (debug) {
900 fprintf(where,
901 "local_data_address not set, using address family info\n");
902 fflush(where);
903 }
904 /* by default, use 0.0.0.0 - assume IPv4 */
905 strcpy(local_data_address,"0.0.0.0");
906 #if defined(AF_INET6)
907 if ((AF_INET6 == local_data_family) ||
908 ((AF_UNSPEC == local_data_family) &&
909 (AF_INET6 == remote_data_family)) ||
910 ((AF_UNSPEC == local_data_family) &&
911 (AF_INET6 == (*remote)->ai_family))) {
912 strcpy(local_data_address,"::0");
913 }
914 #endif
915 }
916 }
917
918 *local = complete_addrinfo("what to put here?",
919 local_data_address,
920 local_data_port,
921 local_data_family,
922 type,
923 protocol,
924 flags|AI_PASSIVE);
925
926 /* OK, at this point, if remote_data_address is NULL, we know that
927 we used the value of remote_host (the control connection) for the
928 remote, which means we can/should set remote_data_address to
929 remote_host so the "omni" output routines can use that global
930 variable. at least i think I can get away with that :) I'm sure
931 that at some point I'll find-out that I need to allocate
932 something for it rather than mess with the pointers, but that can
933 wait. famous last words of raj 2008-01-25 */
934 if (remote_data_address == NULL)
935 remote_data_address = remote_host;
936 }
937
938 void
set_hostname_and_port(char * hostname,char * portstr,int family,int port)939 set_hostname_and_port(char *hostname, char *portstr, int family, int port)
940 {
941 strcpy(hostname,"0.0.0.0");
942 #if defined AF_INET6
943 if (AF_INET6 == family) {
944 strcpy(hostname,"::0");
945 }
946 #endif
947
948 sprintf(portstr, "%u", port);
949
950 }
951
952 static unsigned short
get_port_number(struct addrinfo * res)953 get_port_number(struct addrinfo *res)
954 {
955 switch(res->ai_family) {
956 case AF_INET: {
957 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
958 return(ntohs(foo->sin_port));
959 break;
960 }
961 #if defined(AF_INET6)
962 case AF_INET6: {
963 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
964 return(ntohs(foo->sin6_port));
965 break;
966 }
967 #endif
968 default:
969 fprintf(where,
970 "Given Unexpected Address Family of %u\n",res->ai_family);
971 fflush(where);
972 exit(-1);
973 }
974 }
975
976 static void
extract_inet_address_and_port(struct addrinfo * res,void * addr,int len,int * port)977 extract_inet_address_and_port(struct addrinfo *res, void *addr, int len, int *port)
978 {
979 switch(res->ai_family) {
980 case AF_INET: {
981 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
982 *port = foo->sin_port;
983 memcpy(addr,&(foo->sin_addr),min(len,sizeof(foo->sin_addr)));
984 break;
985 }
986 #if defined(AF_INET6)
987 case AF_INET6: {
988 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
989 *port = foo->sin6_port;
990 memcpy(addr,&(foo->sin6_addr),min(len,sizeof(foo->sin6_addr)));
991 break;
992 }
993 #endif
994 default:
995 *port = 0xDEADBEEF;
996 strncpy(addr,"UNKN FAMILY",len);
997 }
998 }
999
1000 /* this routine will set the port number of the sockaddr in the
1001 addrinfo to the specified value, based on the address family */
1002 void
set_port_number(struct addrinfo * res,unsigned short port)1003 set_port_number(struct addrinfo *res, unsigned short port)
1004 {
1005 switch(res->ai_family) {
1006 case AF_INET:
1007 #if defined(AF_RDS)
1008 case AF_RDS:
1009 #endif
1010 {
1011 struct sockaddr_in *foo = (struct sockaddr_in *)res->ai_addr;
1012 foo->sin_port = htons(port);
1013 break;
1014 }
1015 #if defined(AF_INET6)
1016 case AF_INET6: {
1017 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)res->ai_addr;
1018 foo->sin6_port = htons(port);
1019 break;
1020 }
1021 #endif
1022 default:
1023 fprintf(where,
1024 "set_port_number Unexpected Address Family of %u\n",res->ai_family);
1025 fflush(where);
1026 exit(-1);
1027 }
1028 }
1029
1030 /* stuff the address family, port number and address into a
1031 sockaddr. for now, we will go ahead and zero-out the sockaddr
1032 first */
1033 void
set_sockaddr_family_addr_port(struct sockaddr_storage * sockaddr,int family,void * addr,int port)1034 set_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int port) {
1035
1036 memset(sockaddr,0,sizeof(struct sockaddr_storage));
1037
1038 switch (family) {
1039 #if defined(AF_RDS)
1040 case AF_RDS:
1041 #endif
1042 case AF_INET: {
1043 struct sockaddr_in *foo = (struct sockaddr_in *)sockaddr;
1044 foo->sin_port = htons((unsigned short) port);
1045 foo->sin_family = (unsigned short) family;
1046 memcpy(&(foo->sin_addr),addr,sizeof(foo->sin_addr));
1047 *(int *)addr = htonl(*(int *)addr);
1048 break;
1049 }
1050 #if defined(AF_INET6)
1051 case AF_INET6: {
1052 struct sockaddr_in6 *foo = (struct sockaddr_in6 *)sockaddr;
1053 foo->sin6_port = htons((unsigned short) port);
1054 foo->sin6_family = (unsigned short) family;
1055 memcpy(&(foo->sin6_addr),addr,sizeof(foo->sin6_addr));
1056 break;
1057 }
1058 #endif
1059 default:
1060 fprintf(where,
1061 "set_sockaddr_family_addr_port Unexpected Address Family of %u\n",family);
1062 fflush(where);
1063 exit(-1);
1064 }
1065 }
1066
1067 /* pull the port and address out of the sockaddr in host format */
1068 int
get_sockaddr_family_addr_port(struct sockaddr_storage * sockaddr,int family,void * addr,int * port)1069 get_sockaddr_family_addr_port(struct sockaddr_storage *sockaddr, int family, void *addr, int *port)
1070 {
1071 struct sockaddr_in *sin = (struct sockaddr_in *)sockaddr;
1072
1073 int ret = 0;
1074 if (sin->sin_family != family) {
1075 fprintf(where,
1076 "get_sockaddr_family_addr_port family mismatch %d vs %d\n",
1077 sin->sin_family,
1078 family);
1079 fflush(where);
1080 return -1;
1081 }
1082
1083 switch(family) {
1084 #if defined(AF_RDS)
1085 case AF_RDS:
1086 #endif
1087 case AF_INET: {
1088 *port = ntohs(sin->sin_port);
1089 memcpy(addr,&(sin->sin_addr),sizeof(sin->sin_addr));
1090 if (*(int *)addr == INADDR_ANY) ret = 1;
1091 *(int *)addr = ntohl(*(int *)addr);
1092 break;
1093 }
1094 #ifdef AF_INET6
1095 case AF_INET6: {
1096 int i;
1097 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sockaddr;
1098 *port = ntohs(sin6->sin6_port);
1099 ret = 1;
1100 for (i=0; i < sizeof(struct in6_addr); i++)
1101 if (sin6->sin6_addr.s6_addr[i] != 0) ret=0;
1102 memcpy(addr,&(sin6->sin6_addr), sizeof(sin6->sin6_addr));
1103 break;
1104 }
1105 #endif
1106 default:
1107 fprintf(where,
1108 "get_sockaddr_family_addr_port: Unexpected Address Family of %u\n",family);
1109 fflush(where);
1110 exit(-1);
1111 }
1112 return ret;
1113 }
1114
1115
1116 int
set_socket_tos(SOCKET sock,int family,int socket_tos)1117 set_socket_tos(SOCKET sock, int family, int socket_tos) {
1118
1119 int my_tos = -3;
1120 netperf_socklen_t sock_opt_len;
1121
1122 switch (family) {
1123 #if defined(IP_TOS)
1124 case AF_INET:
1125 /* should I mask-away anything above the byte? */
1126 my_tos = socket_tos;
1127 if (setsockopt(sock,
1128 IPPROTO_IP,
1129 IP_TOS,
1130 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) {
1131 fprintf(where,
1132 "%s ip_tos failed with %s (errno %d)\n",
1133 __FUNCTION__,
1134 strerror(errno),
1135 errno);
1136 fflush(where);
1137 my_tos = -2;
1138 }
1139 else {
1140 sock_opt_len = sizeof(my_tos);
1141 getsockopt(sock,
1142 IPPROTO_IP,
1143 IP_TOS,
1144 (char *)&my_tos,
1145 &sock_opt_len);
1146 }
1147 break;
1148 #endif
1149 #if defined(IPV6_TCLASS)
1150 case AF_INET6:
1151 /* should I mask-away anything above the byte? */
1152 my_tos = socket_tos;
1153 if (setsockopt(sock,
1154 IPPROTO_IPV6,
1155 IPV6_TCLASS,
1156 (const char *)&my_tos,sizeof(my_tos)) == SOCKET_ERROR) {
1157 fprintf(where,
1158 "%s ip_tos failed with %s (errno %d)\n",
1159 __FUNCTION__,
1160 strerror(errno),
1161 errno);
1162 fflush(where);
1163 my_tos = -2;
1164 }
1165 else {
1166 sock_opt_len = sizeof(my_tos);
1167 getsockopt(sock,
1168 IPPROTO_IPV6,
1169 IPV6_TCLASS,
1170 (char *)&my_tos,
1171 &sock_opt_len);
1172 }
1173 break;
1174 #endif
1175 }
1176 return my_tos;
1177 }
1178
1179
1180 /* This routine will create a data (listen) socket with the
1181 apropriate options set and return it to the caller. this replaces
1182 all the duplicate code in each of the test routines and should help
1183 make things a little easier to understand. since this routine can be
1184 called by either the netperf or netserver programs, all output
1185 should be directed towards "where." family is generally AF_INET and
1186 type will be either SOCK_STREAM or SOCK_DGRAM. This routine will
1187 also be used by the "SCTP" tests, hence the slightly strange-looking
1188 SCTP stuff in the classic bsd sockets test file... vlad/raj
1189 2005-03-15 */
1190
1191 SOCKET
create_data_socket(struct addrinfo * res)1192 create_data_socket(struct addrinfo *res)
1193 {
1194
1195 SOCKET temp_socket;
1196 int one = 1;
1197 int on = 1;
1198 netperf_socklen_t sock_opt_len;
1199
1200 /*set up the data socket */
1201 temp_socket = socket(res->ai_family,
1202 res->ai_socktype,
1203 res->ai_protocol);
1204
1205 if (temp_socket == INVALID_SOCKET){
1206 fprintf(where,
1207 "netperf: create_data_socket: socket: errno %d fam %s type %s prot %s errmsg %s\n",
1208 errno,
1209 inet_ftos(res->ai_family),
1210 inet_ttos(res->ai_socktype),
1211 inet_ptos(res->ai_protocol),
1212 strerror(errno));
1213 fflush(where);
1214 exit(1);
1215 }
1216
1217 if (debug) {
1218 fprintf(where,"create_data_socket: socket %d obtained...\n",temp_socket);
1219 fflush(where);
1220 }
1221
1222 /* Modify the local socket size. The reason we alter the send buffer
1223 size here rather than when the connection is made is to take care
1224 of decreases in buffer size. Decreasing the window size after
1225 connection establishment is a TCP no-no. Also, by setting the
1226 buffer (window) size before the connection is established, we can
1227 control the TCP MSS (segment size). The MSS is never (well, should
1228 never be) more that 1/2 the minimum receive buffer size at each
1229 half of the connection. This is why we are altering the receive
1230 buffer size on the sending size of a unidirectional transfer. If
1231 the user has not requested that the socket buffers be altered, we
1232 will try to find-out what their values are. If we cannot touch the
1233 socket buffer in any way, we will set the values to -1 to indicate
1234 that. */
1235
1236 /* all the oogy nitty gritty stuff moved from here into the routine
1237 being called below, per patches from davidm to workaround the bug
1238 in Linux getsockopt(). raj 2004-06-15 */
1239 set_sock_buffer (temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
1240 set_sock_buffer (temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
1241
1242 /* now, we may wish to enable the copy avoidance features on the */
1243 /* local system. of course, this may not be possible... */
1244
1245 #ifdef SO_RCV_COPYAVOID
1246 /* this is ancient vestigial HP-UX code that should probably go away
1247 one day */
1248 if (loc_rcvavoid) {
1249 if (setsockopt(temp_socket,
1250 SOL_SOCKET,
1251 SO_RCV_COPYAVOID,
1252 (const char *)&loc_rcvavoid,
1253 sizeof(int)) == SOCKET_ERROR) {
1254 fprintf(where,
1255 "netperf: create_data_socket: Could not enable receive copy avoidance");
1256 fflush(where);
1257 loc_rcvavoid = 0;
1258 }
1259 }
1260 #endif
1261
1262 #ifdef SO_SND_COPYAVOID
1263 if (loc_sndavoid) {
1264 if (setsockopt(temp_socket,
1265 SOL_SOCKET,
1266 SO_SND_COPYAVOID,
1267 (const char *)&loc_sndavoid,
1268 sizeof(int)) == SOCKET_ERROR) {
1269 fprintf(where,
1270 "netperf: create_data_socket: Could not enable send copy avoidance");
1271 fflush(where);
1272 loc_sndavoid = 0;
1273 }
1274 }
1275 #endif
1276
1277 /* Now, we will see about setting the TCP_NODELAY flag on the local */
1278 /* socket. We will only do this for those systems that actually */
1279 /* support the option. If it fails, note the fact, but keep going. */
1280 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
1281 /* will cause an error to be displayed */
1282
1283 /* well..... long ago and far away that would have happened, in
1284 particular because we would always use IPPROTO_TCP here.
1285 however, now we are using res->ai_protocol, which will be
1286 IPPROT_UDP, and while HP-UX, and I suspect no-one else on the
1287 planet has a UDP_mumble option that overlaps with TCP_NODELAY,
1288 sure as knuth made little green programs, linux has a UDP_CORK
1289 option that is defined as a value of 1, which is the same a
1290 TCP_NODELAY under Linux. So, when asking for -D and
1291 "TCP_NODELAY" under Linux, we are actually setting UDP_CORK
1292 instead of getting an error like every other OS on the
1293 planet. joy and rupture. this stops a UDP_RR test cold sooo we
1294 have to make sure that res->ai_protocol actually makes sense for
1295 a _NODELAY setsockopt() or a UDP_RR test on Linux where someone
1296 mistakenly sets -D will hang. raj 2005-04-21 */
1297
1298 #if defined(TCP_NODELAY) || defined(SCTP_NODELAY)
1299 if ((loc_nodelay) && (res->ai_protocol != IPPROTO_UDP)) {
1300
1301 /* strictly speaking, since the if defined above is an OR, we
1302 should probably check against TCP_NODELAY being defined here.
1303 however, the likelihood of SCTP_NODELAY being defined and
1304 TCP_NODELAY _NOT_ being defined is, probably :), epsilon. raj
1305 2005-03-15 */
1306
1307 int option = TCP_NODELAY;
1308
1309 /* I suspect that WANT_SCTP would suffice here since that is the
1310 only time we would have called getaddrinfo with a hints asking
1311 for SCTP, but just in case there is an SCTP implementation out
1312 there _without_ SCTP_NODELAY... raj 2005-03-15 */
1313 /* change this to IPPROTO_SCTP rather than WANT_SCTP to better fit
1314 with the modus operandi of the new "omni" tests. raj
1315 2008-02-04 */
1316 #if defined(IPPROTO_SCTP) && defined(SCTP_NODELAY)
1317 if (IPPROTO_SCTP == res->ai_protocol) {
1318 option = SCTP_NODELAY;
1319 }
1320 #endif
1321
1322 one = 1;
1323 if(setsockopt(temp_socket,
1324 res->ai_protocol,
1325 option,
1326 (char *)&one,
1327 sizeof(one)) == SOCKET_ERROR) {
1328 fprintf(where,
1329 "netperf: create_data_socket: nodelay: errno %d\n",
1330 errno);
1331 fflush(where);
1332 }
1333
1334 if (debug > 1) {
1335 fprintf(where,
1336 "netperf: create_data_socket: [TCP|SCTP]_NODELAY requested...\n");
1337 fflush(where);
1338 }
1339 }
1340 #else /* TCP_NODELAY */
1341
1342 loc_nodelay = 0;
1343
1344 #endif /* TCP_NODELAY */
1345
1346 if ((transport_mss_req != -1) && (IPPROTO_TCP == res->ai_protocol)) {
1347 set_tcp_mss(temp_socket,transport_mss_req);
1348 }
1349
1350 #if defined(TCP_CORK)
1351
1352 if (loc_tcpcork > 0) {
1353 /* the user wishes for us to set TCP_CORK on the socket */
1354 if (setsockopt(temp_socket,
1355 getprotobyname("tcp")->p_proto,
1356 TCP_CORK,
1357 (char *)&one,
1358 sizeof(one)) == SOCKET_ERROR) {
1359 perror("netperf: create_data_socket: tcp_cork");
1360 exit(1);
1361 }
1362 if (debug) {
1363 fprintf(where,"create_data_socket: tcp_cork...\n");
1364 }
1365 }
1366
1367 #endif /* TCP_CORK */
1368
1369 /* well, after Knuth only knows how many years, I have finally
1370 decided to enable setting SO_KEEPALIVE on the data socket. 99
1371 times out of 10 this should not be necessary, but that 100th time,
1372 perhaps when netperf is being (ab)used by functional testers, may
1373 benefit from it. And it may help clean-up some lingering
1374 netservers from time to time. raj 2011-06-29 */
1375
1376 #if defined(SO_KEEPALIVE)
1377
1378 if (want_keepalive) {
1379 if (setsockopt(temp_socket,
1380 SOL_SOCKET,
1381 SO_KEEPALIVE,
1382 (const char *)&on,
1383 sizeof(on)) < 0) {
1384 if (debug) {
1385 fprintf(where,
1386 "%s: unable to set SO_KEEPALIVE on data socket: %s (errno %d)\n",
1387 __FUNCTION__,
1388 strerror(errno),
1389 errno);
1390 fflush(where);
1391 }
1392 }
1393 }
1394
1395 #endif /* SO_KEEPALIVE */
1396
1397 /* since some of the UDP tests do not do anything to cause an
1398 implicit bind() call, we need to be rather explicit about our
1399 bind() call here. even if the address and/or the port are zero
1400 (INADDR_ANY etc). raj 2004-07-20 */
1401
1402 if (setsockopt(temp_socket,
1403 #ifdef IPPROTO_DCCP
1404 /* it is REALLY SILLY THAT THIS SHOULD BE NEEDED!! I
1405 should be able to use SOL_SOCKET for this just
1406 like TCP and SCTP */
1407 /* IT IS EVEN SILLIER THAT THERE COULD BE SYSTEMS
1408 WITH IPPROTO_DCCP and no SOL_DCCP */
1409 #ifndef SOL_DCCP
1410 #define SOL_DCCP SOL_SOCKET
1411 #define NETPERF_NEED_CLEANUP 1
1412 #endif
1413 (res->ai_protocol == IPPROTO_DCCP) ? SOL_DCCP : SOL_SOCKET,
1414 #ifdef NETPERF_NEED_CLEANUP
1415 #undef SOL_DCCP
1416 #undef NETPERF_NEED_CLEANUP
1417 #endif
1418
1419 #else
1420 SOL_SOCKET,
1421 #endif
1422 SO_REUSEADDR,
1423 (const char *)&on,
1424 sizeof(on)) < 0) {
1425 fprintf(where,
1426 "netperf: create_data_socket: SO_REUSEADDR failed %d\n",
1427 errno);
1428 fflush(where);
1429 }
1430
1431 if (bind(temp_socket,
1432 res->ai_addr,
1433 res->ai_addrlen) < 0) {
1434 if (debug) {
1435 fprintf(where,
1436 "netperf: create_data_socket: data socket bind failed: %s (errno %d)\n",
1437 strerror(errno),
1438 errno);
1439 fprintf(where," port: %d\n",get_port_number(res));
1440 fflush(where);
1441 }
1442 }
1443
1444 /* this one is a slightly grudgingly added backside covering for
1445 those folks who (ab)use netperf as a functional testing tool, and
1446 further compound that error by running tests on systems also
1447 connected to their site networks, and then compound it even
1448 further compound it by running UDP_STREAM tests over links that
1449 generate link-down events and so cause the traffic to be sent out
1450 the default route into their corporate network... frankly such
1451 people should not be allowed to run netperf in the first place
1452 but there we are... raj 20091026 */
1453
1454 #if defined (SO_DONTROUTE)
1455 if (!routing_allowed) {
1456 if (setsockopt(temp_socket,
1457 SOL_SOCKET,
1458 SO_DONTROUTE,
1459 (char *)&one,
1460 sizeof(one)) == SOCKET_ERROR) {
1461 fprintf(where,
1462 "netperf: create_data_socket: so_dontroute: errno %d\n",
1463 errno);
1464 fflush(where);
1465 }
1466 }
1467 #endif
1468
1469 #if defined(SO_PRIORITY)
1470 if (local_socket_prio >= 0) {
1471 if (setsockopt(temp_socket,
1472 SOL_SOCKET,
1473 SO_PRIORITY,
1474 &local_socket_prio,
1475 sizeof(int)) == SOCKET_ERROR) {
1476 fprintf(where,
1477 "netperf: create_data_socket: so_priority: errno %d\n",
1478 errno);
1479 fflush(where);
1480 local_socket_prio = -2;
1481 }
1482 else {
1483 sock_opt_len = 4;
1484 getsockopt(temp_socket,
1485 SOL_SOCKET,
1486 SO_PRIORITY,
1487 &local_socket_prio,
1488 &sock_opt_len);
1489 }
1490 }
1491 #else
1492 local_socket_prio = -3;
1493 #endif
1494
1495 #if defined (IP_TOS) || defined(IPV6_TCLASS)
1496 if (local_socket_tos > 0)
1497 local_socket_tos = set_socket_tos(temp_socket,res->ai_family, local_socket_tos);
1498 #endif
1499
1500 return temp_socket;
1501 }
1502
1503 #ifdef KLUDGE_SOCKET_OPTIONS
1504
1505
1506 /* This routine is for those BROKEN systems which do not correctly */
1507 /* pass socket attributes through calls such as accept(). It should */
1508 /* only be called for those broken systems. I *really* don't want to */
1509 /* have this, but even broken systems must be measured. raj 11/95 */
1510 void
kludge_socket_options(int temp_socket)1511 kludge_socket_options(int temp_socket)
1512 {
1513
1514 set_sock_buffer(temp_socket, SEND_BUFFER, lss_size_req, &lss_size);
1515 set_sock_buffer(temp_socket, RECV_BUFFER, lsr_size_req, &lsr_size);
1516
1517 /* now, we may wish to enable the copy avoidance features on the */
1518 /* local system. of course, this may not be possible... */
1519 /* those calls were only valid for HP-UX, and I know that HP-UX is */
1520 /* written correctly, and so we do not need to include those calls */
1521 /* in this kludgy routine. raj 11/95 */
1522
1523
1524 /* Now, we will see about setting the TCP_NODELAY flag on the local */
1525 /* socket. We will only do this for those systems that actually */
1526 /* support the option. If it fails, note the fact, but keep going. */
1527 /* If the user tries to enable TCP_NODELAY on a UDP socket, this */
1528 /* will cause an error to be displayed */
1529
1530 #ifdef TCP_NODELAY
1531 if (loc_nodelay) {
1532 one = 1;
1533 if(setsockopt(temp_socket,
1534 getprotobyname("tcp")->p_proto,
1535 TCP_NODELAY,
1536 (char *)&one,
1537 sizeof(one)) == SOCKET_ERROR) {
1538 fprintf(where,"netperf: kludge_socket_options: nodelay: errno %d\n",
1539 errno);
1540 fflush(where);
1541 }
1542
1543 if (debug > 1) {
1544 fprintf(where,
1545 "netperf: kludge_socket_options: TCP_NODELAY requested...\n");
1546 fflush(where);
1547 }
1548 }
1549 #else /* TCP_NODELAY */
1550
1551 loc_nodelay = 0;
1552
1553 #endif /* TCP_NODELAY */
1554
1555 }
1556
1557 #endif /* KLUDGE_SOCKET_OPTIONS */
1558
1559
1560 static void *
get_address_address(struct addrinfo * info)1561 get_address_address(struct addrinfo *info)
1562 {
1563 struct sockaddr_in *sin;
1564 #if defined(AF_INET6)
1565 struct sockaddr_in6 *sin6;
1566 #endif
1567
1568 switch(info->ai_family) {
1569 case AF_INET:
1570 sin = (struct sockaddr_in *)info->ai_addr;
1571 return(&(sin->sin_addr));
1572 break;
1573 #if defined(AF_INET6)
1574 case AF_INET6:
1575 sin6 = (struct sockaddr_in6 *)info->ai_addr;
1576 return(&(sin6->sin6_addr));
1577 break;
1578 #endif
1579 default:
1580 fprintf(stderr,"we never expected to get here in get_address_address\n");
1581 fflush(stderr);
1582 exit(-1);
1583 }
1584 }
1585
1586 #if defined(WIN32)
1587 #if !defined(InetNtop)
1588 /* +*+ Why isn't this in the winsock headers yet? */
1589 const char *
1590 inet_ntop(int af, const void *src, char *dst, size_t size);
1591 #endif
1592 #endif
1593
1594 /* This routine is a generic test header printer for the topmost header */
1595 void
print_top_test_header(char test_name[],struct addrinfo * source,struct addrinfo * destination)1596 print_top_test_header(char test_name[], struct addrinfo *source, struct addrinfo *destination)
1597 {
1598
1599 char *address_buf;
1600
1601 #ifdef AF_INET6
1602 address_buf = malloc(INET6_ADDRSTRLEN);
1603 #else
1604 address_buf = malloc(16); /* magic constant */
1605 #endif
1606
1607 if (address_buf == NULL) {
1608 fprintf(where,"Unable to allocate address_buf\n");
1609 fflush(where);
1610 exit(1);
1611 }
1612
1613 /* we want to have some additional, interesting information in the
1614 headers. we know some of it here, but not all, so we will only
1615 print the test title here and will print the results titles after
1616 the test is finished */
1617 fprintf(where,"%s",test_name);
1618
1619 address_buf[0] = '\0';
1620 inet_ntop(source->ai_family,get_address_address(source),address_buf,sizeof(address_buf));
1621 fprintf(where,
1622 " from %s (%s) port %u %s",
1623 source->ai_canonname,
1624 address_buf,
1625 get_port_number(source),
1626 inet_ftos(source->ai_family));
1627
1628 address_buf[0] = '\0';
1629 inet_ntop(destination->ai_family,get_address_address(destination),address_buf,sizeof(address_buf));
1630 fprintf(where,
1631 " to %s (%s) port %u %s",
1632 destination->ai_canonname,
1633 address_buf,
1634 get_port_number(destination),
1635 inet_ftos(destination->ai_family));
1636
1637 if (iteration_max > 1) {
1638 fprintf(where,
1639 " : +/-%.3f%% @ %2d%% conf. %s",
1640 interval/0.02,
1641 confidence_level,
1642 result_confidence_only ? " on result only" : "");
1643 }
1644 if ((loc_nodelay > 0) || (rem_nodelay > 0)) {
1645 fprintf(where," : nodelay");
1646 }
1647 if ((loc_sndavoid > 0) ||
1648 (loc_rcvavoid > 0) ||
1649 (rem_sndavoid > 0) ||
1650 (rem_rcvavoid > 0)) {
1651 fprintf(where," : copy avoidance");
1652 }
1653
1654 if (no_control) {
1655 fprintf(where," : no control");
1656 }
1657
1658 #ifdef WANT_HISTOGRAM
1659 fprintf(where," : histogram");
1660 #endif /* WANT_HISTOGRAM */
1661
1662 #ifdef WANT_INTERVALS
1663 #ifndef WANT_SPIN
1664 fprintf(where," : interval");
1665 #else
1666 fprintf(where," : spin interval");
1667 #endif
1668 #endif /* WANT_INTERVALS */
1669
1670 #ifdef DIRTY
1671 fprintf(where," : dirty data");
1672 #endif /* DIRTY */
1673 #ifdef WANT_DEMO
1674 fprintf(where," : demo");
1675 #endif
1676 #ifdef WANT_FIRST_BURST
1677 /* a little hokey perhaps, but we really only want this to be
1678 emitted for tests where it actually is used, which means a
1679 "REQUEST/RESPONSE" test. raj 2005-11-10 */
1680 if (strstr(test_name,"REQUEST/RESPONSE")) {
1681 fprintf(where," : first burst %d",first_burst_size);
1682 }
1683 #endif
1684 if (cpu_binding_requested) {
1685 fprintf(where," : cpu bind");
1686 }
1687 fprintf(where,"\n");
1688
1689 free(address_buf);
1690 }
1691
1692 /* if WANT_MIGRATION is defined, we will use the send_tcp_stream()
1693 call in src/nettest_omni.c */
1694 #ifndef WANT_MIGRATION
1695
1696 /* This routine implements the TCP unidirectional data transfer test */
1697 /* (a.k.a. stream) for the sockets interface. It receives its */
1698 /* parameters via global variables from the shell and writes its */
1699 /* output to the standard output. */
1700
1701 void
send_tcp_stream(char remote_host[])1702 send_tcp_stream(char remote_host[])
1703 {
1704
1705 char *tput_title = "\
1706 Recv Send Send \n\
1707 Socket Socket Message Elapsed \n\
1708 Size Size Size Time Throughput \n\
1709 bytes bytes bytes secs. %s/sec \n\n";
1710
1711 char *tput_fmt_0 =
1712 "%7.2f %s\n";
1713
1714 char *tput_fmt_1 =
1715 "%6d %6d %6d %-6.2f %7.2f %s\n";
1716
1717 char *cpu_title = "\
1718 Recv Send Send Utilization Service Demand\n\
1719 Socket Socket Message Elapsed Send Recv Send Recv\n\
1720 Size Size Size Time Throughput local remote local remote\n\
1721 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
1722
1723 char *cpu_fmt_0 =
1724 "%6.3f %c %s\n";
1725
1726 char *cpu_fmt_1 =
1727 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
1728
1729 char *ksink_fmt = "\n\
1730 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
1731 Local Remote Local Remote Xfered Per Per\n\
1732 Send Recv Send Recv Send (avg) Recv (avg)\n\
1733 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
1734
1735 char *ksink_fmt2 = "\n\
1736 Maximum\n\
1737 Segment\n\
1738 Size (bytes)\n\
1739 %6d\n";
1740
1741
1742 float elapsed_time;
1743
1744 /* what we want is to have a buffer space that is at least one */
1745 /* send-size greater than our send window. this will insure that we */
1746 /* are never trying to re-use a buffer that may still be in the hands */
1747 /* of the transport. This buffer will be malloc'd after we have found */
1748 /* the size of the local senc socket buffer. We will want to deal */
1749 /* with alignment and offset concerns as well. */
1750
1751 struct ring_elt *send_ring;
1752
1753 int len;
1754 unsigned int nummessages = 0;
1755 SOCKET send_socket;
1756 int bytes_remaining;
1757 int tcp_mss = -1; /* possibly uninitialized on printf far below */
1758
1759 /* with links like fddi, one can send > 32 bits worth of bytes
1760 during a test... ;-) at some point, this should probably become a
1761 64bit integral type, but those are not entirely common
1762 yet... time passes, and 64 bit types do indeed become common. */
1763 #if defined(WIN32) && _MSC_VER <= 1200
1764 __int64 local_bytes_sent = 0;
1765 #else
1766 unsigned long long local_bytes_sent = 0;
1767 #endif
1768
1769 double bytes_sent = 0.0;
1770
1771 float local_cpu_utilization;
1772 float local_service_demand;
1773 float remote_cpu_utilization;
1774 float remote_service_demand;
1775
1776 double thruput;
1777
1778 struct addrinfo *remote_res;
1779 struct addrinfo *local_res;
1780
1781 struct tcp_stream_request_struct *tcp_stream_request;
1782 struct tcp_stream_response_struct *tcp_stream_response;
1783 struct tcp_stream_results_struct *tcp_stream_result;
1784
1785 tcp_stream_request =
1786 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
1787 tcp_stream_response =
1788 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
1789 tcp_stream_result =
1790 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
1791
1792 #ifdef WANT_HISTOGRAM
1793 if (verbosity > 1) {
1794 time_hist = HIST_new();
1795 }
1796 #endif /* WANT_HISTOGRAM */
1797 /* since we are now disconnected from the code that established the */
1798 /* control socket, and since we want to be able to use different */
1799 /* protocols and such, we are passed the name of the remote host and */
1800 /* must turn that into the test specific addressing information. */
1801
1802 /* complete_addrinfos will either succede or exit the process */
1803 complete_addrinfos(&remote_res,
1804 &local_res,
1805 remote_host,
1806 SOCK_STREAM,
1807 IPPROTO_TCP,
1808 0);
1809
1810 if ( print_headers ) {
1811 print_top_test_header("TCP STREAM TEST",local_res,remote_res);
1812 }
1813
1814 send_ring = NULL;
1815 confidence_iteration = 1;
1816 init_stat();
1817
1818 /* we have a great-big while loop which controls the number of times */
1819 /* we run a particular test. this is for the calculation of a */
1820 /* confidence interval (I really should have stayed awake during */
1821 /* probstats :). If the user did not request confidence measurement */
1822 /* (no confidence is the default) then we will only go though the */
1823 /* loop once. the confidence stuff originates from the folks at IBM */
1824
1825 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
1826 (confidence_iteration <= iteration_min)) {
1827
1828 /* initialize a few counters. we have to remember that we might be */
1829 /* going through the loop more than once. */
1830
1831 nummessages = 0;
1832 bytes_sent = 0.0;
1833 times_up = 0;
1834
1835 /*set up the data socket */
1836 send_socket = create_data_socket(local_res);
1837
1838 if (send_socket == INVALID_SOCKET){
1839 perror("netperf: send_tcp_stream: tcp stream data socket");
1840 exit(1);
1841 }
1842
1843 if (debug) {
1844 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
1845 }
1846
1847 /* at this point, we have either retrieved the socket buffer sizes, */
1848 /* or have tried to set them, so now, we may want to set the send */
1849 /* size based on that (because the user either did not use a -m */
1850 /* option, or used one with an argument of 0). If the socket buffer */
1851 /* size is not available, we will set the send size to 4KB - no */
1852 /* particular reason, just arbitrary... */
1853 if (send_size == 0) {
1854 if (lss_size > 0) {
1855 send_size = lss_size;
1856 }
1857 else {
1858 send_size = 4096;
1859 }
1860 }
1861
1862 /* set-up the data buffer ring with the requested alignment and offset. */
1863 /* note also that we have allocated a quantity */
1864 /* of memory that is at least one send-size greater than our socket */
1865 /* buffer size. We want to be sure that there are at least two */
1866 /* buffers allocated - this can be a bit of a problem when the */
1867 /* send_size is bigger than the socket size, so we must check... the */
1868 /* user may have wanted to explicitly set the "width" of our send */
1869 /* buffers, we should respect that wish... */
1870 if (send_width == 0) {
1871 send_width = (lss_size/send_size) + 1;
1872 if (send_width == 1) send_width++;
1873 }
1874
1875 if (send_ring == NULL) {
1876 /* only allocate the send ring once. this is a networking test, */
1877 /* not a memory allocation test. this way, we do not need a */
1878 /* deallocate_buffer_ring() routine, and I don't feel like */
1879 /* writing one anyway :) raj 11/94 */
1880 send_ring = allocate_buffer_ring(send_width,
1881 send_size,
1882 local_send_align,
1883 local_send_offset);
1884 }
1885
1886 /* If the user has requested cpu utilization measurements, we must */
1887 /* calibrate the cpu(s). We will perform this task within the tests */
1888 /* themselves. If the user has specified the cpu rate, then */
1889 /* calibrate_local_cpu will return rather quickly as it will have */
1890 /* nothing to do. If local_cpu_rate is zero, then we will go through */
1891 /* all the "normal" calibration stuff and return the rate back. */
1892
1893 if (local_cpu_usage) {
1894 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
1895 }
1896
1897 if (!no_control) {
1898 /* Tell the remote end to do a listen. The server alters the
1899 socket paramters on the other side at this point, hence the
1900 reason for all the values being passed in the setup
1901 message. If the user did not specify any of the parameters,
1902 they will be passed as 0, which will indicate to the remote
1903 that no changes beyond the system's default should be
1904 used. Alignment is the exception, it will default to 1, which
1905 will be no alignment alterations. */
1906
1907 netperf_request.content.request_type = DO_TCP_STREAM;
1908 tcp_stream_request->send_buf_size = rss_size_req;
1909 tcp_stream_request->recv_buf_size = rsr_size_req;
1910 tcp_stream_request->receive_size = recv_size;
1911 tcp_stream_request->no_delay = rem_nodelay;
1912 tcp_stream_request->recv_alignment = remote_recv_align;
1913 tcp_stream_request->recv_offset = remote_recv_offset;
1914 tcp_stream_request->measure_cpu = remote_cpu_usage;
1915 tcp_stream_request->cpu_rate = remote_cpu_rate;
1916 if (test_time) {
1917 tcp_stream_request->test_length = test_time;
1918 }
1919 else {
1920 tcp_stream_request->test_length = test_bytes;
1921 }
1922 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
1923 tcp_stream_request->so_sndavoid = rem_sndavoid;
1924 #ifdef DIRTY
1925 tcp_stream_request->dirty_count = rem_dirty_count;
1926 tcp_stream_request->clean_count = rem_clean_count;
1927 #endif /* DIRTY */
1928 tcp_stream_request->port = atoi(remote_data_port);
1929 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
1930 if (debug > 1) {
1931 fprintf(where,
1932 "netperf: send_tcp_stream: requesting TCP stream test\n");
1933 }
1934
1935 send_request();
1936
1937 /* The response from the remote will contain all of the relevant
1938 socket parameters for this test type. We will put them back
1939 into the variables here so they can be displayed if desired.
1940 The remote will have calibrated CPU if necessary, and will
1941 have done all the needed set-up we will have calibrated the
1942 cpu locally before sending the request, and will grab the
1943 counter value right after the connect returns. The remote
1944 will grab the counter right after the accept call. This saves
1945 the hassle of extra messages being sent for the TCP
1946 tests. */
1947
1948 recv_response();
1949
1950 if (!netperf_response.content.serv_errno) {
1951 if (debug)
1952 fprintf(where,"remote listen done.\n");
1953 rsr_size = tcp_stream_response->recv_buf_size;
1954 rss_size = tcp_stream_response->send_buf_size;
1955 rem_nodelay = tcp_stream_response->no_delay;
1956 remote_cpu_usage= tcp_stream_response->measure_cpu;
1957 remote_cpu_rate = tcp_stream_response->cpu_rate;
1958
1959 /* we have to make sure that the server port number is in
1960 network order */
1961 set_port_number(remote_res,
1962 (short)tcp_stream_response->data_port_number);
1963
1964 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
1965 rem_sndavoid = tcp_stream_response->so_sndavoid;
1966 }
1967 else {
1968 Set_errno(netperf_response.content.serv_errno);
1969 fprintf(where,
1970 "netperf: remote error %d",
1971 netperf_response.content.serv_errno);
1972 perror("");
1973 fflush(where);
1974
1975 exit(1);
1976 }
1977 }
1978
1979 #ifdef WANT_DEMO
1980 demo_stream_setup(lss_size,rsr_size);
1981 #endif
1982
1983 /*Connect up to the remote port on the data socket */
1984 if (connect(send_socket,
1985 remote_res->ai_addr,
1986 remote_res->ai_addrlen) == INVALID_SOCKET){
1987 perror("netperf: send_tcp_stream: data socket connect failed");
1988 exit(1);
1989 }
1990
1991 #ifdef WIN32
1992 /* this is used so the timer thread can close the socket out from */
1993 /* under us, which to date is the easiest/cleanest/least */
1994 /* Windows-specific way I can find to force the winsock calls to */
1995 /* return WSAEINTR with the test is over. anything that will run on */
1996 /* 95 and NT and is closer to what netperf expects from Unix signals */
1997 /* and such would be appreciated raj 1/96 */
1998 win_kludge_socket = send_socket;
1999 #endif /* WIN32 */
2000
2001 /* Data Socket set-up is finished. If there were problems, either */
2002 /* the connect would have failed, or the previous response would */
2003 /* have indicated a problem. I failed to see the value of the */
2004 /* extra message after the accept on the remote. If it failed, */
2005 /* we'll see it here. If it didn't, we might as well start pumping */
2006 /* data. */
2007
2008 /* Set-up the test end conditions. For a stream test, they can be */
2009 /* either time or byte-count based. */
2010
2011 if (test_time) {
2012 /* The user wanted to end the test after a period of time. */
2013 times_up = 0;
2014 bytes_remaining = 0;
2015 /* in previous revisions, we had the same code repeated throught */
2016 /* all the test suites. this was unnecessary, and meant more */
2017 /* work for me when I wanted to switch to POSIX signals, so I */
2018 /* have abstracted this out into a routine in netlib.c. if you */
2019 /* are experiencing signal problems, you might want to look */
2020 /* there. raj 11/94 */
2021 start_timer(test_time);
2022 }
2023 else {
2024 /* The tester wanted to send a number of bytes. */
2025 bytes_remaining = test_bytes;
2026 times_up = 1;
2027 }
2028
2029 /* The cpu_start routine will grab the current time and possibly */
2030 /* value of the idle counter for later use in measuring cpu */
2031 /* utilization and/or service demand and thruput. */
2032
2033 cpu_start(local_cpu_usage);
2034
2035 /* we only start the interval timer if we are using the
2036 timer-timed intervals rather than the sit and spin ones. raj
2037 2006-02-06 */
2038 #if defined(WANT_INTERVALS)
2039 INTERVALS_INIT();
2040 #endif /* WANT_INTERVALS */
2041
2042 /* before we start, initialize a few variables */
2043
2044 #ifdef WANT_DEMO
2045 if (demo_mode) {
2046 demo_first_timestamp();
2047 }
2048 #endif
2049
2050
2051 /* We use an "OR" to control test execution. When the test is */
2052 /* controlled by time, the byte count check will always return false. */
2053 /* When the test is controlled by byte count, the time test will */
2054 /* always return false. When the test is finished, the whole */
2055 /* expression will go false and we will stop sending data. */
2056
2057 while ((!times_up) || (bytes_remaining > 0)) {
2058
2059 #ifdef DIRTY
2060 access_buffer(send_ring->buffer_ptr,
2061 send_size,
2062 loc_dirty_count,
2063 loc_clean_count);
2064 #endif /* DIRTY */
2065
2066 #ifdef WANT_HISTOGRAM
2067 if (verbosity > 1) {
2068 /* timestamp just before we go into send and then again just
2069 after we come out raj 8/94 */
2070 /* but lets only do this if there is going to be a histogram
2071 displayed */
2072 HIST_timestamp(&time_one);
2073 }
2074 #endif /* WANT_HISTOGRAM */
2075
2076 if((len=send(send_socket,
2077 send_ring->buffer_ptr,
2078 send_size,
2079 0)) != send_size) {
2080 if ((len >=0) || SOCKET_EINTR(len)) {
2081 /* the test was interrupted, must be the end of test */
2082 break;
2083 }
2084 perror("netperf: data send error");
2085 printf("len was %d\n",len);
2086 exit(1);
2087 }
2088
2089 local_bytes_sent += send_size;
2090
2091 #ifdef WANT_HISTOGRAM
2092 if (verbosity > 1) {
2093 /* timestamp the exit from the send call and update the histogram */
2094 HIST_timestamp(&time_two);
2095 HIST_add(time_hist,delta_micro(&time_one,&time_two));
2096 }
2097 #endif /* WANT_HISTOGRAM */
2098
2099 #ifdef WANT_DEMO
2100 demo_stream_interval(send_size);
2101 #endif
2102
2103 #if defined(WANT_INTERVALS)
2104 INTERVALS_WAIT();
2105 #endif /* WANT_INTERVALS */
2106
2107 /* now we want to move our pointer to the next position in the */
2108 /* data buffer...we may also want to wrap back to the "beginning" */
2109 /* of the bufferspace, so we will mod the number of messages sent */
2110 /* by the send width, and use that to calculate the offset to add */
2111 /* to the base pointer. */
2112 nummessages++;
2113 send_ring = send_ring->next;
2114 if (bytes_remaining) {
2115 bytes_remaining -= send_size;
2116 }
2117 }
2118
2119 /* The test is over. Flush the buffers to the remote end. We do a */
2120 /* graceful release to insure that all data has been taken by the */
2121 /* remote. */
2122
2123 /* but first, if the verbosity is greater than 1, find-out what */
2124 /* the TCP maximum segment_size was (if possible) */
2125 if (verbosity > 1) {
2126 tcp_mss = -1;
2127 get_tcp_info(send_socket,&tcp_mss);
2128 }
2129
2130 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR && !times_up) {
2131 perror("netperf: cannot shutdown tcp stream socket");
2132 exit(1);
2133 }
2134
2135 /* hang a recv() off the socket to block until the remote has */
2136 /* brought all the data up into the application. it will do a */
2137 /* shutdown to cause a FIN to be sent our way. We will assume that */
2138 /* any exit from the recv() call is good... raj 4/93 */
2139
2140 recv(send_socket, send_ring->buffer_ptr, send_size, 0);
2141
2142 /* this call will always give us the elapsed time for the test, and */
2143 /* will also store-away the necessaries for cpu utilization */
2144
2145 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
2146 /* measured and how */
2147 /* long did we really */
2148 /* run? */
2149
2150 /* we are finished with the socket, so close it to prevent hitting */
2151 /* the limit on maximum open files. */
2152
2153 close(send_socket);
2154
2155 #if defined(WANT_INTERVALS)
2156 #ifdef WIN32
2157 stop_itimer();
2158 #endif
2159 #endif /* WANT_INTERVALS */
2160
2161 if (!no_control) {
2162 /* Get the statistics from the remote end. The remote will have
2163 calculated service demand and all those interesting
2164 things. If it wasn't supposed to care, it will return obvious
2165 values. */
2166
2167 recv_response();
2168 if (!netperf_response.content.serv_errno) {
2169 if (debug)
2170 fprintf(where,
2171 "remote reporting results for %.2f seconds\n",
2172 tcp_stream_result->elapsed_time);
2173 }
2174 else {
2175 Set_errno(netperf_response.content.serv_errno);
2176 fprintf(where,
2177 "netperf: remote error %d",
2178 netperf_response.content.serv_errno);
2179 perror("");
2180 fflush(where);
2181
2182 exit(1);
2183 }
2184
2185 /* We now calculate what our thruput was for the test. In the
2186 future, we may want to include a calculation of the thruput
2187 measured by the remote, but it should be the case that for a
2188 TCP stream test, that the two numbers should be *very*
2189 close... We calculate bytes_sent regardless of the way the
2190 test length was controlled. If it was time, we needed to,
2191 and if it was by bytes, the user may have specified a number
2192 of bytes that wasn't a multiple of the send_size, so we
2193 really didn't send what he asked for ;-) */
2194
2195 bytes_sent = ntohd(tcp_stream_result->bytes_received);
2196 }
2197 else {
2198 bytes_sent = (double)local_bytes_sent;
2199 }
2200
2201 thruput = calc_thruput(bytes_sent);
2202
2203 if (local_cpu_usage || remote_cpu_usage) {
2204 /* We must now do a little math for service demand and cpu */
2205 /* utilization for the system(s) */
2206 /* Of course, some of the information might be bogus because */
2207 /* there was no idle counter in the kernel(s). We need to make */
2208 /* a note of this for the user's benefit...*/
2209 if (local_cpu_usage) {
2210
2211 local_cpu_utilization = calc_cpu_util(0.0);
2212 local_service_demand = calc_service_demand(bytes_sent,
2213 0.0,
2214 0.0,
2215 0);
2216 }
2217 else {
2218 local_cpu_utilization = (float) -1.0;
2219 local_service_demand = (float) -1.0;
2220 }
2221
2222 if (remote_cpu_usage) {
2223
2224 remote_cpu_utilization = tcp_stream_result->cpu_util;
2225 remote_service_demand = calc_service_demand(bytes_sent,
2226 0.0,
2227 remote_cpu_utilization,
2228 tcp_stream_result->num_cpus);
2229 }
2230 else {
2231 remote_cpu_utilization = (float) -1.0;
2232 remote_service_demand = (float) -1.0;
2233 }
2234 }
2235 else {
2236 /* we were not measuring cpu, for the confidence stuff, we */
2237 /* should make it -1.0 */
2238 local_cpu_utilization = (float) -1.0;
2239 local_service_demand = (float) -1.0;
2240 remote_cpu_utilization = (float) -1.0;
2241 remote_service_demand = (float) -1.0;
2242 }
2243
2244 /* at this point, we want to calculate the confidence information. */
2245 /* if debugging is on, calculate_confidence will print-out the */
2246 /* parameters we pass it */
2247
2248 calculate_confidence(confidence_iteration,
2249 elapsed_time,
2250 thruput,
2251 local_cpu_utilization,
2252 remote_cpu_utilization,
2253 local_service_demand,
2254 remote_service_demand);
2255
2256
2257 confidence_iteration++;
2258 }
2259
2260 /* at this point, we have finished making all the runs that we */
2261 /* will be making. so, we should extract what the calcuated values */
2262 /* are for all the confidence stuff. we could make the values */
2263 /* global, but that seemed a little messy, and it did not seem worth */
2264 /* all the mucking with header files. so, we create a routine much */
2265 /* like calcualte_confidence, which just returns the mean values. */
2266 /* raj 11/94 */
2267
2268 retrieve_confident_values(&elapsed_time,
2269 &thruput,
2270 &local_cpu_utilization,
2271 &remote_cpu_utilization,
2272 &local_service_demand,
2273 &remote_service_demand);
2274
2275 /* We are now ready to print all the information. If the user */
2276 /* has specified zero-level verbosity, we will just print the */
2277 /* local service demand, or the remote service demand. If the */
2278 /* user has requested verbosity level 1, he will get the basic */
2279 /* "streamperf" numbers. If the user has specified a verbosity */
2280 /* of greater than 1, we will display a veritable plethora of */
2281 /* background information from outside of this block as it it */
2282 /* not cpu_measurement specific... */
2283
2284 if (confidence < 0) {
2285 /* we did not hit confidence, but were we asked to look for it? */
2286 if (iteration_max > 1) {
2287 display_confidence();
2288 }
2289 }
2290
2291 if (local_cpu_usage || remote_cpu_usage) {
2292 local_cpu_method = format_cpu_method(cpu_method);
2293 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
2294
2295 switch (verbosity) {
2296 case 0:
2297 if (local_cpu_usage) {
2298 fprintf(where,
2299 cpu_fmt_0,
2300 local_service_demand,
2301 local_cpu_method,
2302 ((print_headers) ||
2303 (result_brand == NULL)) ? "" : result_brand);
2304 }
2305 else {
2306 fprintf(where,
2307 cpu_fmt_0,
2308 remote_service_demand,
2309 remote_cpu_method,
2310 ((print_headers) ||
2311 (result_brand == NULL)) ? "" : result_brand);
2312 }
2313 break;
2314 case 1:
2315 case 2:
2316 if (print_headers) {
2317 fprintf(where,
2318 cpu_title,
2319 format_units(),
2320 local_cpu_method,
2321 remote_cpu_method);
2322 }
2323
2324 fprintf(where,
2325 cpu_fmt_1, /* the format string */
2326 rsr_size, /* remote recvbuf size */
2327 lss_size, /* local sendbuf size */
2328 send_size, /* how large were the sends */
2329 elapsed_time, /* how long was the test */
2330 thruput, /* what was the xfer rate */
2331 local_cpu_utilization, /* local cpu */
2332 remote_cpu_utilization, /* remote cpu */
2333 local_service_demand, /* local service demand */
2334 remote_service_demand, /* remote service demand */
2335 ((print_headers) ||
2336 (result_brand == NULL)) ? "" : result_brand);
2337 break;
2338 }
2339 }
2340 else {
2341 /* The tester did not wish to measure service demand. */
2342
2343 switch (verbosity) {
2344 case 0:
2345 fprintf(where,
2346 tput_fmt_0,
2347 thruput,
2348 ((print_headers) ||
2349 (result_brand == NULL)) ? "" : result_brand);
2350 break;
2351 case 1:
2352 case 2:
2353 if (print_headers) {
2354 fprintf(where,tput_title,format_units());
2355 }
2356 fprintf(where,
2357 tput_fmt_1, /* the format string */
2358 rsr_size, /* remote recvbuf size */
2359 lss_size, /* local sendbuf size */
2360 send_size, /* how large were the sends */
2361 elapsed_time, /* how long did it take */
2362 thruput, /* how fast did it go */
2363 ((print_headers) ||
2364 (result_brand == NULL)) ? "" : result_brand);
2365 break;
2366 }
2367 }
2368
2369 /* it would be a good thing to include information about some of the */
2370 /* other parameters that may have been set for this test, but at the */
2371 /* moment, I do not wish to figure-out all the formatting, so I will */
2372 /* just put this comment here to help remind me that it is something */
2373 /* that should be done at a later time. */
2374
2375 if (verbosity > 1) {
2376 /* The user wanted to know it all, so we will give it to him. */
2377 /* This information will include as much as we can find about */
2378 /* TCP statistics, the alignments of the sends and receives */
2379 /* and all that sort of rot... */
2380
2381 /* this stuff needs to be worked-out in the presence of confidence */
2382 /* intervals and multiple iterations of the test... raj 11/94 */
2383
2384 fprintf(where,
2385 ksink_fmt,
2386 "Bytes",
2387 "Bytes",
2388 "Bytes",
2389 local_send_align,
2390 remote_recv_align,
2391 local_send_offset,
2392 remote_recv_offset,
2393 bytes_sent,
2394 bytes_sent / (double)nummessages,
2395 nummessages,
2396 bytes_sent / (double)tcp_stream_result->recv_calls,
2397 tcp_stream_result->recv_calls);
2398 fprintf(where,
2399 ksink_fmt2,
2400 tcp_mss);
2401 fflush(where);
2402 #ifdef WANT_HISTOGRAM
2403 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
2404 fflush(where);
2405 HIST_report(time_hist);
2406 #endif /* WANT_HISTOGRAM */
2407 }
2408
2409 }
2410
2411
2412
2413 /* This routine implements the netperf-side TCP unidirectional data
2414 transfer test (a.k.a. stream) for the sockets interface where the
2415 data flow is from the netserver to the netperf. It receives its
2416 parameters via global variables from the shell and writes its
2417 output to the standard output. */
2418
2419
2420 void
send_tcp_maerts(char remote_host[])2421 send_tcp_maerts(char remote_host[])
2422 {
2423
2424 char *tput_title = "\
2425 Recv Send Send \n\
2426 Socket Socket Message Elapsed \n\
2427 Size Size Size Time Throughput \n\
2428 bytes bytes bytes secs. %s/sec \n\n";
2429
2430 char *tput_fmt_0 =
2431 "%7.2f %s\n";
2432
2433 char *tput_fmt_1 =
2434 "%6d %6d %6d %-6.2f %7.2f %s\n";
2435
2436 char *cpu_title = "\
2437 Recv Send Send Utilization Service Demand\n\
2438 Socket Socket Message Elapsed Recv Send Recv Send\n\
2439 Size Size Size Time Throughput local remote local remote\n\
2440 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
2441
2442 char *cpu_fmt_0 =
2443 "%6.3f %c %s\n";
2444
2445 char *cpu_fmt_1 =
2446 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
2447
2448 char *ksink_fmt = "\n\
2449 Alignment Offset %-8.8s %-8.8s Recvs %-8.8s Sends\n\
2450 Local Remote Local Remote Xfered Per Per\n\
2451 Recv Send Recv Send Recv (avg) Send (avg)\n\
2452 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
2453
2454 char *ksink_fmt2 = "\n\
2455 Maximum\n\
2456 Segment\n\
2457 Size (bytes)\n\
2458 %6d\n";
2459
2460
2461 float elapsed_time;
2462
2463 /* what we want is to have a buffer space that is at least one */
2464 /* recv-size greater than our recv window. this will insure that we */
2465 /* are never trying to re-use a buffer that may still be in the hands */
2466 /* of the transport. This buffer will be malloc'd after we have found */
2467 /* the size of the local senc socket buffer. We will want to deal */
2468 /* with alignment and offset concerns as well. */
2469
2470 struct ring_elt *recv_ring;
2471
2472 int len;
2473 unsigned int nummessages = 0;
2474 SOCKET recv_socket;
2475 int bytes_remaining;
2476 int tcp_mss = -1; /* possibly uninitialized on printf far below */
2477
2478 /* with links like fddi, one can recv > 32 bits worth of bytes
2479 during a test... ;-) at some point, this should probably become a
2480 64bit integral type, but those are not entirely common yet. of
2481 course, time passes and they do become common.
2482 */
2483 double bytes_sent = 0.0;
2484
2485 #if defined(WIN32) && (_MSC_VER < 1200)
2486 __int64 local_bytes_recvd = 0;
2487 #else
2488 unsigned long long local_bytes_recvd = 0;
2489 #endif
2490
2491 float local_cpu_utilization;
2492 float local_service_demand;
2493 float remote_cpu_utilization;
2494 float remote_service_demand;
2495
2496 double thruput;
2497
2498 struct addrinfo *remote_res;
2499 struct addrinfo *local_res;
2500
2501 struct tcp_maerts_request_struct *tcp_maerts_request;
2502 struct tcp_maerts_response_struct *tcp_maerts_response;
2503 struct tcp_maerts_results_struct *tcp_maerts_result;
2504
2505 tcp_maerts_request =
2506 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
2507 tcp_maerts_response =
2508 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
2509 tcp_maerts_result =
2510 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
2511
2512 #ifdef WANT_HISTOGRAM
2513 if (verbosity > 1) {
2514 time_hist = HIST_new();
2515 }
2516 #endif /* WANT_HISTOGRAM */
2517 /* since we are now disconnected from the code that established the */
2518 /* control socket, and since we want to be able to use different */
2519 /* protocols and such, we are passed the name of the remote host and */
2520 /* must turn that into the test specific addressing information. */
2521
2522 complete_addrinfos(&remote_res,
2523 &local_res,
2524 remote_host,
2525 SOCK_STREAM,
2526 IPPROTO_TCP,
2527 0);
2528
2529 if ( print_headers ) {
2530 print_top_test_header("TCP MAERTS TEST",local_res,remote_res);
2531 }
2532
2533 recv_ring = NULL;
2534 confidence_iteration = 1;
2535 init_stat();
2536
2537 /* we have a great-big while loop which controls the number of times */
2538 /* we run a particular test. this is for the calculation of a */
2539 /* confidence interval (I really should have stayed awake during */
2540 /* probstats :). If the user did not request confidence measurement */
2541 /* (no confidence is the default) then we will only go though the */
2542 /* loop once. the confidence stuff originates from the folks at IBM */
2543
2544 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
2545 (confidence_iteration <= iteration_min)) {
2546
2547 /* initialize a few counters. we have to remember that we might be */
2548 /* going through the loop more than once. */
2549
2550 nummessages = 0;
2551 bytes_sent = 0.0;
2552 times_up = 0;
2553
2554 /*set up the data socket */
2555 recv_socket = create_data_socket(local_res);
2556
2557 if (recv_socket == INVALID_SOCKET){
2558 perror("netperf: send_tcp_maerts: tcp stream data socket");
2559 exit(1);
2560 }
2561
2562 if (debug) {
2563 fprintf(where,"send_tcp_maerts: recv_socket obtained...\n");
2564 }
2565
2566 /* at this point, we have either retrieved the socket buffer sizes, */
2567 /* or have tried to set them, so now, we may want to set the recv */
2568 /* size based on that (because the user either did not use a -m */
2569 /* option, or used one with an argument of 0). If the socket buffer */
2570 /* size is not available, we will set the recv size to 4KB - no */
2571 /* particular reason, just arbitrary... */
2572 if (recv_size == 0) {
2573 if (lsr_size > 0) {
2574 recv_size = lsr_size;
2575 }
2576 else {
2577 recv_size = 4096;
2578 }
2579 }
2580
2581 /* set-up the data buffer ring with the requested alignment and offset. */
2582 /* note also that we have allocated a quantity */
2583 /* of memory that is at least one recv-size greater than our socket */
2584 /* buffer size. We want to be sure that there are at least two */
2585 /* buffers allocated - this can be a bit of a problem when the */
2586 /* recv_size is bigger than the socket size, so we must check... the */
2587 /* user may have wanted to explicitly set the "width" of our recv */
2588 /* buffers, we should respect that wish... */
2589 if (recv_width == 0) {
2590 recv_width = (lsr_size/recv_size) + 1;
2591 if (recv_width == 1) recv_width++;
2592 }
2593
2594 if (recv_ring == NULL) {
2595 /* only allocate the recv ring once. this is a networking test, */
2596 /* not a memory allocation test. this way, we do not need a */
2597 /* deallocate_buffer_ring() routine, and I don't feel like */
2598 /* writing one anyway :) raj 11/94 */
2599 recv_ring = allocate_buffer_ring(recv_width,
2600 recv_size,
2601 local_recv_align,
2602 local_recv_offset);
2603 }
2604
2605 /* If the user has requested cpu utilization measurements, we must */
2606 /* calibrate the cpu(s). We will perform this task within the tests */
2607 /* themselves. If the user has specified the cpu rate, then */
2608 /* calibrate_local_cpu will return rather quickly as it will have */
2609 /* nothing to do. If local_cpu_rate is zero, then we will go through */
2610 /* all the "normal" calibration stuff and return the rate back. */
2611
2612 if (local_cpu_usage) {
2613 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
2614 }
2615
2616 if (!no_control) {
2617 /* Tell the remote end to do a listen. The server alters the
2618 socket paramters on the other side at this point, hence the
2619 reason for all the values being passed in the setup
2620 message. If the user did not specify any of the parameters,
2621 they will be passed as 0, which will indicate to the remote
2622 that no changes beyond the system's default should be
2623 used. Alignment is the exception, it will default to 1, which
2624 will be no alignment alterations. */
2625
2626 netperf_request.content.request_type = DO_TCP_MAERTS;
2627 tcp_maerts_request->send_buf_size = rss_size_req;
2628 tcp_maerts_request->recv_buf_size = rsr_size_req;
2629 tcp_maerts_request->send_size = send_size;
2630 tcp_maerts_request->no_delay = rem_nodelay;
2631 tcp_maerts_request->send_alignment = remote_send_align;
2632 tcp_maerts_request->send_offset = remote_send_offset;
2633 tcp_maerts_request->measure_cpu = remote_cpu_usage;
2634 tcp_maerts_request->cpu_rate = remote_cpu_rate;
2635 if (test_time) {
2636 tcp_maerts_request->test_length = test_time;
2637 }
2638 else {
2639 tcp_maerts_request->test_length = test_bytes;
2640 }
2641 tcp_maerts_request->so_rcvavoid = rem_rcvavoid;
2642 tcp_maerts_request->so_sndavoid = rem_sndavoid;
2643 #ifdef DIRTY
2644 tcp_maerts_request->dirty_count = rem_dirty_count;
2645 tcp_maerts_request->clean_count = rem_clean_count;
2646 #endif /* DIRTY */
2647 tcp_maerts_request->port = atoi(remote_data_port);
2648 tcp_maerts_request->ipfamily = af_to_nf(remote_res->ai_family);
2649 if (debug > 1) {
2650 fprintf(where,
2651 "netperf: send_tcp_maerts: requesting TCP maerts test\n");
2652 }
2653
2654 send_request();
2655
2656 /* The response from the remote will contain all of the relevant
2657 socket parameters for this test type. We will put them back
2658 into the variables here so they can be displayed if desired.
2659 The remote will have calibrated CPU if necessary, and will
2660 have done all the needed set-up we will have calibrated the
2661 cpu locally before sending the request, and will grab the
2662 counter value right after the connect returns. The remote
2663 will grab the counter right after the accept call. This saves
2664 the hassle of extra messages being sent for the TCP
2665 tests. */
2666
2667 recv_response();
2668
2669 if (!netperf_response.content.serv_errno) {
2670 if (debug)
2671 fprintf(where,"remote listen done.\n");
2672 rsr_size = tcp_maerts_response->recv_buf_size;
2673 rss_size = tcp_maerts_response->send_buf_size;
2674 rem_nodelay = tcp_maerts_response->no_delay;
2675 remote_cpu_usage= tcp_maerts_response->measure_cpu;
2676 remote_cpu_rate = tcp_maerts_response->cpu_rate;
2677 send_size = tcp_maerts_response->send_size;
2678
2679 /* we have to make sure that the server port number is in
2680 network order */
2681 set_port_number(remote_res,
2682 (short)tcp_maerts_response->data_port_number);
2683 rem_rcvavoid = tcp_maerts_response->so_rcvavoid;
2684 rem_sndavoid = tcp_maerts_response->so_sndavoid;
2685 }
2686 else {
2687 Set_errno(netperf_response.content.serv_errno);
2688 fprintf(where,
2689 "netperf: remote error %d",
2690 netperf_response.content.serv_errno);
2691 perror("");
2692 fflush(where);
2693
2694 exit(1);
2695 }
2696 }
2697
2698 #ifdef WANT_DEMO
2699 demo_stream_setup(lsr_size,rss_size);
2700 #endif
2701
2702 /*Connect up to the remote port on the data socket */
2703 if (connect(recv_socket,
2704 remote_res->ai_addr,
2705 remote_res->ai_addrlen) == INVALID_SOCKET){
2706 perror("netperf: send_tcp_maerts: data socket connect failed");
2707 exit(1);
2708 }
2709
2710 #ifdef WIN32
2711 /* this is used so the timer thread can close the socket out from */
2712 /* under us, which to date is the easiest/cleanest/least */
2713 /* Windows-specific way I can find to force the winsock calls to */
2714 /* return WSAEINTR with the test is over. anything that will run on */
2715 /* 95 and NT and is closer to what netperf expects from Unix signals */
2716 /* and such would be appreciated raj 1/96 */
2717 win_kludge_socket = recv_socket;
2718 #endif /* WIN32 */
2719
2720 /* Data Socket set-up is finished. If there were problems, either */
2721 /* the connect would have failed, or the previous response would */
2722 /* have indicated a problem. I failed to see the value of the */
2723 /* extra message after the accept on the remote. If it failed, */
2724 /* we'll see it here. If it didn't, we might as well start pumping */
2725 /* data. */
2726
2727 /* Set-up the test end conditions. For a maerts test, they can be */
2728 /* either time or byte-count based. */
2729
2730 if (test_time) {
2731 /* The user wanted to end the test after a period of time. */
2732 times_up = 0;
2733 bytes_remaining = 0;
2734 /* in previous revisions, we had the same code repeated throught */
2735 /* all the test suites. this was unnecessary, and meant more */
2736 /* work for me when I wanted to switch to POSIX signals, so I */
2737 /* have abstracted this out into a routine in netlib.c. if you */
2738 /* are experiencing signal problems, you might want to look */
2739 /* there. raj 11/94 */
2740 if (!no_control) {
2741 /* this is a netperf to netserver test, netserver will close
2742 to tell us the test is over, so use PAD_TIME to avoid
2743 causing the netserver fits. */
2744 start_timer(test_time + PAD_TIME);
2745 }
2746 else {
2747 /* this is a netperf to data source test, no PAD_TIME */
2748 start_timer(test_time);
2749 }
2750 }
2751 else {
2752 /* The tester wanted to recv a number of bytes. we don't do that
2753 in a TCP_MAERTS test. sorry. raj 2002-06-21 */
2754 printf("netperf: send_tcp_maerts: test must be timed\n");
2755 exit(1);
2756 }
2757
2758 /* The cpu_start routine will grab the current time and possibly */
2759 /* value of the idle counter for later use in measuring cpu */
2760 /* utilization and/or service demand and thruput. */
2761
2762 cpu_start(local_cpu_usage);
2763
2764 #ifdef WANT_INTERVALS
2765 INTERVALS_INIT();
2766 #endif /* WANT_INTERVALS */
2767
2768 /* before we start, initialize a few variables */
2769
2770 #ifdef WANT_DEMO
2771 if (demo_mode) {
2772 demo_first_timestamp();
2773 }
2774 #endif
2775
2776 /* the test will continue until we either get a zero-byte recv()
2777 on the socket or our failsafe timer expires. most of the time
2778 we trust that we get a zero-byte recieve from the socket. raj
2779 2002-06-21 */
2780
2781 #ifdef WANT_HISTOGRAM
2782 if (verbosity > 1) {
2783 /* timestamp just before we go into recv and then again just
2784 after we come out raj 8/94 */
2785 /* but only if we are actually going to display a histogram. raj
2786 2006-02-07 */
2787 HIST_timestamp(&time_one);
2788 }
2789 #endif /* WANT_HISTOGRAM */
2790
2791 while ((!times_up) && (len=recv(recv_socket,
2792 recv_ring->buffer_ptr,
2793 recv_size,
2794 0)) > 0 ) {
2795
2796 #ifdef WANT_HISTOGRAM
2797 if (verbosity > 1) {
2798 /* timestamp the exit from the recv call and update the histogram */
2799 HIST_timestamp(&time_two);
2800 HIST_add(time_hist,delta_micro(&time_one,&time_two));
2801 }
2802 #endif /* WANT_HISTOGRAM */
2803
2804 #ifdef DIRTY
2805 access_buffer(recv_ring->buffer_ptr,
2806 recv_size,
2807 loc_dirty_count,
2808 loc_clean_count);
2809 #endif /* DIRTY */
2810
2811 #ifdef WANT_DEMO
2812 demo_stream_interval(len);
2813 #endif
2814
2815 #ifdef WANT_INTERVALS
2816 INTERVALS_WAIT();
2817 #endif /* WANT_INTERVALS */
2818
2819 /* now we want to move our pointer to the next position in the */
2820 /* data buffer...we may also want to wrap back to the "beginning" */
2821 /* of the bufferspace, so we will mod the number of messages sent */
2822 /* by the recv width, and use that to calculate the offset to add */
2823 /* to the base pointer. */
2824 nummessages++;
2825 recv_ring = recv_ring->next;
2826 if (bytes_remaining) {
2827 bytes_remaining -= len;
2828 }
2829
2830 local_bytes_recvd += len;
2831
2832 #ifdef WANT_HISTOGRAM
2833 if (verbosity > 1) {
2834 /* make sure we timestamp just before we go into recv */
2835 /* raj 2004-06-15 */
2836 HIST_timestamp(&time_one);
2837 }
2838 #endif /* WANT_HISTOGRAM */
2839
2840 }
2841
2842 /* an EINTR is to be expected when this is a no_control test */
2843 if (((len < 0) || SOCKET_EINTR(len)) && (!no_control)) {
2844 perror("send_tcp_maerts: data recv error");
2845 printf("len was %d\n",len);
2846 exit(1);
2847 }
2848
2849 /* if we get here, it must mean we had a recv return of 0 before
2850 the watchdog timer expired, or the watchdog timer expired and
2851 this was a no_control test */
2852
2853 /* The test is over. Flush the buffers to the remote end. We do a
2854 graceful release to tell the remote we have all the data. */
2855
2856 /* but first, if the verbosity is greater than 1, find-out what */
2857 /* the TCP maximum segment_size was (if possible) */
2858 if (verbosity > 1) {
2859 tcp_mss = -1;
2860 get_tcp_info(recv_socket,&tcp_mss);
2861 }
2862
2863 if (shutdown(recv_socket,SHUT_WR) == SOCKET_ERROR) {
2864 perror("netperf: cannot shutdown tcp maerts socket");
2865 exit(1);
2866 }
2867
2868 stop_timer();
2869
2870 #if defined(WANT_INTERVALS)
2871 #ifdef WIN32
2872 stop_itimer();
2873 #endif
2874 #endif /* WANT_INTERVALS */
2875
2876 /* this call will always give us the local elapsed time for the
2877 test, and will also store-away the necessaries for cpu
2878 utilization */
2879
2880 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
2881 /* measured and how */
2882 /* long did we really */
2883 /* run? */
2884
2885 /* we are finished with the socket, so close it to prevent hitting */
2886 /* the limit on maximum open files. */
2887
2888 close(recv_socket);
2889
2890 if (!no_control) {
2891 /* Get the statistics from the remote end. The remote will have
2892 calculated service demand and all those interesting
2893 things. If it wasn't supposed to care, it will return obvious
2894 values. */
2895
2896 recv_response();
2897 if (!netperf_response.content.serv_errno) {
2898 if (debug)
2899 fprintf(where,"remote results obtained\n");
2900 }
2901 else {
2902 Set_errno(netperf_response.content.serv_errno);
2903 fprintf(where,
2904 "netperf: remote error %d",
2905 netperf_response.content.serv_errno);
2906 perror("");
2907 fflush(where);
2908
2909 exit(1);
2910 }
2911
2912 /* We now calculate what our thruput was for the test. In the
2913 future, we may want to include a calculation of the thruput
2914 measured by the remote, but it should be the case that for a
2915 TCP maerts test, that the two numbers should be *very*
2916 close... We calculate bytes_sent regardless of the way the
2917 test length was controlled. If it was time, we needed to,
2918 and if it was by bytes, the user may have specified a number
2919 of bytes that wasn't a multiple of the recv_size, so we
2920 really didn't recv what he asked for ;-) */
2921
2922 bytes_sent = ntohd(tcp_maerts_result->bytes_sent);
2923 }
2924 else {
2925 bytes_sent = (double)local_bytes_recvd;
2926 }
2927
2928
2929 thruput = calc_thruput(bytes_sent);
2930
2931 if (local_cpu_usage || remote_cpu_usage) {
2932 /* We must now do a little math for service demand and cpu */
2933 /* utilization for the system(s) */
2934 /* Of course, some of the information might be bogus because */
2935 /* there was no idle counter in the kernel(s). We need to make */
2936 /* a note of this for the user's benefit...*/
2937 if (local_cpu_usage) {
2938
2939 local_cpu_utilization = calc_cpu_util(0.0);
2940 local_service_demand = calc_service_demand(bytes_sent,
2941 0.0,
2942 0.0,
2943 0);
2944 }
2945 else {
2946 local_cpu_utilization = (float) -1.0;
2947 local_service_demand = (float) -1.0;
2948 }
2949
2950 if (remote_cpu_usage) {
2951
2952 remote_cpu_utilization = tcp_maerts_result->cpu_util;
2953 remote_service_demand = calc_service_demand(bytes_sent,
2954 0.0,
2955 remote_cpu_utilization,
2956 tcp_maerts_result->num_cpus);
2957 }
2958 else {
2959 remote_cpu_utilization = (float) -1.0;
2960 remote_service_demand = (float) -1.0;
2961 }
2962 }
2963 else {
2964 /* we were not measuring cpu, for the confidence stuff, we */
2965 /* should make it -1.0 */
2966 local_cpu_utilization = (float) -1.0;
2967 local_service_demand = (float) -1.0;
2968 remote_cpu_utilization = (float) -1.0;
2969 remote_service_demand = (float) -1.0;
2970 }
2971
2972 /* at this point, we want to calculate the confidence information. */
2973 /* if debugging is on, calculate_confidence will print-out the */
2974 /* parameters we pass it */
2975
2976 calculate_confidence(confidence_iteration,
2977 elapsed_time,
2978 thruput,
2979 local_cpu_utilization,
2980 remote_cpu_utilization,
2981 local_service_demand,
2982 remote_service_demand);
2983
2984
2985 confidence_iteration++;
2986 }
2987
2988 /* at this point, we have finished making all the runs that we */
2989 /* will be making. so, we should extract what the calcuated values */
2990 /* are for all the confidence stuff. we could make the values */
2991 /* global, but that seemed a little messy, and it did not seem worth */
2992 /* all the mucking with header files. so, we create a routine much */
2993 /* like calcualte_confidence, which just returns the mean values. */
2994 /* raj 11/94 */
2995
2996 retrieve_confident_values(&elapsed_time,
2997 &thruput,
2998 &local_cpu_utilization,
2999 &remote_cpu_utilization,
3000 &local_service_demand,
3001 &remote_service_demand);
3002
3003 /* We are now ready to print all the information. If the user */
3004 /* has specified zero-level verbosity, we will just print the */
3005 /* local service demand, or the remote service demand. If the */
3006 /* user has requested verbosity level 1, he will get the basic */
3007 /* "streamperf" numbers. If the user has specified a verbosity */
3008 /* of greater than 1, we will display a veritable plethora of */
3009 /* background information from outside of this block as it it */
3010 /* not cpu_measurement specific... */
3011
3012 if (confidence < 0) {
3013 /* we did not hit confidence, but were we asked to look for it? */
3014 if (iteration_max > 1) {
3015 display_confidence();
3016 }
3017 }
3018
3019 if (local_cpu_usage || remote_cpu_usage) {
3020 local_cpu_method = format_cpu_method(cpu_method);
3021 remote_cpu_method = format_cpu_method(tcp_maerts_result->cpu_method);
3022
3023 switch (verbosity) {
3024 case 0:
3025 if (local_cpu_usage) {
3026 fprintf(where,
3027 cpu_fmt_0,
3028 local_service_demand,
3029 local_cpu_method,
3030 ((print_headers) ||
3031 (result_brand == NULL)) ? "" : result_brand);
3032 }
3033 else {
3034 fprintf(where,
3035 cpu_fmt_0,
3036 remote_service_demand,
3037 remote_cpu_method,
3038 ((print_headers) ||
3039 (result_brand == NULL)) ? "" : result_brand);
3040 }
3041 break;
3042 case 1:
3043 case 2:
3044 if (print_headers) {
3045 fprintf(where,
3046 cpu_title,
3047 format_units(),
3048 local_cpu_method,
3049 remote_cpu_method);
3050 }
3051
3052 fprintf(where,
3053 cpu_fmt_1, /* the format string */
3054 rsr_size, /* remote recvbuf size */
3055 lss_size, /* local sendbuf size */
3056 send_size, /* how large were the recvs */
3057 elapsed_time, /* how long was the test */
3058 thruput, /* what was the xfer rate */
3059 local_cpu_utilization, /* local cpu */
3060 remote_cpu_utilization, /* remote cpu */
3061 local_service_demand, /* local service demand */
3062 remote_service_demand, /* remote service demand */
3063 ((print_headers) ||
3064 (result_brand == NULL)) ? "" : result_brand);
3065 break;
3066 }
3067 }
3068 else {
3069 /* The tester did not wish to measure service demand. */
3070
3071 switch (verbosity) {
3072 case 0:
3073 fprintf(where,
3074 tput_fmt_0,
3075 thruput,
3076 ((print_headers) ||
3077 (result_brand == NULL)) ? "" : result_brand);
3078 break;
3079 case 1:
3080 case 2:
3081 if (print_headers) {
3082 fprintf(where,tput_title,format_units());
3083 }
3084 fprintf(where,
3085 tput_fmt_1, /* the format string */
3086 lsr_size, /* local recvbuf size */
3087 rss_size, /* remot sendbuf size */
3088 send_size, /* how large were the recvs */
3089 elapsed_time, /* how long did it take */
3090 thruput, /* how fast did it go */
3091 ((print_headers) ||
3092 (result_brand == NULL)) ? "" : result_brand);
3093 break;
3094 }
3095 }
3096
3097 /* it would be a good thing to include information about some of the */
3098 /* other parameters that may have been set for this test, but at the */
3099 /* moment, I do not wish to figure-out all the formatting, so I will */
3100 /* just put this comment here to help remind me that it is something */
3101 /* that should be done at a later time. */
3102
3103 if (verbosity > 1) {
3104 /* The user wanted to know it all, so we will give it to him. */
3105 /* This information will include as much as we can find about */
3106 /* TCP statistics, the alignments of the sends and receives */
3107 /* and all that sort of rot... */
3108
3109 /* this stuff needs to be worked-out in the presence of confidence */
3110 /* intervals and multiple iterations of the test... raj 11/94 */
3111
3112 fprintf(where,
3113 ksink_fmt,
3114 "Bytes",
3115 "Bytes",
3116 "Bytes",
3117 local_recv_align,
3118 remote_recv_align,
3119 local_recv_offset,
3120 remote_recv_offset,
3121 bytes_sent,
3122 bytes_sent / (double)nummessages,
3123 nummessages,
3124 bytes_sent / (double)tcp_maerts_result->send_calls,
3125 tcp_maerts_result->send_calls);
3126 fprintf(where,
3127 ksink_fmt2,
3128 tcp_mss);
3129 fflush(where);
3130 #ifdef WANT_HISTOGRAM
3131 fprintf(where,"\n\nHistogram of time spent in recv() call.\n");
3132 fflush(where);
3133 HIST_report(time_hist);
3134 #endif /* WANT_HISTOGRAM */
3135 }
3136
3137 }
3138 #endif /* WANT_MIGRATION */
3139
3140
3141 /* this routine implements the TCP_MSS test. All it does is pretend
3142 to be a TCP_STREAM test and report the TCP_MSS for the data
3143 connection. No actual data is transferred. raj 2007-11-07
3144 */
3145 void
send_tcp_mss(char remote_host[])3146 send_tcp_mss(char remote_host[])
3147 {
3148
3149 char *mss_title = "\
3150 Maximum\n\
3151 Segment\n\
3152 Size (bytes)\n\n";
3153
3154 char *mss_fmt_0 =
3155 "%d %s\n";
3156
3157 SOCKET send_socket;
3158 int tcp_mss = -1; /* possibly uninitialized on printf far below */
3159
3160 struct addrinfo *remote_res;
3161 struct addrinfo *local_res;
3162
3163 struct tcp_stream_request_struct *tcp_stream_request;
3164 struct tcp_stream_response_struct *tcp_stream_response;
3165 struct tcp_stream_results_struct *tcp_stream_result;
3166
3167 tcp_stream_request =
3168 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
3169 tcp_stream_response =
3170 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
3171 tcp_stream_result =
3172 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
3173
3174 /* since we are now disconnected from the code that established the */
3175 /* control socket, and since we want to be able to use different */
3176 /* protocols and such, we are passed the name of the remote host and */
3177 /* must turn that into the test specific addressing information. */
3178
3179 /* complete_addrinfos will either succede or exit the process */
3180 complete_addrinfos(&remote_res,
3181 &local_res,
3182 remote_host,
3183 SOCK_STREAM,
3184 IPPROTO_TCP,
3185 0);
3186
3187 if ( print_headers ) {
3188 print_top_test_header("TCP MSS TEST",local_res,remote_res);
3189 }
3190
3191 /*set up the data socket */
3192 send_socket = create_data_socket(local_res);
3193
3194 if (send_socket == INVALID_SOCKET){
3195 perror("netperf: send_tcp_stream: tcp stream data socket");
3196 exit(1);
3197 }
3198
3199 if (debug) {
3200 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
3201 }
3202
3203
3204 if (!no_control) {
3205 /* Tell the remote end to do a listen. The server alters the
3206 socket paramters on the other side at this point, hence the
3207 reason for all the values being passed in the setup
3208 message. If the user did not specify any of the parameters,
3209 they will be passed as 0, which will indicate to the remote
3210 that no changes beyond the system's default should be
3211 used. Alignment is the exception, it will default to 1, which
3212 will be no alignment alterations. */
3213
3214 netperf_request.content.request_type = DO_TCP_STREAM;
3215 tcp_stream_request->send_buf_size = rss_size_req;
3216 tcp_stream_request->recv_buf_size = rsr_size_req;
3217 tcp_stream_request->receive_size = recv_size;
3218 tcp_stream_request->no_delay = rem_nodelay;
3219 tcp_stream_request->recv_alignment = remote_recv_align;
3220 tcp_stream_request->recv_offset = remote_recv_offset;
3221 tcp_stream_request->measure_cpu = remote_cpu_usage;
3222 tcp_stream_request->cpu_rate = remote_cpu_rate;
3223 if (test_time) {
3224 tcp_stream_request->test_length = test_time;
3225 }
3226 else {
3227 tcp_stream_request->test_length = test_bytes;
3228 }
3229 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
3230 tcp_stream_request->so_sndavoid = rem_sndavoid;
3231 #ifdef DIRTY
3232 tcp_stream_request->dirty_count = rem_dirty_count;
3233 tcp_stream_request->clean_count = rem_clean_count;
3234 #endif /* DIRTY */
3235 tcp_stream_request->port = atoi(remote_data_port);
3236 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
3237 if (debug > 1) {
3238 fprintf(where,
3239 "netperf: send_tcp_mss: requesting TCP stream test\n");
3240 }
3241
3242 send_request();
3243
3244 /* The response from the remote will contain all of the relevant
3245 socket parameters for this test type. We will put them back
3246 into the variables here so they can be displayed if desired.
3247 The remote will have calibrated CPU if necessary, and will
3248 have done all the needed set-up we will have calibrated the
3249 cpu locally before sending the request, and will grab the
3250 counter value right after the connect returns. The remote
3251 will grab the counter right after the accept call. This saves
3252 the hassle of extra messages being sent for the TCP
3253 tests. */
3254
3255 recv_response();
3256
3257 if (!netperf_response.content.serv_errno) {
3258 if (debug)
3259 fprintf(where,"remote listen done.\n");
3260 rsr_size = tcp_stream_response->recv_buf_size;
3261 rss_size = tcp_stream_response->send_buf_size;
3262 rem_nodelay = tcp_stream_response->no_delay;
3263 remote_cpu_usage= tcp_stream_response->measure_cpu;
3264 remote_cpu_rate = tcp_stream_response->cpu_rate;
3265
3266 /* we have to make sure that the server port number is in
3267 network order */
3268 set_port_number(remote_res,
3269 (short)tcp_stream_response->data_port_number);
3270
3271 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
3272 rem_sndavoid = tcp_stream_response->so_sndavoid;
3273 }
3274 else {
3275 Set_errno(netperf_response.content.serv_errno);
3276 fprintf(where,
3277 "netperf: remote error %d",
3278 netperf_response.content.serv_errno);
3279 perror("");
3280 fflush(where);
3281
3282 exit(1);
3283 }
3284 }
3285
3286 /*Connect up to the remote port on the data socket */
3287 if (connect(send_socket,
3288 remote_res->ai_addr,
3289 remote_res->ai_addrlen) == INVALID_SOCKET){
3290 perror("netperf: send_tcp_mss: data socket connect failed");
3291 exit(1);
3292 }
3293
3294
3295 /* find-out what the TCP maximum segment_size was (if possible) */
3296 tcp_mss = -1;
3297 get_tcp_info(send_socket,&tcp_mss);
3298
3299 /* just go ahead and close the socket, the remote should figure it
3300 out */
3301 close(send_socket);
3302
3303 /* statistics? we don't need no stinking statistics */
3304
3305
3306 switch (verbosity) {
3307 case 0:
3308 fprintf(where,
3309 mss_fmt_0,
3310 tcp_mss,
3311 ((print_headers) ||
3312 (result_brand == NULL)) ? "" : result_brand);
3313 break;
3314 case 1:
3315 case 2:
3316 if (print_headers) {
3317 fprintf(where,"%s",mss_title);
3318 }
3319 fprintf(where,
3320 mss_fmt_0, /* the format string */
3321 tcp_mss,
3322 ((print_headers) ||
3323 (result_brand == NULL)) ? "" : result_brand);
3324 break;
3325 }
3326
3327
3328 }
3329
3330
3331
3332 #ifdef HAVE_ICSC_EXS
3333
3334 #include <sys/exs.h>
3335
3336
3337 /* This routine implements the TCP unidirectional data transfer test */
3338 /* (a.k.a. stream) for the sockets interface. It receives its */
3339 /* parameters via global variables from the shell and writes its */
3340 /* output to the standard output. */
3341
3342 void
send_exs_tcp_stream(char remote_host[])3343 send_exs_tcp_stream(char remote_host[])
3344 {
3345
3346 char *tput_title = "\
3347 Recv Send Send \n\
3348 Socket Socket Message Elapsed \n\
3349 Size Size Size Time Throughput \n\
3350 bytes bytes bytes secs. %s/sec \n\n";
3351
3352 char *tput_fmt_0 =
3353 "%7.2f\n";
3354
3355 char *tput_fmt_1 =
3356 "%6d %6d %6d %-6.2f %7.2f \n";
3357
3358 char *cpu_title = "\
3359 Recv Send Send Utilization Service Demand\n\
3360 Socket Socket Message Elapsed Send Recv Send Recv\n\
3361 Size Size Size Time Throughput local remote local remote\n\
3362 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
3363
3364 char *cpu_fmt_0 =
3365 "%6.3f %c\n";
3366
3367 char *cpu_fmt_1 =
3368 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
3369
3370 char *ksink_fmt = "\n\
3371 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
3372 Local Remote Local Remote Xfered Per Per\n\
3373 Send Recv Send Recv Send (avg) Recv (avg)\n\
3374 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
3375
3376 char *ksink_fmt2 = "\n\
3377 Maximum\n\
3378 Segment\n\
3379 Size (bytes)\n\
3380 %6d\n";
3381
3382
3383 float elapsed_time;
3384
3385 /* what we want is to have a buffer space that is at least one */
3386 /* send-size greater than our send window. this will insure that we */
3387 /* are never trying to re-use a buffer that may still be in the hands */
3388 /* of the transport. This buffer will be malloc'd after we have found */
3389 /* the size of the local senc socket buffer. We will want to deal */
3390 /* with alignment and offset concerns as well. */
3391
3392 struct ring_elt *send_ring;
3393
3394 int len;
3395 unsigned int nummessages = 0;
3396 SOCKET send_socket;
3397 int bytes_remaining;
3398 int tcp_mss = -1; /* possibly uninitialized on printf far below */
3399
3400 exs_mhandle_t exs_mhandle;
3401 exs_qhandle_t exs_qhandle;
3402 #define NETPERF_EXS_PENDING 16
3403 int exs_aio_pending;
3404 int exs_aio_eagain;
3405 int exs_aio_dequeued;
3406 int exs_aio_dequeuecnt;
3407 int exs_evtcnt;
3408 #define NETPERF_EXS_QSIZE 128
3409 exs_event_t exs_evtvec[NETPERF_EXS_QSIZE];
3410
3411 /* with links like fddi, one can send > 32 bits worth of bytes */
3412 /* during a test... ;-) at some point, this should probably become a */
3413 /* 64bit integral type, but those are not entirely common yet */
3414
3415 double bytes_sent = 0.0;
3416
3417 float local_cpu_utilization;
3418 float local_service_demand;
3419 float remote_cpu_utilization;
3420 float remote_service_demand;
3421
3422 double thruput;
3423
3424 struct addrinfo *remote_res;
3425 struct addrinfo *local_res;
3426
3427 struct tcp_stream_request_struct *tcp_stream_request;
3428 struct tcp_stream_response_struct *tcp_stream_response;
3429 struct tcp_stream_results_struct *tcp_stream_result;
3430
3431 tcp_stream_request =
3432 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
3433 tcp_stream_response =
3434 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
3435 tcp_stream_result =
3436 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
3437
3438 #if 0 /* def WANT_HISTOGRAM */
3439 time_hist = HIST_new();
3440 #endif /* WANT_HISTOGRAM */
3441 /* since we are now disconnected from the code that established the */
3442 /* control socket, and since we want to be able to use different */
3443 /* protocols and such, we are passed the name of the remote host and */
3444 /* must turn that into the test specific addressing information. */
3445
3446 /* complete_addrinfos will either succede or exit the process */
3447 complete_addrinfos(&remote_res,
3448 &local_res,
3449 remote_host,
3450 SOCK_STREAM,
3451 IPPROTO_TCP,
3452 0);
3453
3454 if ( print_headers ) {
3455 print_top_test_header("EXS TCP STREAM TEST",local_res,remote_res);
3456 }
3457
3458 send_ring = NULL;
3459 confidence_iteration = 1;
3460 init_stat();
3461
3462 /* initialize EXS API and create event queue */
3463 if (exs_init (EXS_VERSION) == -1) {
3464 perror ("netperf: send_exs_tcp_stream: exs_init failed");
3465 exit (1);
3466 }
3467
3468 if ((exs_qhandle = exs_qcreate (NETPERF_EXS_QSIZE)) == EXS_QHANDLE_INVALID) {
3469 perror ("netperf: send_exs_tcp_stream: exs_qcreate failed");
3470 exit (1);
3471 }
3472 if (debug) {
3473 fprintf (where, "send_exs_tcp_stream: qhandle=%d\n", exs_qhandle);
3474 }
3475
3476 /* we have a great-big while loop which controls the number of times */
3477 /* we run a particular test. this is for the calculation of a */
3478 /* confidence interval (I really should have stayed awake during */
3479 /* probstats :). If the user did not request confidence measurement */
3480 /* (no confidence is the default) then we will only go though the */
3481 /* loop once. the confidence stuff originates from the folks at IBM */
3482
3483 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
3484 (confidence_iteration <= iteration_min)) {
3485
3486 /* initialize a few counters. we have to remember that we might be */
3487 /* going through the loop more than once. */
3488
3489 nummessages = 0;
3490 bytes_sent = 0.0;
3491 times_up = 0;
3492
3493 /*set up the data socket */
3494 send_socket = create_data_socket(local_res);
3495
3496 if (send_socket == INVALID_SOCKET){
3497 perror("netperf: send_tcp_stream: tcp stream data socket");
3498 exit(1);
3499 }
3500
3501 if (debug) {
3502 fprintf(where,"send_tcp_stream: send_socket obtained...\n");
3503 }
3504
3505 /* at this point, we have either retrieved the socket buffer sizes, */
3506 /* or have tried to set them, so now, we may want to set the send */
3507 /* size based on that (because the user either did not use a -m */
3508 /* option, or used one with an argument of 0). If the socket buffer */
3509 /* size is not available, we will set the send size to 4KB - no */
3510 /* particular reason, just arbitrary... */
3511 if (send_size == 0) {
3512 if (lss_size > 0) {
3513 send_size = lss_size;
3514 }
3515 else {
3516 send_size = 4096;
3517 }
3518 }
3519
3520 /* set-up the data buffer ring with the requested alignment and offset. */
3521 /* note also that we have allocated a quantity */
3522 /* of memory that is at least one send-size greater than our socket */
3523 /* buffer size. We want to be sure that there are at least two */
3524 /* buffers allocated - this can be a bit of a problem when the */
3525 /* send_size is bigger than the socket size, so we must check... the */
3526 /* user may have wanted to explicitly set the "width" of our send */
3527 /* buffers, we should respect that wish... */
3528 if (send_width == 0) {
3529 send_width = (lss_size/send_size) + 1;
3530 if (send_width == 1) send_width++;
3531 }
3532
3533 if (send_ring == NULL) {
3534 /* only allocate the send ring once. this is a networking test, */
3535 /* not a memory allocation test. this way, we do not need a */
3536 /* deallocate_buffer_ring() routine, and I don't feel like */
3537 /* writing one anyway :) raj 11/94 */
3538 send_ring = allocate_exs_buffer_ring(send_width,
3539 send_size,
3540 local_send_align,
3541 local_send_offset,
3542 &exs_mhandle);
3543 }
3544
3545 /* If the user has requested cpu utilization measurements, we must */
3546 /* calibrate the cpu(s). We will perform this task within the tests */
3547 /* themselves. If the user has specified the cpu rate, then */
3548 /* calibrate_local_cpu will return rather quickly as it will have */
3549 /* nothing to do. If local_cpu_rate is zero, then we will go through */
3550 /* all the "normal" calibration stuff and return the rate back. */
3551
3552 if (local_cpu_usage) {
3553 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
3554 }
3555
3556 /* Tell the remote end to do a listen. The server alters the socket */
3557 /* paramters on the other side at this point, hence the reason for */
3558 /* all the values being passed in the setup message. If the user did */
3559 /* not specify any of the parameters, they will be passed as 0, which */
3560 /* will indicate to the remote that no changes beyond the system's */
3561 /* default should be used. Alignment is the exception, it will */
3562 /* default to 1, which will be no alignment alterations. */
3563
3564 netperf_request.content.request_type = DO_TCP_STREAM;
3565 tcp_stream_request->send_buf_size = rss_size_req;
3566 tcp_stream_request->recv_buf_size = rsr_size_req;
3567 tcp_stream_request->receive_size = recv_size;
3568 tcp_stream_request->no_delay = rem_nodelay;
3569 tcp_stream_request->recv_alignment = remote_recv_align;
3570 tcp_stream_request->recv_offset = remote_recv_offset;
3571 tcp_stream_request->measure_cpu = remote_cpu_usage;
3572 tcp_stream_request->cpu_rate = remote_cpu_rate;
3573 if (test_time) {
3574 tcp_stream_request->test_length = test_time;
3575 }
3576 else {
3577 tcp_stream_request->test_length = test_bytes;
3578 }
3579 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
3580 tcp_stream_request->so_sndavoid = rem_sndavoid;
3581 #ifdef DIRTY
3582 tcp_stream_request->dirty_count = rem_dirty_count;
3583 tcp_stream_request->clean_count = rem_clean_count;
3584 #endif /* DIRTY */
3585 tcp_stream_request->port = atoi(remote_data_port);
3586 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
3587 if (debug > 1) {
3588 fprintf(where,
3589 "netperf: send_tcp_stream: requesting TCP stream test\n");
3590 }
3591
3592 send_request();
3593
3594 /* The response from the remote will contain all of the relevant */
3595 /* socket parameters for this test type. We will put them back into */
3596 /* the variables here so they can be displayed if desired. The */
3597 /* remote will have calibrated CPU if necessary, and will have done */
3598 /* all the needed set-up we will have calibrated the cpu locally */
3599 /* before sending the request, and will grab the counter value right*/
3600 /* after the connect returns. The remote will grab the counter right*/
3601 /* after the accept call. This saves the hassle of extra messages */
3602 /* being sent for the TCP tests. */
3603
3604 recv_response();
3605
3606 if (!netperf_response.content.serv_errno) {
3607 if (debug)
3608 fprintf(where,"remote listen done.\n");
3609 rsr_size = tcp_stream_response->recv_buf_size;
3610 rss_size = tcp_stream_response->send_buf_size;
3611 rem_nodelay = tcp_stream_response->no_delay;
3612 remote_cpu_usage= tcp_stream_response->measure_cpu;
3613 remote_cpu_rate = tcp_stream_response->cpu_rate;
3614
3615 /* we have to make sure that the server port number is in */
3616 /* network order */
3617 set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
3618
3619 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
3620 rem_sndavoid = tcp_stream_response->so_sndavoid;
3621 }
3622 else {
3623 Set_errno(netperf_response.content.serv_errno);
3624 fprintf(where,
3625 "netperf: remote error %d",
3626 netperf_response.content.serv_errno);
3627 perror("");
3628 fflush(where);
3629
3630 exit(1);
3631 }
3632
3633 #if 0 /* def WANT_DEMO */
3634 demo_stream_setup(lss_size,rsr_size);
3635 #endif
3636
3637 /*Connect up to the remote port on the data socket */
3638 if (connect(send_socket,
3639 remote_res->ai_addr,
3640 remote_res->ai_addrlen) == INVALID_SOCKET){
3641 perror("netperf: send_tcp_stream: data socket connect failed");
3642 exit(1);
3643 }
3644
3645 #ifdef WIN32
3646 /* this is used so the timer thread can close the socket out from */
3647 /* under us, which to date is the easiest/cleanest/least */
3648 /* Windows-specific way I can find to force the winsock calls to */
3649 /* return WSAEINTR with the test is over. anything that will run on */
3650 /* 95 and NT and is closer to what netperf expects from Unix signals */
3651 /* and such would be appreciated raj 1/96 */
3652 win_kludge_socket = send_socket;
3653 #endif /* WIN32 */
3654
3655 /* Data Socket set-up is finished. If there were problems, either */
3656 /* the connect would have failed, or the previous response would */
3657 /* have indicated a problem. I failed to see the value of the */
3658 /* extra message after the accept on the remote. If it failed, */
3659 /* we'll see it here. If it didn't, we might as well start pumping */
3660 /* data. */
3661
3662 /* Set-up the test end conditions. For a stream test, they can be */
3663 /* either time or byte-count based. */
3664
3665 if (test_time) {
3666 /* The user wanted to end the test after a period of time. */
3667 times_up = 0;
3668 bytes_remaining = 0;
3669 /* in previous revisions, we had the same code repeated throught */
3670 /* all the test suites. this was unnecessary, and meant more */
3671 /* work for me when I wanted to switch to POSIX signals, so I */
3672 /* have abstracted this out into a routine in netlib.c. if you */
3673 /* are experiencing signal problems, you might want to look */
3674 /* there. raj 11/94 */
3675 start_timer(test_time);
3676 }
3677 else {
3678 /* The tester wanted to send a number of bytes. */
3679 bytes_remaining = test_bytes;
3680 times_up = 1;
3681 }
3682
3683 /* The cpu_start routine will grab the current time and possibly */
3684 /* value of the idle counter for later use in measuring cpu */
3685 /* utilization and/or service demand and thruput. */
3686
3687 cpu_start(local_cpu_usage);
3688
3689 #if 0 /* def WANT_INTERVALS */
3690 INTERVALS_INIT();
3691 #endif /* WANT_INTERVALS */
3692
3693 /* before we start, initialize a few variables */
3694
3695 #if 0 /* def WANT_DEMO */
3696 if (demo_mode) {
3697 demo_first_timestamp();
3698 }
3699 #endif
3700
3701
3702 /* We use an "OR" to control test execution. When the test is */
3703 /* controlled by time, the byte count check will always return false. */
3704 /* When the test is controlled by byte count, the time test will */
3705 /* always return false. When the test is finished, the whole */
3706 /* expression will go false and we will stop sending data. */
3707
3708 exs_aio_pending = 0;
3709 exs_aio_eagain = 0;
3710 exs_aio_dequeuecnt = 0;
3711
3712 while ((!times_up) || (bytes_remaining > 0)) {
3713
3714 #ifdef DIRTY
3715 access_buffer(send_ring->buffer_ptr,
3716 send_size,
3717 loc_dirty_count,
3718 loc_clean_count);
3719 #endif /* DIRTY */
3720
3721 #if 0 /* def WANT_HISTOGRAM */
3722 /* timestamp just before we go into send and then again just after */
3723 /* we come out raj 8/94 */
3724 HIST_timestamp(&time_one);
3725 #endif /* WANT_HISTOGRAM */
3726
3727
3728 /* post up to NETPERF_EXS_PENDING I/Os */
3729 while ((exs_aio_pending < NETPERF_EXS_PENDING) &&
3730 (exs_send (send_socket, send_ring->buffer_ptr, send_size,
3731 0, exs_qhandle, (exs_ahandle_t)-1, exs_mhandle) == 0)) {
3732 exs_aio_pending++;
3733
3734 /* now we want to move our pointer to the next
3735 position in the data buffer...we may also want to
3736 wrap back to the "beginning" of the bufferspace, so
3737 we will mod the number of messages sent by the send
3738 width, and use that to calculate the offset to add
3739 to the base pointer. */
3740
3741 nummessages++;
3742 send_ring = send_ring->next;
3743 if (bytes_remaining) {
3744 bytes_remaining -= send_size;
3745 }
3746 }
3747
3748 /* check exs_send result */
3749 if (exs_aio_pending < NETPERF_EXS_PENDING) {
3750 /* standard flow control case */
3751 if (errno == EAGAIN)
3752 exs_aio_eagain++;
3753 /* case of times_up */
3754 else if (errno == EINTR)
3755 break;
3756 /* strange, let's stop */
3757 else {
3758 perror ("netperf: exs_send error");
3759 exit (1);
3760 }
3761 }
3762
3763 /* dequeue events with "threshold" on 1/2 posted */
3764 exs_aio_dequeued =
3765 exs_qdequeue (exs_qhandle, exs_evtvec,
3766 -(exs_aio_pending>>1), NULL);
3767 exs_aio_dequeuecnt++;
3768
3769 /* check exs_dequeue result */
3770 if (exs_aio_dequeued < 0) {
3771 /* case of times_up */
3772 if (errno == EINTR)
3773 break;
3774 /* strange, let's stop */
3775 else {
3776 perror ("netperf: exs_send error");
3777 exit (1);
3778 }
3779 }
3780 /* update number of pending I/Os */
3781 else {
3782 exs_aio_pending -= exs_aio_dequeued;
3783 }
3784
3785
3786 #if 0 /* def WANT_HISTOGRAM */
3787 /* timestamp the exit from the send call and update the histogram */
3788 HIST_timestamp(&time_two);
3789 HIST_add(time_hist,delta_micro(&time_one,&time_two));
3790 #endif /* WANT_HISTOGRAM */
3791
3792 #if 0 /* def WANT_DEMO */
3793 demo_stream_interval(send_size);
3794 #endif
3795
3796 #if 0 /* def WANT_INTERVALS */
3797 INTERVALS_WAIT();
3798 #endif /* WANT_INTERVALS */
3799
3800 }
3801
3802 /* Collect the last completion events */
3803 exs_aio_dequeued =
3804 exs_qdequeue (exs_qhandle, exs_evtvec, -exs_aio_pending, NULL);
3805 exs_aio_dequeuecnt++;
3806 /* check exs_dequeue result and update number of pending I/Os */
3807 if (exs_aio_dequeued < 0) {
3808 perror ("netperf: exs_send error");
3809 exit (1);
3810 }
3811 exs_aio_pending -= exs_aio_dequeued;
3812
3813 /* Display some async I/O debug info */
3814 if (debug) {
3815 fprintf (where, "send_exs_tcp_stream: "
3816 "aio sent=%d eagain=%d dequeue=%d pending=%d\n",
3817 nummessages, exs_aio_eagain, exs_aio_dequeuecnt, exs_aio_pending);
3818 }
3819
3820 /* The test is over. Flush the buffers to the remote end. We do a */
3821 /* graceful release to insure that all data has been taken by the */
3822 /* remote. */
3823
3824 /* but first, if the verbosity is greater than 1, find-out what */
3825 /* the TCP maximum segment_size was (if possible) */
3826 if (verbosity > 1) {
3827 tcp_mss = -1;
3828 get_tcp_info(send_socket,&tcp_mss);
3829 }
3830
3831 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
3832 perror("netperf: cannot shutdown tcp stream socket");
3833 exit(1);
3834 }
3835
3836 /* hang a recv() off the socket to block until the remote has */
3837 /* brought all the data up into the application. it will do a */
3838 /* shutdown to cause a FIN to be sent our way. We will assume that */
3839 /* any exit from the recv() call is good... raj 4/93 */
3840
3841 recv(send_socket, send_ring->buffer_ptr, send_size, 0);
3842
3843 /* this call will always give us the elapsed time for the test, and */
3844 /* will also store-away the necessaries for cpu utilization */
3845
3846 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
3847 /* measured and how */
3848 /* long did we really */
3849 /* run? */
3850
3851 /* we are finished with the socket, so close it to prevent hitting */
3852 /* the limit on maximum open files. */
3853
3854 close(send_socket);
3855
3856 /* Get the statistics from the remote end. The remote will have */
3857 /* calculated service demand and all those interesting things. If it */
3858 /* wasn't supposed to care, it will return obvious values. */
3859
3860 recv_response();
3861 if (!netperf_response.content.serv_errno) {
3862 if (debug)
3863 fprintf(where,"remote results obtained\n");
3864 }
3865 else {
3866 Set_errno(netperf_response.content.serv_errno);
3867 fprintf(where,
3868 "netperf: remote error %d",
3869 netperf_response.content.serv_errno);
3870 perror("");
3871 fflush(where);
3872
3873 exit(1);
3874 }
3875
3876 /* We now calculate what our thruput was for the test. In the future, */
3877 /* we may want to include a calculation of the thruput measured by */
3878 /* the remote, but it should be the case that for a TCP stream test, */
3879 /* that the two numbers should be *very* close... We calculate */
3880 /* bytes_sent regardless of the way the test length was controlled. */
3881 /* If it was time, we needed to, and if it was by bytes, the user may */
3882 /* have specified a number of bytes that wasn't a multiple of the */
3883 /* send_size, so we really didn't send what he asked for ;-) */
3884
3885 bytes_sent = ntohd(tcp_stream_result->bytes_received);
3886
3887 thruput = calc_thruput(bytes_sent);
3888
3889 if (local_cpu_usage || remote_cpu_usage) {
3890 /* We must now do a little math for service demand and cpu */
3891 /* utilization for the system(s) */
3892 /* Of course, some of the information might be bogus because */
3893 /* there was no idle counter in the kernel(s). We need to make */
3894 /* a note of this for the user's benefit...*/
3895 if (local_cpu_usage) {
3896
3897 local_cpu_utilization = calc_cpu_util(0.0);
3898 local_service_demand = calc_service_demand(bytes_sent,
3899 0.0,
3900 0.0,
3901 0);
3902 }
3903 else {
3904 local_cpu_utilization = (float) -1.0;
3905 local_service_demand = (float) -1.0;
3906 }
3907
3908 if (remote_cpu_usage) {
3909
3910 remote_cpu_utilization = tcp_stream_result->cpu_util;
3911 remote_service_demand = calc_service_demand(bytes_sent,
3912 0.0,
3913 remote_cpu_utilization,
3914 tcp_stream_result->num_cpus);
3915 }
3916 else {
3917 remote_cpu_utilization = (float) -1.0;
3918 remote_service_demand = (float) -1.0;
3919 }
3920 }
3921 else {
3922 /* we were not measuring cpu, for the confidence stuff, we */
3923 /* should make it -1.0 */
3924 local_cpu_utilization = (float) -1.0;
3925 local_service_demand = (float) -1.0;
3926 remote_cpu_utilization = (float) -1.0;
3927 remote_service_demand = (float) -1.0;
3928 }
3929
3930 /* at this point, we want to calculate the confidence information. */
3931 /* if debugging is on, calculate_confidence will print-out the */
3932 /* parameters we pass it */
3933
3934 calculate_confidence(confidence_iteration,
3935 elapsed_time,
3936 thruput,
3937 local_cpu_utilization,
3938 remote_cpu_utilization,
3939 local_service_demand,
3940 remote_service_demand);
3941
3942
3943 confidence_iteration++;
3944 }
3945
3946 /* at this point, we have finished making all the runs that we */
3947 /* will be making. so, we should extract what the calcuated values */
3948 /* are for all the confidence stuff. we could make the values */
3949 /* global, but that seemed a little messy, and it did not seem worth */
3950 /* all the mucking with header files. so, we create a routine much */
3951 /* like calcualte_confidence, which just returns the mean values. */
3952 /* raj 11/94 */
3953
3954 retrieve_confident_values(&elapsed_time,
3955 &thruput,
3956 &local_cpu_utilization,
3957 &remote_cpu_utilization,
3958 &local_service_demand,
3959 &remote_service_demand);
3960
3961 /* We are now ready to print all the information. If the user */
3962 /* has specified zero-level verbosity, we will just print the */
3963 /* local service demand, or the remote service demand. If the */
3964 /* user has requested verbosity level 1, he will get the basic */
3965 /* "streamperf" numbers. If the user has specified a verbosity */
3966 /* of greater than 1, we will display a veritable plethora of */
3967 /* background information from outside of this block as it it */
3968 /* not cpu_measurement specific... */
3969
3970 if (confidence < 0) {
3971 /* we did not hit confidence, but were we asked to look for it? */
3972 if (iteration_max > 1) {
3973 display_confidence();
3974 }
3975 }
3976
3977 if (local_cpu_usage || remote_cpu_usage) {
3978 local_cpu_method = format_cpu_method(cpu_method);
3979 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
3980
3981 switch (verbosity) {
3982 case 0:
3983 if (local_cpu_usage) {
3984 fprintf(where,
3985 cpu_fmt_0,
3986 local_service_demand,
3987 local_cpu_method);
3988 }
3989 else {
3990 fprintf(where,
3991 cpu_fmt_0,
3992 remote_service_demand,
3993 remote_cpu_method);
3994 }
3995 break;
3996 case 1:
3997 case 2:
3998 if (print_headers) {
3999 fprintf(where,
4000 cpu_title,
4001 format_units(),
4002 local_cpu_method,
4003 remote_cpu_method);
4004 }
4005
4006 fprintf(where,
4007 cpu_fmt_1, /* the format string */
4008 rsr_size, /* remote recvbuf size */
4009 lss_size, /* local sendbuf size */
4010 send_size, /* how large were the sends */
4011 elapsed_time, /* how long was the test */
4012 thruput, /* what was the xfer rate */
4013 local_cpu_utilization, /* local cpu */
4014 remote_cpu_utilization, /* remote cpu */
4015 local_service_demand, /* local service demand */
4016 remote_service_demand); /* remote service demand */
4017 break;
4018 }
4019 }
4020 else {
4021 /* The tester did not wish to measure service demand. */
4022
4023 switch (verbosity) {
4024 case 0:
4025 fprintf(where,
4026 tput_fmt_0,
4027 thruput);
4028 break;
4029 case 1:
4030 case 2:
4031 if (print_headers) {
4032 fprintf(where,tput_title,format_units());
4033 }
4034 fprintf(where,
4035 tput_fmt_1, /* the format string */
4036 rsr_size, /* remote recvbuf size */
4037 lss_size, /* local sendbuf size */
4038 send_size, /* how large were the sends */
4039 elapsed_time, /* how long did it take */
4040 thruput);/* how fast did it go */
4041 break;
4042 }
4043 }
4044
4045 /* it would be a good thing to include information about some of the */
4046 /* other parameters that may have been set for this test, but at the */
4047 /* moment, I do not wish to figure-out all the formatting, so I will */
4048 /* just put this comment here to help remind me that it is something */
4049 /* that should be done at a later time. */
4050
4051 if (verbosity > 1) {
4052 /* The user wanted to know it all, so we will give it to him. */
4053 /* This information will include as much as we can find about */
4054 /* TCP statistics, the alignments of the sends and receives */
4055 /* and all that sort of rot... */
4056
4057 /* this stuff needs to be worked-out in the presence of confidence */
4058 /* intervals and multiple iterations of the test... raj 11/94 */
4059
4060 fprintf(where,
4061 ksink_fmt,
4062 "Bytes",
4063 "Bytes",
4064 "Bytes",
4065 local_send_align,
4066 remote_recv_align,
4067 local_send_offset,
4068 remote_recv_offset,
4069 bytes_sent,
4070 bytes_sent / (double)nummessages,
4071 nummessages,
4072 bytes_sent / (double)tcp_stream_result->recv_calls,
4073 tcp_stream_result->recv_calls);
4074 fprintf(where,
4075 ksink_fmt2,
4076 tcp_mss);
4077 fflush(where);
4078 #if 0 /* def WANT_HISTOGRAM */
4079 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
4080 fflush(where);
4081 HIST_report(time_hist);
4082 #endif /* WANT_HISTOGRAM */
4083 }
4084
4085 }
4086
4087 #endif /* HAVE_ICSC_EXS */
4088
4089
4090
4091 #if defined(HAVE_SENDFILE)
4092
4093
4094 /* This routine implements the TCP unidirectional data transfer test
4095 (a.k.a. stream) for the sockets interface using the sendfile()
4096 system call - TCP_SENDFILE. It receives its parameters via global
4097 variables from the shell and writes its output to the standard
4098 output. Basically, this is the same test as the send_tcp_stream()
4099 logic and we even tell the remote to do a TCP_STREAM test since for
4100 all it knows, nothig is different. */
4101
4102 void
sendfile_tcp_stream(remote_host)4103 sendfile_tcp_stream(remote_host)
4104 char remote_host[];
4105 {
4106
4107 char *tput_title = "\
4108 Recv Send Send \n\
4109 Socket Socket Message Elapsed \n\
4110 Size Size Size Time Throughput \n\
4111 bytes bytes bytes secs. %s/sec \n\n";
4112
4113 char *tput_fmt_0 =
4114 "%7.2f %s\n";
4115
4116 char *tput_fmt_1 =
4117 "%6d %6d %6d %-6.2f %7.2f %s\n";
4118
4119 char *cpu_title = "\
4120 Recv Send Send Utilization Service Demand\n\
4121 Socket Socket Message Elapsed Send Recv Send Recv\n\
4122 Size Size Size Time Throughput local remote local remote\n\
4123 bytes bytes bytes secs. %-8.8s/s %% %c %% %c us/KB us/KB\n\n";
4124
4125 char *cpu_fmt_0 =
4126 "%6.3f %c %s\n";
4127 char *cpu_fmt_1 =
4128 "%6d %6d %6d %-6.2f %7.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
4129
4130 char *ksink_fmt = "\n\
4131 Alignment Offset %-8.8s %-8.8s Sends %-8.8s Recvs\n\
4132 Local Remote Local Remote Xfered Per Per\n\
4133 Send Recv Send Recv Send (avg) Recv (avg)\n\
4134 %5d %5d %5d %5d %6.4g %6.2f %6d %6.2f %6d\n";
4135
4136 char *ksink_fmt2 = "\n\
4137 Maximum\n\
4138 Segment\n\
4139 Size (bytes)\n\
4140 %6d\n";
4141
4142 float elapsed_time;
4143
4144 /* what we want is to have a buffer space that is at least one */
4145 /* send-size greater than our send window. this will insure that we */
4146 /* are never trying to re-use a buffer that may still be in the hands */
4147 /* of the transport. This buffer will be malloc'd after we have found */
4148 /* the size of the local senc socket buffer. We will want to deal */
4149 /* with alignment and offset concerns as well. */
4150
4151 struct ring_elt *send_ring;
4152
4153 int len;
4154 unsigned int nummessages = 0;
4155 SOCKET send_socket;
4156 int bytes_remaining;
4157 int tcp_mss = -1; /* possibly uninitialized on printf far below */
4158
4159 /* with links like fddi, one can send > 32 bits worth of bytes */
4160 /* during a test... ;-) at some point, this should probably become a */
4161 /* 64bit integral type, but those are not entirely common yet */
4162 double bytes_sent = 0.0;
4163
4164 float local_cpu_utilization;
4165 float local_service_demand;
4166 float remote_cpu_utilization;
4167 float remote_service_demand;
4168
4169 double thruput;
4170
4171 struct addrinfo *remote_res;
4172 struct addrinfo *local_res;
4173 struct sockaddr_in server;
4174
4175 #if defined(__linux) || defined(__sun)
4176 off_t scratch_offset; /* the linux sendfile() call will update
4177 the offset variable, which is
4178 something we do _not_ want to happen
4179 to the value in the send_ring! so, we
4180 have to use a scratch variable. */
4181 #endif /* __linux || defined(__sun) */
4182 #if defined (USE_OSX)
4183 off_t scratch_len; /* Darwin 9.x need a value-result parameter */
4184 #endif
4185 #if defined (__sun)
4186 size_t scratch_len; /* the sun sendfilev() needs a place to
4187 tell us how many bytes were written,
4188 even though it also returns the value */
4189 sendfilevec_t sv;
4190 #endif /* __sun */
4191
4192 struct tcp_stream_request_struct *tcp_stream_request;
4193 struct tcp_stream_response_struct *tcp_stream_response;
4194 struct tcp_stream_results_struct *tcp_stream_result;
4195
4196 tcp_stream_request =
4197 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
4198 tcp_stream_response =
4199 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
4200 tcp_stream_result =
4201 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
4202
4203 #ifdef WANT_HISTOGRAM
4204 if (verbosity > 1) {
4205 time_hist = HIST_new();
4206 }
4207 #endif /* WANT_HISTOGRAM */
4208
4209 /* since we are now disconnected from the code that established the */
4210 /* control socket, and since we want to be able to use different */
4211 /* protocols and such, we are passed the name of the remote host and */
4212 /* must turn that into the test specific addressing information. */
4213
4214 bzero((char *)&server,
4215 sizeof(server));
4216
4217 complete_addrinfos(&remote_res,
4218 &local_res,
4219 remote_host,
4220 SOCK_STREAM,
4221 IPPROTO_TCP,
4222 0);
4223
4224 if ( print_headers ) {
4225 /* we want to have some additional, interesting information in */
4226 /* the headers. we know some of it here, but not all, so we will */
4227 /* only print the test title here and will print the results */
4228 /* titles after the test is finished */
4229 print_top_test_header("TCP SENDFILE TEST",local_res,remote_res);
4230 }
4231
4232 send_ring = NULL;
4233 confidence_iteration = 1;
4234 init_stat();
4235
4236 /* we have a great-big while loop which controls the number of times */
4237 /* we run a particular test. this is for the calculation of a */
4238 /* confidence interval (I really should have stayed awake during */
4239 /* probstats :). If the user did not request confidence measurement */
4240 /* (no confidence is the default) then we will only go though the */
4241 /* loop once. the confidence stuff originates from the folks at IBM */
4242
4243 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
4244 (confidence_iteration <= iteration_min)) {
4245
4246 /* initialize a few counters. we have to remember that we might be */
4247 /* going through the loop more than once. */
4248
4249 nummessages = 0;
4250 bytes_sent = 0.0;
4251 times_up = 0;
4252
4253 /* set up the data socket */
4254 send_socket = create_data_socket(local_res);
4255
4256 if (send_socket == INVALID_SOCKET){
4257 perror("netperf: sendfile_tcp_stream: tcp stream data socket");
4258 exit(1);
4259 }
4260
4261 if (debug) {
4262 fprintf(where,"sendfile_tcp_stream: send_socket obtained...\n");
4263 }
4264
4265 #if defined(TCP_CORK)
4266 /* should this even be here?!? */
4267 if (loc_tcpcork > 0) {
4268 /* the user wishes for us to set TCP_CORK on the socket */
4269 int one = 1;
4270 if (setsockopt(send_socket,
4271 getprotobyname("tcp")->p_proto,
4272 TCP_CORK,
4273 (char *)&one,
4274 sizeof(one)) == SOCKET_ERROR) {
4275 perror("netperf: sendfile_tcp_stream: tcp_cork");
4276 exit(1);
4277 }
4278 if (debug) {
4279 fprintf(where,"sendfile_tcp_stream: tcp_cork...\n");
4280 }
4281 }
4282
4283 #endif /* TCP_CORK */
4284
4285 /* at this point, we have either retrieved the socket buffer sizes, */
4286 /* or have tried to set them, so now, we may want to set the send */
4287 /* size based on that (because the user either did not use a -m */
4288 /* option, or used one with an argument of 0). If the socket buffer */
4289 /* size is not available, we will set the send size to 4KB - no */
4290 /* particular reason, just arbitrary... */
4291
4292 /*check for file size/ min file size here? create file here/ back out???*/
4293
4294 if (send_size == 0) {
4295 if (lss_size > 0) {
4296 send_size = lss_size;
4297 }
4298 else {
4299 send_size = 4096;
4300 }
4301 }
4302
4303 /* set-up the data buffer ring with the requested alignment and
4304 offset. note also that we have allocated a quantity of memory
4305 that is at least one send-size greater than our socket buffer
4306 size. We want to be sure that there are at least two buffers
4307 allocated - this can be a bit of a problem when the send_size
4308 is bigger than the socket size, so we must check... the user
4309 may have wanted to explicitly set the "width" of our send
4310 buffers, we should respect that wish... */
4311
4312 /*sendring -> an offset index that will shift the starting point of the*/
4313 /*section of the file sent throughout the file*/
4314
4315 if (send_width == 0) {
4316 send_width = (lss_size/send_size) + 1;
4317 if (send_width == 1) send_width++;
4318 }
4319
4320 if (send_ring == NULL) {
4321
4322 /* only allocate the send ring once. this is a networking test,
4323 not a memory allocation test. this way, we do not need a
4324 deallocate_buffer_ring() routine, and I don't feel like
4325 writing one anyway :) raj 11/94 */
4326
4327 send_ring = alloc_sendfile_buf_ring(send_width,
4328 send_size,
4329 local_send_align,
4330 local_send_offset);
4331 }
4332
4333 /* If the user has requested cpu utilization measurements, we must
4334 calibrate the cpu(s). We will perform this task within the
4335 tests themselves. If the user has specified the cpu rate, then
4336 calibrate_local_cpu will return rather quickly as it will have
4337 nothing to do. If local_cpu_rate is zero, then we will go
4338 through all the "normal" calibration stuff and return the rate
4339 back. */
4340
4341 if (local_cpu_usage) {
4342 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
4343 }
4344
4345 /* Tell the remote end to do a listen. The server alters the
4346 socket paramters on the other side at this point, hence the
4347 reason for all the values being passed in the setup
4348 message. If the user did not specify any of the parameters,
4349 they will be passed as 0, which will indicate to the remote
4350 that no changes beyond the system's default should be
4351 used. Alignment is the exception, it will default to 1, which
4352 will be no alignment alterations. */
4353
4354 netperf_request.content.request_type = DO_TCP_STREAM;
4355 tcp_stream_request->send_buf_size = rss_size_req;
4356 tcp_stream_request->recv_buf_size = rsr_size_req;
4357 tcp_stream_request->receive_size = recv_size;
4358 tcp_stream_request->no_delay = rem_nodelay;
4359 tcp_stream_request->recv_alignment = remote_recv_align;
4360 tcp_stream_request->recv_offset = remote_recv_offset;
4361 tcp_stream_request->measure_cpu = remote_cpu_usage;
4362 tcp_stream_request->cpu_rate = remote_cpu_rate;
4363
4364 if (test_time) {
4365 tcp_stream_request->test_length = test_time;
4366 }
4367 else {
4368 tcp_stream_request->test_length = test_bytes;
4369 }
4370
4371 tcp_stream_request->so_rcvavoid = rem_rcvavoid;
4372 tcp_stream_request->so_sndavoid = rem_sndavoid;
4373
4374 #ifdef DIRTY
4375 tcp_stream_request->dirty_count = rem_dirty_count;
4376 tcp_stream_request->clean_count = rem_clean_count;
4377 #endif /* DIRTY */
4378 tcp_stream_request->port = atoi(remote_data_port);
4379 tcp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
4380
4381 if (debug > 1) {
4382 fprintf(where,
4383 "netperf: send_tcp_stream: requesting TCP stream test\n");
4384 }
4385
4386 send_request();
4387
4388 /* The response from the remote will contain all of the relevant
4389 socket parameters for this test type. We will put them back
4390 into the variables here so they can be displayed if desired.
4391 The remote will have calibrated CPU if necessary, and will have
4392 done all the needed set-up we will have calibrated the cpu
4393 locally before sending the request, and will grab the counter
4394 value right after the connect returns. The remote will grab the
4395 counter right after the accept call. This saves the hassle of
4396 extra messages being sent for the TCP tests. */
4397
4398 recv_response();
4399
4400 if (!netperf_response.content.serv_errno) {
4401 if (debug)
4402 fprintf(where,"remote listen done.\n");
4403 rsr_size = tcp_stream_response->recv_buf_size;
4404 rss_size = tcp_stream_response->send_buf_size;
4405 rem_nodelay = tcp_stream_response->no_delay;
4406 remote_cpu_usage= tcp_stream_response->measure_cpu;
4407 remote_cpu_rate = tcp_stream_response->cpu_rate;
4408
4409 /* we have to make sure that the server port number is in */
4410 /* network order */
4411 set_port_number(remote_res,(short)tcp_stream_response->data_port_number);
4412 rem_rcvavoid = tcp_stream_response->so_rcvavoid;
4413 rem_sndavoid = tcp_stream_response->so_sndavoid;
4414 }
4415 else {
4416 Set_errno(netperf_response.content.serv_errno);
4417 fprintf(where,
4418 "netperf: remote error %d",
4419 netperf_response.content.serv_errno);
4420 perror("");
4421 fflush(where);
4422
4423 exit(1);
4424 }
4425
4426 #ifdef WANT_DEMO
4427 demo_stream_setup(lss_size,rsr_size);
4428 #endif
4429
4430 /*Connect up to the remote port on the data socket */
4431 if (connect(send_socket,
4432 remote_res->ai_addr,
4433 remote_res->ai_addrlen) == INVALID_SOCKET){
4434 perror("netperf: send_tcp_stream: data socket connect failed");
4435 printf(" port: %d\n",ntohs(server.sin_port));
4436 exit(1);
4437 }
4438
4439 #ifdef WIN32
4440 /* this is used so the timer thread can close the socket out from */
4441 /* under us, which to date is the easiest/cleanest/least */
4442 /* Windows-specific way I can find to force the winsock calls to */
4443 /* return WSAEINTR with the test is over. anything that will run on */
4444 /* 95 and NT and is closer to what netperf expects from Unix signals */
4445 /* and such would be appreciated raj 1/96 */
4446 win_kludge_socket = send_socket;
4447 #endif /* WIN32 */
4448
4449 /* Data Socket set-up is finished. If there were problems, either
4450 the connect would have failed, or the previous response would
4451 have indicated a problem. I failed to see the value of the
4452 extra message after the accept on the remote. If it failed,
4453 we'll see it here. If it didn't, we might as well start pumping
4454 data. */
4455
4456 /* Set-up the test end conditions. For a stream test, they can be */
4457 /* either time or byte-count based. */
4458
4459 if (test_time) {
4460 /* The user wanted to end the test after a period of time. */
4461 times_up = 0;
4462 bytes_remaining = 0;
4463
4464 /* in previous revisions, we had the same code repeated throught
4465 all the test suites. this was unnecessary, and meant more
4466 work for me when I wanted to switch to POSIX signals, so I
4467 have abstracted this out into a routine in netlib.c. if you
4468 are experiencing signal problems, you might want to look
4469 there. raj 11/94 */
4470
4471 start_timer(test_time);
4472 }
4473 else {
4474 /* The tester wanted to send a number of bytes. */
4475 bytes_remaining = test_bytes;
4476 times_up = 1;
4477 }
4478
4479 /* The cpu_start routine will grab the current time and possibly */
4480 /* value of the idle counter for later use in measuring cpu */
4481 /* utilization and/or service demand and thruput. */
4482
4483 cpu_start(local_cpu_usage);
4484
4485 #ifdef WANT_INTERVALS
4486 INTERVALS_INIT();
4487 #endif /* WANT_INTERVALS */
4488
4489
4490 /* before we start, initialize a few variables */
4491
4492 #ifdef WANT_DEMO
4493 if (demo_mode) {
4494 demo_first_timestamp();
4495 }
4496 #endif
4497
4498 /* We use an "OR" to control test execution. When the test is
4499 controlled by time, the byte count check will always return
4500 false. When the test is controlled by byte count, the time test
4501 will always return false. When the test is finished, the whole
4502 expression will go false and we will stop sending data. */
4503
4504 while ((!times_up) || (bytes_remaining > 0)) {
4505
4506 /* the sendfile_tcp_stream test does not support making the buffers
4507 dirty. 08/2000 */
4508
4509 #ifdef WANT_HISTOGRAM
4510 if (verbosity > 1) {
4511 /* timestamp just before we go into sendfile() and then again
4512 just after we come out raj 08/2000 */
4513 /* but only if we are actually going to display a histogram */
4514 HIST_timestamp(&time_one);
4515 }
4516 #endif /* WANT_HISTOGRAM */
4517
4518 /* you can look at netlib.h for a description of the fields we
4519 are passing to sendfile(). 08/2000 */
4520 if (netperf_sendfile(send_socket, send_ring) != send_size) {
4521 /* the test was interrupted, must be the end of test. the
4522 send_tcp_stream code has some WIN32 ifdefs that we do not
4523 need here. */
4524 if ((len >=0) || SOCKET_EINTR(len)) {
4525 break;
4526 }
4527 perror("netperf: data send error: sendfile");
4528 fprintf(stderr,
4529 "len was %d send_size was %d\n",
4530 len,
4531 send_size);
4532 fflush(stderr);
4533 exit(1);
4534 }
4535
4536 #ifdef WANT_HISTOGRAM
4537 if (verbosity > 1) {
4538 /* timestamp the exit from the send call and update the
4539 histogram */
4540
4541 HIST_timestamp(&time_two);
4542 HIST_add(time_hist,delta_micro(&time_one,&time_two));
4543 }
4544 #endif /* WANT_HISTOGRAM */
4545
4546 #ifdef WANT_DEMO
4547 demo_stream_interval(send_size);
4548 #endif
4549
4550 #ifdef WANT_INTERVALS
4551 INTERVALS_WAIT();
4552 #endif /* WANT_INTERVALS */
4553
4554 /* now we want to move our pointer to the next position in the */
4555 /* data buffer...we may also want to wrap back to the "beginning" */
4556 /* of the bufferspace, so we will mod the number of messages sent */
4557 /* by the send width, and use that to calculate the offset to add */
4558 /* to the base pointer. */
4559
4560 nummessages++;
4561 send_ring = send_ring->next;
4562 if (bytes_remaining) {
4563 bytes_remaining -= send_size;
4564 }
4565 }
4566
4567 /* The test is over. Flush the buffers to the remote end. We do a
4568 graceful release to insure that all data has been taken by the
4569 remote. */
4570
4571 /* but first, if the verbosity is greater than 1, find-out what */
4572 /* the TCP maximum segment_size was (if possible) */
4573 if (verbosity > 1) {
4574 tcp_mss = -1;
4575 get_tcp_info(send_socket,&tcp_mss);
4576 }
4577
4578 if (shutdown(send_socket,SHUT_WR) == SOCKET_ERROR) {
4579 perror("netperf: cannot shutdown tcp stream socket");
4580 exit(1);
4581 }
4582
4583 /* hang a recv() off the socket to block until the remote has */
4584 /* brought all the data up into the application. it will do a */
4585 /* shutdown to cause a FIN to be sent our way. We will assume that */
4586 /* any exit from the recv() call is good... raj 4/93 */
4587
4588 /* since we are using sendfile() instead of send, we have no
4589 scratch buffer from the send_ring to use for the
4590 receive. however, since we "know" that the recv should be
4591 returning zero bytes (not that we are making the checks we
4592 should) we can pass the address of the flags field. raj 08/2000
4593 */
4594
4595 recv(send_socket,
4596 &(send_ring->flags),
4597 sizeof(send_ring->flags),
4598 0);
4599
4600 /* this call will always give us the elapsed time for the test, and */
4601 /* will also store-away the necessaries for cpu utilization */
4602
4603 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
4604 /* measured and how */
4605 /* long did we really */
4606 /* run? */
4607
4608 /* we are finished with the socket, so close it to prevent hitting */
4609 /* the limit on maximum open files. */
4610
4611 close(send_socket);
4612
4613 #if defined(WANT_INTERVALS)
4614 #ifdef WIN32
4615 stop_itimer();
4616 #endif
4617 #endif /* WANT_INTERVALS */
4618
4619 /* Get the statistics from the remote end. The remote will have */
4620 /* calculated service demand and all those interesting things. If it */
4621 /* wasn't supposed to care, it will return obvious values. */
4622
4623 recv_response();
4624
4625 if (!netperf_response.content.serv_errno) {
4626 if (debug)
4627 fprintf(where,"remote results obtained\n");
4628 }
4629
4630 else {
4631 Set_errno(netperf_response.content.serv_errno);
4632 fprintf(where,
4633 "netperf: remote error %d",
4634 netperf_response.content.serv_errno);
4635 perror("");
4636 fflush(where);
4637
4638 exit(1);
4639 }
4640
4641 /* We now calculate what our thruput was for the test. In the future, */
4642 /* we may want to include a calculation of the thruput measured by */
4643 /* the remote, but it should be the case that for a TCP stream test, */
4644 /* that the two numbers should be *very* close... We calculate */
4645 /* bytes_sent regardless of the way the test length was controlled. */
4646 /* If it was time, we needed to, and if it was by bytes, the user may */
4647 /* have specified a number of bytes that wasn't a multiple of the */
4648 /* send_size, so we really didn't send what he asked for ;-) */
4649
4650 bytes_sent = ntohd(tcp_stream_result->bytes_received);
4651
4652 thruput = calc_thruput(bytes_sent);
4653
4654 if (local_cpu_usage || remote_cpu_usage) {
4655
4656 /* We must now do a little math for service demand and cpu */
4657 /* utilization for the system(s) */
4658 /* Of course, some of the information might be bogus because */
4659 /* there was no idle counter in the kernel(s). We need to make */
4660 /* a note of this for the user's benefit...*/
4661 if (local_cpu_usage) {
4662
4663 local_cpu_utilization = calc_cpu_util(0.0);
4664 local_service_demand = calc_service_demand(bytes_sent,
4665 0.0,
4666 0.0,
4667 0);
4668 }
4669 else {
4670 local_cpu_utilization = (float) -1.0;
4671 local_service_demand = (float) -1.0;
4672 }
4673
4674 if (remote_cpu_usage) {
4675
4676 remote_cpu_utilization = tcp_stream_result->cpu_util;
4677 remote_service_demand = calc_service_demand(bytes_sent,
4678 0.0,
4679 remote_cpu_utilization,
4680 tcp_stream_result->num_cpus);
4681 }
4682 else {
4683 remote_cpu_utilization = (float) -1.0;
4684 remote_service_demand = (float) -1.0;
4685 }
4686 }
4687 else {
4688 /* we were not measuring cpu, for the confidence stuff, we */
4689 /* should make it -1.0 */
4690 local_cpu_utilization = (float) -1.0;
4691 local_service_demand = (float) -1.0;
4692 remote_cpu_utilization = (float) -1.0;
4693 remote_service_demand = (float) -1.0;
4694 }
4695
4696 /* at this point, we want to calculate the confidence information. */
4697 /* if debugging is on, calculate_confidence will print-out the */
4698 /* parameters we pass it */
4699
4700 calculate_confidence(confidence_iteration,
4701 elapsed_time,
4702 thruput,
4703 local_cpu_utilization,
4704 remote_cpu_utilization,
4705 local_service_demand,
4706 remote_service_demand);
4707
4708 confidence_iteration++;
4709 }
4710
4711 /* at this point, we have finished making all the runs that we */
4712 /* will be making. so, we should extract what the calcuated values */
4713 /* are for all the confidence stuff. we could make the values */
4714 /* global, but that seemed a little messy, and it did not seem worth */
4715 /* all the mucking with header files. so, we create a routine much */
4716 /* like calcualte_confidence, which just returns the mean values. */
4717 /* raj 11/94 */
4718
4719 retrieve_confident_values(&elapsed_time,
4720 &thruput,
4721 &local_cpu_utilization,
4722 &remote_cpu_utilization,
4723 &local_service_demand,
4724 &remote_service_demand);
4725
4726 /* We are now ready to print all the information. If the user */
4727 /* has specified zero-level verbosity, we will just print the */
4728 /* local service demand, or the remote service demand. If the */
4729 /* user has requested verbosity level 1, he will get the basic */
4730 /* "streamperf" numbers. If the user has specified a verbosity */
4731 /* of greater than 1, we will display a veritable plethora of */
4732 /* background information from outside of this block as it it */
4733 /* not cpu_measurement specific... */
4734
4735 if (confidence < 0) {
4736 /* we did not hit confidence, but were we asked to look for it? */
4737 if (iteration_max > 1) {
4738 display_confidence();
4739 }
4740 }
4741
4742 if (local_cpu_usage || remote_cpu_usage) {
4743 local_cpu_method = format_cpu_method(cpu_method);
4744 remote_cpu_method = format_cpu_method(tcp_stream_result->cpu_method);
4745
4746 switch (verbosity) {
4747 case 0:
4748
4749 if (local_cpu_usage) {
4750 fprintf(where,
4751 cpu_fmt_0,
4752 local_service_demand,
4753 local_cpu_method,
4754 ((print_headers) ||
4755 (result_brand == NULL)) ? "" : result_brand);
4756 }
4757
4758 else {
4759 fprintf(where,
4760 cpu_fmt_0,
4761 remote_service_demand,
4762 remote_cpu_method,
4763 ((print_headers) ||
4764 (result_brand == NULL)) ? "" : result_brand);
4765 }
4766
4767 break;
4768
4769 case 1:
4770 case 2:
4771 if (print_headers) {
4772 fprintf(where,
4773 cpu_title,
4774 format_units(),
4775 local_cpu_method,
4776 remote_cpu_method);
4777 }
4778
4779 fprintf(where,
4780 cpu_fmt_1, /* the format string */
4781 rsr_size, /* remote recvbuf size */
4782 lss_size, /* local sendbuf size */
4783 send_size, /* how large were the sends */
4784 elapsed_time, /* how long was the test */
4785 thruput, /* what was the xfer rate */
4786 local_cpu_utilization, /* local cpu */
4787 remote_cpu_utilization, /* remote cpu */
4788 local_service_demand, /* local service demand */
4789 remote_service_demand, /* remote service demand */
4790 ((print_headers) ||
4791 (result_brand == NULL)) ? "" : result_brand);
4792 break;
4793 }
4794
4795 }
4796
4797 else {
4798 /* The tester did not wish to measure service demand. */
4799
4800 switch (verbosity) {
4801
4802 case 0:
4803
4804 fprintf(where,
4805 tput_fmt_0,
4806 thruput,
4807 ((print_headers) ||
4808 (result_brand == NULL)) ? "" : result_brand);
4809 break;
4810
4811 case 1:
4812 case 2:
4813
4814 if (print_headers) {
4815 fprintf(where,tput_title,format_units());
4816 }
4817
4818 fprintf(where,
4819 tput_fmt_1, /* the format string */
4820 rsr_size, /* remote recvbuf size */
4821 lss_size, /* local sendbuf size */
4822 send_size, /* how large were the sends */
4823 elapsed_time, /* how long did it take */
4824 thruput, /* how fast did it go */
4825 ((print_headers) ||
4826 (result_brand == NULL)) ? "" : result_brand);
4827 break;
4828 }
4829 }
4830
4831 /* it would be a good thing to include information about some of the */
4832 /* other parameters that may have been set for this test, but at the */
4833 /* moment, I do not wish to figure-out all the formatting, so I will */
4834 /* just put this comment here to help remind me that it is something */
4835 /* that should be done at a later time. */
4836
4837 if (verbosity > 1) {
4838
4839 /* The user wanted to know it all, so we will give it to him. */
4840 /* This information will include as much as we can find about */
4841 /* TCP statistics, the alignments of the sends and receives */
4842 /* and all that sort of rot... */
4843
4844 /* this stuff needs to be worked-out in the presence of confidence */
4845 /* intervals and multiple iterations of the test... raj 11/94 */
4846
4847 fprintf(where,
4848 ksink_fmt,
4849 "Bytes",
4850 "Bytes",
4851 "Bytes",
4852 local_send_align,
4853 remote_recv_align,
4854 local_send_offset,
4855 remote_recv_offset,
4856 bytes_sent,
4857 bytes_sent / (double)nummessages,
4858 nummessages,
4859 bytes_sent / (double)tcp_stream_result->recv_calls,
4860 tcp_stream_result->recv_calls);
4861
4862 fprintf(where,
4863 ksink_fmt2,
4864 tcp_mss);
4865
4866 fflush(where);
4867
4868 #ifdef WANT_HISTOGRAM
4869
4870 fprintf(where,"\n\nHistogram of time spent in send() call.\n");
4871 fflush(where);
4872 HIST_report(time_hist);
4873 #endif /* WANT_HISTOGRAM */
4874 }
4875 }
4876
4877 #endif /* HAVE_SENDFILE */
4878
4879 /* This is the server-side routine for the tcp stream test. It is */
4880 /* implemented as one routine. I could break things-out somewhat, but */
4881 /* didn't feel it was necessary. */
4882
4883 void
recv_tcp_stream()4884 recv_tcp_stream()
4885 {
4886
4887 struct sockaddr_storage myaddr_in, peeraddr_in;
4888 SOCKET s_listen,s_data;
4889 netperf_socklen_t addrlen;
4890 int len;
4891 unsigned int receive_calls;
4892 float elapsed_time;
4893 double bytes_received;
4894
4895 struct ring_elt *recv_ring;
4896
4897 struct addrinfo *local_res;
4898 char local_name[BUFSIZ];
4899 char port_buffer[PORTBUFSIZE];
4900
4901 #ifdef DO_SELECT
4902 fd_set readfds;
4903 struct timeval timeout;
4904 #endif /* DO_SELECT */
4905
4906 struct tcp_stream_request_struct *tcp_stream_request;
4907 struct tcp_stream_response_struct *tcp_stream_response;
4908 struct tcp_stream_results_struct *tcp_stream_results;
4909
4910 #ifdef DO_SELECT
4911 FD_ZERO(&readfds);
4912 timeout.tv_sec = 1;
4913 timeout.tv_usec = 0;
4914 #endif /* DO_SELECT */
4915
4916 tcp_stream_request =
4917 (struct tcp_stream_request_struct *)netperf_request.content.test_specific_data;
4918 tcp_stream_response =
4919 (struct tcp_stream_response_struct *)netperf_response.content.test_specific_data;
4920 tcp_stream_results =
4921 (struct tcp_stream_results_struct *)netperf_response.content.test_specific_data;
4922
4923 if (debug) {
4924 fprintf(where,"netserver: recv_tcp_stream: entered...\n");
4925 fflush(where);
4926 }
4927
4928 /* We want to set-up the listen socket with all the desired */
4929 /* parameters and then let the initiator know that all is ready. If */
4930 /* socket size defaults are to be used, then the initiator will have */
4931 /* sent us 0's. If the socket sizes cannot be changed, then we will */
4932 /* send-back what they are. If that information cannot be determined, */
4933 /* then we send-back -1's for the sizes. If things go wrong for any */
4934 /* reason, we will drop back ten yards and punt. */
4935
4936 /* If anything goes wrong, we want the remote to know about it. It */
4937 /* would be best if the error that the remote reports to the user is */
4938 /* the actual error we encountered, rather than some bogus unexpected */
4939 /* response type message. */
4940
4941 if (debug) {
4942 fprintf(where,"recv_tcp_stream: setting the response type...\n");
4943 fflush(where);
4944 }
4945
4946 netperf_response.content.response_type = TCP_STREAM_RESPONSE;
4947
4948 if (debug) {
4949 fprintf(where,"recv_tcp_stream: the response type is set...\n");
4950 fflush(where);
4951 }
4952
4953 /* We now alter the message_ptr variable to be at the desired */
4954 /* alignment with the desired offset. */
4955
4956 if (debug) {
4957 fprintf(where,"recv_tcp_stream: requested alignment of %d\n",
4958 tcp_stream_request->recv_alignment);
4959 fflush(where);
4960 }
4961
4962 /* create_data_socket expects to find some things in the global */
4963 /* variables, so set the globals based on the values in the request. */
4964 /* once the socket has been created, we will set the response values */
4965 /* based on the updated value of those globals. raj 7/94 */
4966 lss_size_req = tcp_stream_request->send_buf_size;
4967 lsr_size_req = tcp_stream_request->recv_buf_size;
4968 loc_nodelay = tcp_stream_request->no_delay;
4969 loc_rcvavoid = tcp_stream_request->so_rcvavoid;
4970 loc_sndavoid = tcp_stream_request->so_sndavoid;
4971
4972 set_hostname_and_port(local_name,
4973 port_buffer,
4974 nf_to_af(tcp_stream_request->ipfamily),
4975 tcp_stream_request->port);
4976
4977 local_res = complete_addrinfo(local_name,
4978 local_name,
4979 port_buffer,
4980 nf_to_af(tcp_stream_request->ipfamily),
4981 SOCK_STREAM,
4982 IPPROTO_TCP,
4983 0);
4984
4985 s_listen = create_data_socket(local_res);
4986
4987 if (s_listen == INVALID_SOCKET) {
4988 netperf_response.content.serv_errno = errno;
4989 send_response();
4990 exit(1);
4991 }
4992
4993 #ifdef WIN32
4994 /* The test timer can fire during operations on the listening socket,
4995 so to make the start_timer below work we have to move
4996 it to close s_listen while we are blocked on accept. */
4997 win_kludge_socket2 = s_listen;
4998 #endif
4999
5000 /* what sort of sizes did we end-up with? */
5001 if (tcp_stream_request->receive_size == 0) {
5002 if (lsr_size > 0) {
5003 recv_size = lsr_size;
5004 }
5005 else {
5006 recv_size = 4096;
5007 }
5008 }
5009 else {
5010 recv_size = tcp_stream_request->receive_size;
5011 }
5012
5013 /* we want to set-up our recv_ring in a manner analagous to what we */
5014 /* do on the sending side. this is more for the sake of symmetry */
5015 /* than for the needs of say copy avoidance, but it might also be */
5016 /* more realistic - this way one could conceivably go with a */
5017 /* double-buffering scheme when taking the data an putting it into */
5018 /* the filesystem or something like that. raj 7/94 */
5019
5020 if (recv_width == 0) {
5021 recv_width = (lsr_size/recv_size) + 1;
5022 if (recv_width == 1) recv_width++;
5023 }
5024
5025 recv_ring = allocate_buffer_ring(recv_width,
5026 recv_size,
5027 tcp_stream_request->recv_alignment,
5028 tcp_stream_request->recv_offset);
5029
5030 if (debug) {
5031 fprintf(where,"recv_tcp_stream: receive alignment and offset set...\n");
5032 fflush(where);
5033 }
5034
5035 /* Now, let's set-up the socket to listen for connections */
5036 if (listen(s_listen, 5) == SOCKET_ERROR) {
5037 netperf_response.content.serv_errno = errno;
5038 close(s_listen);
5039 send_response();
5040
5041 exit(1);
5042 }
5043
5044
5045 /* now get the port number assigned by the system */
5046 addrlen = sizeof(myaddr_in);
5047 if (getsockname(s_listen,
5048 (struct sockaddr *)&myaddr_in,
5049 &addrlen) == SOCKET_ERROR){
5050 netperf_response.content.serv_errno = errno;
5051 close(s_listen);
5052 send_response();
5053
5054 exit(1);
5055 }
5056
5057 /* Now myaddr_in contains the port and the internet address this is */
5058 /* returned to the sender also implicitly telling the sender that the */
5059 /* socket buffer sizing has been done. */
5060
5061 tcp_stream_response->data_port_number =
5062 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
5063 netperf_response.content.serv_errno = 0;
5064
5065 /* But wait, there's more. If the initiator wanted cpu measurements, */
5066 /* then we must call the calibrate routine, which will return the max */
5067 /* rate back to the initiator. If the CPU was not to be measured, or */
5068 /* something went wrong with the calibration, we will return a -1 to */
5069 /* the initiator. */
5070
5071 tcp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
5072 if (tcp_stream_request->measure_cpu) {
5073 tcp_stream_response->measure_cpu = 1;
5074 tcp_stream_response->cpu_rate =
5075 calibrate_local_cpu(tcp_stream_request->cpu_rate);
5076 }
5077 else {
5078 tcp_stream_response->measure_cpu = 0;
5079 }
5080
5081 /* before we send the response back to the initiator, pull some of */
5082 /* the socket parms from the globals */
5083 tcp_stream_response->send_buf_size = lss_size;
5084 tcp_stream_response->recv_buf_size = lsr_size;
5085 tcp_stream_response->no_delay = loc_nodelay;
5086 tcp_stream_response->so_rcvavoid = loc_rcvavoid;
5087 tcp_stream_response->so_sndavoid = loc_sndavoid;
5088 tcp_stream_response->receive_size = recv_size;
5089
5090 send_response();
5091
5092 addrlen = sizeof(peeraddr_in);
5093
5094 if ((s_data=accept(s_listen,
5095 (struct sockaddr *)&peeraddr_in,
5096 &addrlen)) == INVALID_SOCKET) {
5097 /* Let's just punt. The remote will be given some information */
5098 close(s_listen);
5099 exit(1);
5100 }
5101
5102 #ifdef WIN32
5103 /* this is used so the timer thread can close the socket out from */
5104 /* under us, which to date is the easiest/cleanest/least */
5105 /* Windows-specific way I can find to force the winsock calls to */
5106 /* return WSAEINTR with the test is over. anything that will run on */
5107 /* 95 and NT and is closer to what netperf expects from Unix signals */
5108 /* and such would be appreciated raj 1/96 */
5109 win_kludge_socket = s_data;
5110 win_kludge_socket2 = INVALID_SOCKET;
5111 #endif /* WIN32 */
5112
5113 times_up = 0;
5114
5115 start_timer(tcp_stream_request->test_length + PAD_TIME);
5116
5117 #ifdef KLUDGE_SOCKET_OPTIONS
5118 /* this is for those systems which *INCORRECTLY* fail to pass */
5119 /* attributes across an accept() call. Including this goes against */
5120 /* my better judgement :( raj 11/95 */
5121
5122 kludge_socket_options(s_data);
5123
5124 #endif /* KLUDGE_SOCKET_OPTIONS */
5125
5126 /* Now it's time to start receiving data on the connection. We will */
5127 /* first grab the apropriate counters and then start grabbing. */
5128
5129 cpu_start(tcp_stream_request->measure_cpu);
5130
5131 /* The loop will exit when the sender does a shutdown, which will */
5132 /* return a length of zero */
5133
5134 /* there used to be an #ifdef DIRTY call to access_buffer() here,
5135 but we have switched from accessing the buffer before the recv()
5136 call to accessing the buffer after the recv() call. The
5137 accessing before was, IIRC, related to having dirty data when
5138 doing page-flipping copy avoidance. */
5139
5140 bytes_received = 0;
5141 receive_calls = 0;
5142
5143 while (!times_up && ((len = recv(s_data, recv_ring->buffer_ptr, recv_size, 0)) != 0)) {
5144 if (len == SOCKET_ERROR ) {
5145 if (times_up) {
5146 break;
5147 }
5148 netperf_response.content.serv_errno = errno;
5149 send_response();
5150 exit(1);
5151 }
5152 bytes_received += len;
5153 receive_calls++;
5154
5155 #ifdef DIRTY
5156 /* we access the buffer after the recv() call now, rather than before */
5157 access_buffer(recv_ring->buffer_ptr,
5158 recv_size,
5159 tcp_stream_request->dirty_count,
5160 tcp_stream_request->clean_count);
5161 #endif /* DIRTY */
5162
5163
5164 /* move to the next buffer in the recv_ring */
5165 recv_ring = recv_ring->next;
5166
5167 #ifdef PAUSE
5168 sleep(1);
5169 #endif /* PAUSE */
5170
5171 #ifdef DO_SELECT
5172 FD_SET(s_data,&readfds);
5173 select(s_data+1,&readfds,NULL,NULL,&timeout);
5174 #endif /* DO_SELECT */
5175
5176 }
5177
5178 /* perform a shutdown to signal the sender that */
5179 /* we have received all the data sent. raj 4/93 */
5180
5181 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR && !times_up) {
5182 netperf_response.content.serv_errno = errno;
5183 send_response();
5184 exit(1);
5185 }
5186
5187 cpu_stop(tcp_stream_request->measure_cpu,&elapsed_time);
5188
5189 /* send the results to the sender */
5190
5191 if (debug) {
5192 fprintf(where,
5193 "recv_tcp_stream: got %g bytes\n",
5194 bytes_received);
5195 fprintf(where,
5196 "recv_tcp_stream: got %d recvs\n",
5197 receive_calls);
5198 fflush(where);
5199 }
5200
5201 tcp_stream_results->bytes_received = htond(bytes_received);
5202 tcp_stream_results->elapsed_time = elapsed_time;
5203 tcp_stream_results->recv_calls = receive_calls;
5204
5205 tcp_stream_results->cpu_method = cpu_method;
5206 tcp_stream_results->num_cpus = lib_num_loc_cpus;
5207
5208 if (tcp_stream_request->measure_cpu) {
5209 tcp_stream_results->cpu_util = calc_cpu_util(0.0);
5210 };
5211
5212 if (debug) {
5213 fprintf(where,
5214 "recv_tcp_stream: test complete, sending results.\n");
5215 fprintf(where,
5216 " bytes_received %g receive_calls %d\n",
5217 bytes_received,
5218 receive_calls);
5219 fprintf(where,
5220 " len %d\n",
5221 len);
5222 fflush(where);
5223 }
5224
5225 send_response();
5226
5227 /* we are now done with the sockets */
5228 close(s_data);
5229 close(s_listen);
5230
5231 }
5232
5233 /* This is the server-side routine for the tcp maerts test. It is
5234 implemented as one routine. I could break things-out somewhat, but
5235 didn't feel it was necessary. */
5236
5237 void
recv_tcp_maerts()5238 recv_tcp_maerts()
5239 {
5240
5241 struct sockaddr_storage myaddr_in, peeraddr_in;
5242 struct addrinfo *local_res;
5243 char local_name[BUFSIZ];
5244 char port_buffer[PORTBUFSIZE];
5245
5246 SOCKET s_listen,s_data;
5247 netperf_socklen_t addrlen;
5248 int len;
5249 unsigned int send_calls;
5250 float elapsed_time;
5251 double bytes_sent = 0.0 ;
5252
5253 struct ring_elt *send_ring;
5254
5255 struct tcp_maerts_request_struct *tcp_maerts_request;
5256 struct tcp_maerts_response_struct *tcp_maerts_response;
5257 struct tcp_maerts_results_struct *tcp_maerts_results;
5258
5259 tcp_maerts_request =
5260 (struct tcp_maerts_request_struct *)netperf_request.content.test_specific_data;
5261 tcp_maerts_response =
5262 (struct tcp_maerts_response_struct *)netperf_response.content.test_specific_data;
5263 tcp_maerts_results =
5264 (struct tcp_maerts_results_struct *)netperf_response.content.test_specific_data;
5265
5266 if (debug) {
5267 fprintf(where,"netserver: recv_tcp_maerts: entered...\n");
5268 fflush(where);
5269 }
5270
5271 /* We want to set-up the listen socket with all the desired
5272 parameters and then let the initiator know that all is ready. If
5273 socket size defaults are to be used, then the initiator will have
5274 sent us 0's. If the socket sizes cannot be changed, then we will
5275 send-back what they are. If that information cannot be
5276 determined, then we send-back -1's for the sizes. If things go
5277 wrong for any reason, we will drop back ten yards and punt. */
5278
5279 /* If anything goes wrong, we want the remote to know about it. It
5280 would be best if the error that the remote reports to the user is
5281 the actual error we encountered, rather than some bogus
5282 unexpected response type message. */
5283
5284 if (debug) {
5285 fprintf(where,"recv_tcp_maerts: setting the response type...\n");
5286 fflush(where);
5287 }
5288
5289 netperf_response.content.response_type = TCP_MAERTS_RESPONSE;
5290
5291 if (debug) {
5292 fprintf(where,"recv_tcp_maerts: the response type is set...\n");
5293 fflush(where);
5294 }
5295
5296 /* We now alter the message_ptr variable to be at the desired */
5297 /* alignment with the desired offset. */
5298
5299 if (debug) {
5300 fprintf(where,"recv_tcp_maerts: requested alignment of %d\n",
5301 tcp_maerts_request->send_alignment);
5302 fflush(where);
5303 }
5304
5305 /* Grab a socket to listen on, and then listen on it. */
5306
5307 if (debug) {
5308 fprintf(where,"recv_tcp_maerts: grabbing a socket...\n");
5309 fflush(where);
5310 }
5311
5312 /* create_data_socket expects to find some things in the global */
5313 /* variables, so set the globals based on the values in the request. */
5314 /* once the socket has been created, we will set the response values */
5315 /* based on the updated value of those globals. raj 7/94 */
5316 lss_size_req = tcp_maerts_request->send_buf_size;
5317 lsr_size_req = tcp_maerts_request->recv_buf_size;
5318 loc_nodelay = tcp_maerts_request->no_delay;
5319 loc_rcvavoid = tcp_maerts_request->so_rcvavoid;
5320 loc_sndavoid = tcp_maerts_request->so_sndavoid;
5321
5322 set_hostname_and_port(local_name,
5323 port_buffer,
5324 nf_to_af(tcp_maerts_request->ipfamily),
5325 tcp_maerts_request->port);
5326
5327 local_res = complete_addrinfo(local_name,
5328 local_name,
5329 port_buffer,
5330 nf_to_af(tcp_maerts_request->ipfamily),
5331 SOCK_STREAM,
5332 IPPROTO_TCP,
5333 0);
5334
5335 s_listen = create_data_socket(local_res);
5336
5337 if (s_listen == INVALID_SOCKET) {
5338 netperf_response.content.serv_errno = errno;
5339 send_response();
5340 exit(1);
5341 }
5342
5343 #ifdef WIN32
5344 /* The test timer can fire during operations on the listening socket,
5345 so to make the start_timer below work we have to move
5346 it to close s_listen while we are blocked on accept. */
5347 win_kludge_socket2 = s_listen;
5348 #endif
5349
5350
5351 /* what sort of sizes did we end-up with? */
5352 if (tcp_maerts_request->send_size == 0) {
5353 if (lss_size > 0) {
5354 send_size = lss_size;
5355 }
5356 else {
5357 send_size = 4096;
5358 }
5359 }
5360 else {
5361 send_size = tcp_maerts_request->send_size;
5362 }
5363
5364 /* we want to set-up our recv_ring in a manner analagous to what we */
5365 /* do on the recving side. this is more for the sake of symmetry */
5366 /* than for the needs of say copy avoidance, but it might also be */
5367 /* more realistic - this way one could conceivably go with a */
5368 /* double-buffering scheme when taking the data an putting it into */
5369 /* the filesystem or something like that. raj 7/94 */
5370
5371 if (send_width == 0) {
5372 send_width = (lsr_size/send_size) + 1;
5373 if (send_width == 1) send_width++;
5374 }
5375
5376 send_ring = allocate_buffer_ring(send_width,
5377 send_size,
5378 tcp_maerts_request->send_alignment,
5379 tcp_maerts_request->send_offset);
5380
5381 if (debug) {
5382 fprintf(where,"recv_tcp_maerts: receive alignment and offset set...\n");
5383 fflush(where);
5384 }
5385
5386 /* Now, let's set-up the socket to listen for connections */
5387 if (listen(s_listen, 5) == SOCKET_ERROR) {
5388 netperf_response.content.serv_errno = errno;
5389 close(s_listen);
5390 send_response();
5391
5392 exit(1);
5393 }
5394
5395
5396 /* now get the port number assigned by the system */
5397 addrlen = sizeof(myaddr_in);
5398 if (getsockname(s_listen,
5399 (struct sockaddr *)&myaddr_in,
5400 &addrlen) == SOCKET_ERROR){
5401 netperf_response.content.serv_errno = errno;
5402 close(s_listen);
5403 send_response();
5404
5405 exit(1);
5406 }
5407
5408 /* Now myaddr_in contains the port and the internet address this is */
5409 /* returned to the sender also implicitly telling the sender that the */
5410 /* socket buffer sizing has been done. */
5411
5412 tcp_maerts_response->data_port_number =
5413 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
5414 netperf_response.content.serv_errno = 0;
5415
5416 /* But wait, there's more. If the initiator wanted cpu measurements, */
5417 /* then we must call the calibrate routine, which will return the max */
5418 /* rate back to the initiator. If the CPU was not to be measured, or */
5419 /* something went wrong with the calibration, we will return a -1 to */
5420 /* the initiator. */
5421
5422 tcp_maerts_response->cpu_rate = (float)0.0; /* assume no cpu */
5423 if (tcp_maerts_request->measure_cpu) {
5424 tcp_maerts_response->measure_cpu = 1;
5425 tcp_maerts_response->cpu_rate =
5426 calibrate_local_cpu(tcp_maerts_request->cpu_rate);
5427 }
5428 else {
5429 tcp_maerts_response->measure_cpu = 0;
5430 }
5431
5432 /* before we send the response back to the initiator, pull some of */
5433 /* the socket parms from the globals */
5434 tcp_maerts_response->send_buf_size = lss_size;
5435 tcp_maerts_response->recv_buf_size = lsr_size;
5436 tcp_maerts_response->no_delay = loc_nodelay;
5437 tcp_maerts_response->so_rcvavoid = loc_rcvavoid;
5438 tcp_maerts_response->so_sndavoid = loc_sndavoid;
5439 tcp_maerts_response->send_size = send_size;
5440
5441 send_response();
5442
5443 addrlen = sizeof(peeraddr_in);
5444
5445 /* we will start the timer before the accept() to be somewhat
5446 analagous to the starting of the timer before the connect() call
5447 in the TCP_STREAM test. raj 2002-06-21 */
5448
5449 start_timer(tcp_maerts_request->test_length);
5450
5451 /* Now it's time to start receiving data on the connection. We will
5452 first grab the apropriate counters and then start grabbing. */
5453
5454 cpu_start(tcp_maerts_request->measure_cpu);
5455
5456
5457 if ((s_data=accept(s_listen,
5458 (struct sockaddr *)&peeraddr_in,
5459 &addrlen)) == INVALID_SOCKET) {
5460 /* Let's just punt. The remote will be given some information */
5461 close(s_listen);
5462 exit(1);
5463 }
5464
5465 #ifdef WIN32
5466 /* this is used so the timer thread can close the socket out from */
5467 /* under us, which to date is the easiest/cleanest/least */
5468 /* Windows-specific way I can find to force the winsock calls to */
5469 /* return WSAEINTR with the test is over. anything that will run on */
5470 /* 95 and NT and is closer to what netperf expects from Unix signals */
5471 /* and such would be appreciated raj 1/96 */
5472 win_kludge_socket = s_data;
5473 win_kludge_socket2 = INVALID_SOCKET;
5474 #endif /* WIN32 */
5475
5476 #ifdef KLUDGE_SOCKET_OPTIONS
5477
5478 /* this is for those systems which *INCORRECTLY* fail to pass
5479 attributes across an accept() call. Including this goes against
5480 my better judgement :( raj 11/95 */
5481
5482 kludge_socket_options(s_data);
5483
5484 #endif /* KLUDGE_SOCKET_OPTIONS */
5485
5486 /* The loop will exit when the sender does a shutdown, which will */
5487 /* return a length of zero */
5488
5489 bytes_sent = 0.0;
5490 send_calls = 0;
5491
5492 len = 0; /* nt-lint; len is not initialized (printf far below) if
5493 times_up initially true.*/
5494 times_up = 0; /* must remember to initialize this little beauty */
5495 while (!times_up) {
5496
5497 #ifdef DIRTY
5498 /* we want to dirty some number of consecutive integers in the buffer */
5499 /* we are about to send. we may also want to bring some number of */
5500 /* them cleanly into the cache. The clean ones will follow any dirty */
5501 /* ones into the cache. */
5502
5503 access_buffer(send_ring->buffer_ptr,
5504 send_size,
5505 tcp_maerts_request->dirty_count,
5506 tcp_maerts_request->clean_count);
5507
5508 #endif /* DIRTY */
5509
5510 if((len=send(s_data,
5511 send_ring->buffer_ptr,
5512 send_size,
5513 0)) != send_size) {
5514 if ((len >=0) || SOCKET_EINTR(len)) {
5515 /* the test was interrupted, must be the end of test */
5516 break;
5517 }
5518 netperf_response.content.serv_errno = errno;
5519 send_response();
5520 exit(1);
5521 }
5522
5523 bytes_sent += len;
5524 send_calls++;
5525
5526 /* more to the next buffer in the send_ring */
5527 send_ring = send_ring->next;
5528
5529 }
5530
5531 /* perform a shutdown to signal the sender that */
5532 /* we have received all the data sent. raj 4/93 */
5533
5534 if (shutdown(s_data,SHUT_WR) == SOCKET_ERROR) {
5535 netperf_response.content.serv_errno = errno;
5536 send_response();
5537 exit(1);
5538 }
5539
5540 /* hang a recv() off the socket to block until the remote has
5541 brought all the data up into the application. it will do a
5542 shutdown to cause a FIN to be sent our way. We will assume that
5543 any exit from the recv() call is good... raj 4/93 */
5544
5545 recv(s_data, send_ring->buffer_ptr, send_size, 0);
5546
5547
5548 cpu_stop(tcp_maerts_request->measure_cpu,&elapsed_time);
5549
5550 /* send the results to the sender */
5551
5552 if (debug) {
5553 fprintf(where,
5554 "recv_tcp_maerts: got %g bytes\n",
5555 bytes_sent);
5556 fprintf(where,
5557 "recv_tcp_maerts: got %d sends\n",
5558 send_calls);
5559 fflush(where);
5560 }
5561
5562 tcp_maerts_results->bytes_sent = htond(bytes_sent);
5563 tcp_maerts_results->elapsed_time = elapsed_time;
5564 tcp_maerts_results->send_calls = send_calls;
5565
5566 if (tcp_maerts_request->measure_cpu) {
5567 tcp_maerts_results->cpu_util = calc_cpu_util(0.0);
5568 };
5569
5570 if (debug) {
5571 fprintf(where,
5572 "recv_tcp_maerts: test complete, sending results.\n");
5573 fprintf(where,
5574 " bytes_sent %g send_calls %d\n",
5575 bytes_sent,
5576 send_calls);
5577 fprintf(where,
5578 " len %d\n",
5579 len);
5580 fflush(where);
5581 }
5582
5583 tcp_maerts_results->cpu_method = cpu_method;
5584 tcp_maerts_results->num_cpus = lib_num_loc_cpus;
5585 send_response();
5586
5587 /* we are now done with the sockets */
5588 close(s_data);
5589 close(s_listen);
5590
5591 }
5592
5593
5594 /* this routine implements the sending (netperf) side of the TCP_RR */
5595 /* test. */
5596 #ifndef WANT_MIGRATION
5597 void
send_tcp_rr(char remote_host[])5598 send_tcp_rr(char remote_host[])
5599 {
5600
5601 char *tput_title = "\
5602 Local /Remote\n\
5603 Socket Size Request Resp. Elapsed Trans.\n\
5604 Send Recv Size Size Time Rate \n\
5605 bytes Bytes bytes bytes secs. per sec \n\n";
5606
5607 char *tput_title_band = "\
5608 Local /Remote\n\
5609 Socket Size Request Resp. Elapsed \n\
5610 Send Recv Size Size Time Throughput \n\
5611 bytes Bytes bytes bytes secs. %s/sec \n\n";
5612
5613 char *tput_fmt_0 =
5614 "%7.2f %s\n";
5615
5616 char *tput_fmt_1_line_1 = "\
5617 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
5618 char *tput_fmt_1_line_2 = "\
5619 %-6d %-6d\n";
5620
5621 char *cpu_title = "\
5622 Local /Remote\n\
5623 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
5624 Send Recv Size Size Time Rate local remote local remote\n\
5625 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
5626
5627 char *cpu_title_tput = "\
5628 Local /Remote\n\
5629 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\
5630 Send Recv Size Size Time %-8.8s local remote local remote\n\
5631 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
5632
5633 char *cpu_title_latency = "\
5634 Local /Remote\n\
5635 Socket Size Request Resp. Elapsed Latency CPU CPU S.dem S.dem\n\
5636 Send Recv Size Size Time usecs local remote local remote\n\
5637 bytes bytes bytes bytes secs. per tran %% %c %% %c us/Tr us/Tr\n\n";
5638
5639 char *cpu_fmt_0 =
5640 "%6.3f %c %s\n";
5641
5642 char *cpu_fmt_1_line_1 = "\
5643 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
5644
5645 char *cpu_fmt_1_line_2 = "\
5646 %-6d %-6d\n";
5647
5648 char *ksink_fmt = "\
5649 Alignment Offset RoundTrip Trans Throughput\n\
5650 Local Remote Local Remote Latency Rate %-8.8s/s\n\
5651 Send Recv Send Recv usec/Tran per sec Outbound Inbound\n\
5652 %5d %5d %5d %5d %-6.3f %-6.3f %-6.3f %-6.3f\n";
5653
5654
5655 int timed_out = 0;
5656 float elapsed_time;
5657
5658 int len;
5659 char *temp_message_ptr;
5660 int nummessages;
5661 SOCKET send_socket;
5662 int trans_remaining;
5663 double bytes_xferd;
5664
5665 struct ring_elt *send_ring;
5666 struct ring_elt *recv_ring;
5667
5668 int rsp_bytes_left;
5669 int rsp_bytes_recvd;
5670
5671 float local_cpu_utilization;
5672 float local_service_demand;
5673 float remote_cpu_utilization;
5674 float remote_service_demand;
5675 double thruput;
5676
5677 struct addrinfo *local_res;
5678 struct addrinfo *remote_res;
5679
5680 struct tcp_rr_request_struct *tcp_rr_request;
5681 struct tcp_rr_response_struct *tcp_rr_response;
5682 struct tcp_rr_results_struct *tcp_rr_result;
5683
5684 #ifdef WANT_FIRST_BURST
5685 #define REQUEST_CWND_INITIAL 2
5686 /* "in the beginning..." the WANT_FIRST_BURST stuff was like both
5687 Unix and the state of New Jersey - both were simple an unspoiled.
5688 then it was realized that some stacks are quite picky about
5689 initial congestion windows and a non-trivial initial burst of
5690 requests would not be individual segments even with TCP_NODELAY
5691 set. so, we have to start tracking a poor-man's congestion window
5692 up here in window space because we want to try to make something
5693 happen that frankly, we cannot guarantee with the specification
5694 of TCP. ain't that grand?-) raj 2006-01-30 */
5695 int requests_outstanding = 0;
5696 int request_cwnd = REQUEST_CWND_INITIAL; /* we ass-u-me that having
5697 three requests
5698 outstanding at the
5699 beginning of the test
5700 is ok with TCP stacks
5701 of interest. the first
5702 two will come from our
5703 first_burst loop, and
5704 the third from our
5705 regularly scheduled
5706 send */
5707 #endif
5708
5709 tcp_rr_request =
5710 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
5711 tcp_rr_response=
5712 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
5713 tcp_rr_result =
5714 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
5715
5716 #ifdef WANT_HISTOGRAM
5717 if (verbosity > 1) {
5718 time_hist = HIST_new();
5719 }
5720 #endif /* WANT_HISTOGRAM */
5721
5722 /* since we are now disconnected from the code that established the */
5723 /* control socket, and since we want to be able to use different */
5724 /* protocols and such, we are passed the name of the remote host and */
5725 /* must turn that into the test specific addressing information. */
5726
5727 complete_addrinfos(&remote_res,
5728 &local_res,
5729 remote_host,
5730 SOCK_STREAM,
5731 IPPROTO_TCP,
5732 0);
5733
5734 if ( print_headers ) {
5735 print_top_test_header("TCP REQUEST/RESPONSE TEST",local_res,remote_res);
5736 }
5737
5738 /* initialize a few counters */
5739
5740 send_ring = NULL;
5741 recv_ring = NULL;
5742 confidence_iteration = 1;
5743 init_stat();
5744
5745 /* we have a great-big while loop which controls the number of times */
5746 /* we run a particular test. this is for the calculation of a */
5747 /* confidence interval (I really should have stayed awake during */
5748 /* probstats :). If the user did not request confidence measurement */
5749 /* (no confidence is the default) then we will only go though the */
5750 /* loop once. the confidence stuff originates from the folks at IBM */
5751
5752 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
5753 (confidence_iteration <= iteration_min)) {
5754
5755 /* initialize a few counters. we have to remember that we might be */
5756 /* going through the loop more than once. */
5757
5758 nummessages = 0;
5759 bytes_xferd = 0.0;
5760 times_up = 0;
5761 timed_out = 0;
5762 trans_remaining = 0;
5763
5764 #ifdef WANT_FIRST_BURST
5765 /* we have to remember to reset the number of transactions
5766 outstanding and the "congestion window for each new
5767 iteration. raj 2006-01-31 */
5768 requests_outstanding = 0;
5769 request_cwnd = REQUEST_CWND_INITIAL;
5770 #endif
5771
5772
5773 /* set-up the data buffers with the requested alignment and offset. */
5774 /* since this is a request/response test, default the send_width and */
5775 /* recv_width to 1 and not two raj 7/94 */
5776
5777 if (send_width == 0) send_width = 1;
5778 if (recv_width == 0) recv_width = 1;
5779
5780 if (send_ring == NULL) {
5781 send_ring = allocate_buffer_ring(send_width,
5782 req_size,
5783 local_send_align,
5784 local_send_offset);
5785 }
5786
5787 if (recv_ring == NULL) {
5788 recv_ring = allocate_buffer_ring(recv_width,
5789 rsp_size,
5790 local_recv_align,
5791 local_recv_offset);
5792 }
5793
5794 /*set up the data socket */
5795 send_socket = create_data_socket(local_res);
5796
5797 if (send_socket == INVALID_SOCKET){
5798 perror("netperf: send_tcp_rr: tcp stream data socket");
5799 exit(1);
5800 }
5801
5802 if (debug) {
5803 fprintf(where,"send_tcp_rr: send_socket obtained...\n");
5804 }
5805
5806 /* If the user has requested cpu utilization measurements, we must */
5807 /* calibrate the cpu(s). We will perform this task within the tests */
5808 /* themselves. If the user has specified the cpu rate, then */
5809 /* calibrate_local_cpu will return rather quickly as it will have */
5810 /* nothing to do. If local_cpu_rate is zero, then we will go through */
5811 /* all the "normal" calibration stuff and return the rate back.*/
5812
5813 if (local_cpu_usage) {
5814 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
5815 }
5816
5817 if (!no_control) {
5818 /* Tell the remote end to do a listen. The server alters the
5819 socket paramters on the other side at this point, hence the
5820 reason for all the values being passed in the setup
5821 message. If the user did not specify any of the parameters,
5822 they will be passed as 0, which will indicate to the remote
5823 that no changes beyond the system's default should be
5824 used. Alignment is the exception, it will default to 8, which
5825 will be no alignment alterations. */
5826
5827 netperf_request.content.request_type = DO_TCP_RR;
5828 tcp_rr_request->recv_buf_size = rsr_size_req;
5829 tcp_rr_request->send_buf_size = rss_size_req;
5830 tcp_rr_request->recv_alignment = remote_recv_align;
5831 tcp_rr_request->recv_offset = remote_recv_offset;
5832 tcp_rr_request->send_alignment = remote_send_align;
5833 tcp_rr_request->send_offset = remote_send_offset;
5834 tcp_rr_request->request_size = req_size;
5835 tcp_rr_request->response_size = rsp_size;
5836 tcp_rr_request->no_delay = rem_nodelay;
5837 tcp_rr_request->measure_cpu = remote_cpu_usage;
5838 tcp_rr_request->cpu_rate = remote_cpu_rate;
5839 tcp_rr_request->so_rcvavoid = rem_rcvavoid;
5840 tcp_rr_request->so_sndavoid = rem_sndavoid;
5841 if (test_time) {
5842 tcp_rr_request->test_length = test_time;
5843 }
5844 else {
5845 tcp_rr_request->test_length = test_trans * -1;
5846 }
5847 tcp_rr_request->port = atoi(remote_data_port);
5848 tcp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
5849
5850 if (debug > 1) {
5851 fprintf(where,"netperf: send_tcp_rr: requesting TCP rr test\n");
5852 }
5853
5854 send_request();
5855
5856 /* The response from the remote will contain all of the relevant
5857 socket parameters for this test type. We will put them back
5858 into the variables here so they can be displayed if desired.
5859 The remote will have calibrated CPU if necessary, and will
5860 have done all the needed set-up we will have calibrated the
5861 cpu locally before sending the request, and will grab the
5862 counter value right after the connect returns. The remote
5863 will grab the counter right after the accept call. This saves
5864 the hassle of extra messages being sent for the TCP
5865 tests. */
5866
5867 recv_response();
5868
5869 if (!netperf_response.content.serv_errno) {
5870 if (debug)
5871 fprintf(where,"remote listen done.\n");
5872 rsr_size = tcp_rr_response->recv_buf_size;
5873 rss_size = tcp_rr_response->send_buf_size;
5874 rem_nodelay = tcp_rr_response->no_delay;
5875 remote_cpu_usage = tcp_rr_response->measure_cpu;
5876 remote_cpu_rate = tcp_rr_response->cpu_rate;
5877 /* make sure that port numbers are in network order */
5878 set_port_number(remote_res,(short)tcp_rr_response->data_port_number);
5879 }
5880 else {
5881 Set_errno(netperf_response.content.serv_errno);
5882 fprintf(where,
5883 "netperf: remote error %d",
5884 netperf_response.content.serv_errno);
5885 perror("");
5886 fflush(where);
5887
5888 exit(1);
5889 }
5890 }
5891
5892 #ifdef WANT_DEMO
5893 demo_rr_setup(1000);
5894 #endif
5895
5896 /*Connect up to the remote port on the data socket */
5897 if (connect(send_socket,
5898 remote_res->ai_addr,
5899 remote_res->ai_addrlen) == INVALID_SOCKET){
5900 perror("netperf: data socket connect failed");
5901
5902 exit(1);
5903 }
5904
5905 #ifdef WIN32
5906 /* this is used so the timer thread can close the socket out from */
5907 /* under us, which to date is the easiest/cleanest/least */
5908 /* Windows-specific way I can find to force the winsock calls to */
5909 /* return WSAEINTR with the test is over. anything that will run on */
5910 /* 95 and NT and is closer to what netperf expects from Unix signals */
5911 /* and such would be appreciated raj 1/96 */
5912 win_kludge_socket = send_socket;
5913 #endif /* WIN32 */
5914
5915 /* Data Socket set-up is finished. If there were problems, either the */
5916 /* connect would have failed, or the previous response would have */
5917 /* indicated a problem. I failed to see the value of the extra */
5918 /* message after the accept on the remote. If it failed, we'll see it */
5919 /* here. If it didn't, we might as well start pumping data. */
5920
5921 /* Set-up the test end conditions. For a request/response test, they */
5922 /* can be either time or transaction based. */
5923
5924 if (test_time) {
5925 /* The user wanted to end the test after a period of time. */
5926 times_up = 0;
5927 trans_remaining = 0;
5928 start_timer(test_time);
5929 }
5930 else {
5931 /* The tester wanted to send a number of bytes. */
5932 trans_remaining = test_bytes;
5933 times_up = 1;
5934 }
5935
5936 /* The cpu_start routine will grab the current time and possibly */
5937 /* value of the idle counter for later use in measuring cpu */
5938 /* utilization and/or service demand and thruput. */
5939
5940 cpu_start(local_cpu_usage);
5941
5942 #ifdef WANT_INTERVALS
5943 INTERVALS_INIT();
5944 #endif /* WANT_INTERVALS */
5945
5946 /* We use an "OR" to control test execution. When the test is */
5947 /* controlled by time, the byte count check will always return false. */
5948 /* When the test is controlled by byte count, the time test will */
5949 /* always return false. When the test is finished, the whole */
5950 /* expression will go false and we will stop sending data. I think I */
5951 /* just arbitrarily decrement trans_remaining for the timed test, but */
5952 /* will not do that just yet... One other question is whether or not */
5953 /* the send buffer and the receive buffer should be the same buffer. */
5954
5955 #ifdef WANT_DEMO
5956 if (demo_mode) {
5957 demo_first_timestamp();
5958 }
5959 #endif
5960
5961 while ((!times_up) || (trans_remaining > 0)) {
5962 /* send the request. we assume that if we use a blocking socket, */
5963 /* the request will be sent at one shot. */
5964
5965 #ifdef WANT_FIRST_BURST
5966 /* we can inject no more than request_cwnd, which will grow with
5967 time, and no more than first_burst_size. we don't use <= to
5968 account for the "regularly scheduled" send call. of course
5969 that makes it more a "max_outstanding_ than a
5970 "first_burst_size" but for now we won't fix the names. also,
5971 I suspect the extra check against < first_burst_size is
5972 redundant since later I expect to make sure that request_cwnd
5973 can never get larger than first_burst_size, but just at the
5974 moment I'm feeling like a belt and suspenders kind of
5975 programmer. raj 2006-01-30 */
5976 while ((first_burst_size > 0) &&
5977 (requests_outstanding < request_cwnd) &&
5978 (requests_outstanding < first_burst_size)) {
5979 if (debug) {
5980 fprintf(where,
5981 "injecting, req_outstndng %d req_cwnd %d burst %d\n",
5982 requests_outstanding,
5983 request_cwnd,
5984 first_burst_size);
5985 }
5986 if ((len = send(send_socket,
5987 send_ring->buffer_ptr,
5988 req_size,
5989 0)) != req_size) {
5990 /* we should never hit the end of the test in the first burst */
5991 perror("send_tcp_rr: initial burst data send error");
5992 exit(-1);
5993 }
5994 requests_outstanding += 1;
5995 }
5996
5997 #endif /* WANT_FIRST_BURST */
5998
5999 #ifdef WANT_HISTOGRAM
6000 if (verbosity > 1) {
6001 /* timestamp just before our call to send, and then again just
6002 after the receive raj 8/94 */
6003 /* but only if we are actually going to display one. raj
6004 2007-02-07 */
6005
6006 HIST_timestamp(&time_one);
6007 }
6008 #endif /* WANT_HISTOGRAM */
6009
6010 if ((len = send(send_socket,
6011 send_ring->buffer_ptr,
6012 req_size,
6013 0)) != req_size) {
6014 if (SOCKET_EINTR(len) || (errno == 0)) {
6015 /* we hit the end of a */
6016 /* timed test. */
6017 timed_out = 1;
6018 break;
6019 }
6020 perror("send_tcp_rr: data send error");
6021 exit(1);
6022 }
6023 send_ring = send_ring->next;
6024
6025 #ifdef WANT_FIRST_BURST
6026 requests_outstanding += 1;
6027 #endif
6028
6029 /* receive the response */
6030 rsp_bytes_left = rsp_size;
6031 temp_message_ptr = recv_ring->buffer_ptr;
6032 while(rsp_bytes_left > 0) {
6033 if((rsp_bytes_recvd=recv(send_socket,
6034 temp_message_ptr,
6035 rsp_bytes_left,
6036 0)) == SOCKET_ERROR || rsp_bytes_recvd == 0) {
6037 if ( SOCKET_EINTR(rsp_bytes_recvd) ) {
6038 /* We hit the end of a timed test. */
6039 timed_out = 1;
6040 break;
6041 }
6042 perror("send_tcp_rr: data recv error");
6043 exit(1);
6044 }
6045 rsp_bytes_left -= rsp_bytes_recvd;
6046 temp_message_ptr += rsp_bytes_recvd;
6047 }
6048 recv_ring = recv_ring->next;
6049
6050 #ifdef WANT_FIRST_BURST
6051 /* so, since we've gotten a response back, update the
6052 bookkeeping accordingly. there is one less request
6053 outstanding and we can put one more out there than before. */
6054 requests_outstanding -= 1;
6055 if (request_cwnd < first_burst_size) {
6056 request_cwnd += 1;
6057 if (debug) {
6058 fprintf(where,
6059 "incr req_cwnd to %d first_burst %d reqs_outstndng %d\n",
6060 request_cwnd,
6061 first_burst_size,
6062 requests_outstanding);
6063 }
6064 }
6065 #endif
6066 if (timed_out) {
6067 /* we may have been in a nested while loop - we need */
6068 /* another call to break. */
6069 break;
6070 }
6071
6072 #ifdef WANT_HISTOGRAM
6073 if (verbosity > 1) {
6074 HIST_timestamp(&time_two);
6075 HIST_add(time_hist,delta_micro(&time_one,&time_two));
6076 }
6077 #endif /* WANT_HISTOGRAM */
6078
6079 #ifdef WANT_DEMO
6080 demo_rr_interval(1);
6081 #endif
6082
6083 #ifdef WANT_INTERVALS
6084 INTERVALS_WAIT();
6085 #endif /* WANT_INTERVALS */
6086
6087 nummessages++;
6088 if (trans_remaining) {
6089 trans_remaining--;
6090 }
6091
6092 if (debug > 3) {
6093 if ((nummessages % 100) == 0) {
6094 fprintf(where,
6095 "Transaction %d completed\n",
6096 nummessages);
6097 fflush(where);
6098 }
6099 }
6100 }
6101
6102 /* At this point we used to call shutdown on the data socket to be
6103 sure all the data was delivered, but this was not germane in a
6104 request/response test, and it was causing the tests to "hang"
6105 when they were being controlled by time. So, I have replaced
6106 this shutdown call with a call to close that can be found later
6107 in the procedure. */
6108
6109 /* this call will always give us the elapsed time for the test,
6110 and will also store-away the necessaries for cpu utilization */
6111
6112 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
6113 /* measured? how long */
6114 /* did we really run? */
6115
6116 #if defined(WANT_INTERVALS)
6117 #ifdef WIN32
6118 stop_itimer();
6119 #endif
6120 #endif /* WANT_INTERVALS */
6121
6122 if (!no_control) {
6123 /* Get the statistics from the remote end. The remote will have
6124 calculated CPU utilization. If it wasn't supposed to care, it
6125 will return obvious values. */
6126
6127 recv_response();
6128 if (!netperf_response.content.serv_errno) {
6129 if (debug)
6130 fprintf(where,"remote results obtained\n");
6131 }
6132 else {
6133 Set_errno(netperf_response.content.serv_errno);
6134 fprintf(where,"netperf: remote error %d",
6135 netperf_response.content.serv_errno);
6136 perror("");
6137 fflush(where);
6138 exit(1);
6139 }
6140 }
6141
6142 /* We now calculate what our "throughput" was for the test. */
6143
6144 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
6145 thruput = nummessages/elapsed_time;
6146
6147 if (local_cpu_usage || remote_cpu_usage) {
6148 /* We must now do a little math for service demand and cpu
6149 utilization for the system(s) Of course, some of the
6150 information might be bogus because there was no idle counter in
6151 the kernel(s). We need to make a note of this for the user's
6152 benefit... */
6153 if (local_cpu_usage) {
6154 local_cpu_utilization = calc_cpu_util(0.0);
6155 /* since calc_service demand is doing ms/Kunit we will
6156 multiply the number of transaction by 1024 to get "good"
6157 numbers */
6158 local_service_demand = calc_service_demand((double) nummessages*1024,
6159 0.0,
6160 0.0,
6161 0);
6162 }
6163 else {
6164 local_cpu_utilization = (float) -1.0;
6165 local_service_demand = (float) -1.0;
6166 }
6167
6168 if (remote_cpu_usage) {
6169 remote_cpu_utilization = tcp_rr_result->cpu_util;
6170 /* since calc_service demand is doing ms/Kunit we will
6171 multiply the number of transaction by 1024 to get "good"
6172 numbers */
6173 remote_service_demand = calc_service_demand((double) nummessages*1024,
6174 0.0,
6175 remote_cpu_utilization,
6176 tcp_rr_result->num_cpus);
6177 }
6178 else {
6179 remote_cpu_utilization = (float) -1.0;
6180 remote_service_demand = (float) -1.0;
6181 }
6182
6183 }
6184 else {
6185 /* we were not measuring cpu, for the confidence stuff, we */
6186 /* should make it -1.0 */
6187 local_cpu_utilization = (float) -1.0;
6188 local_service_demand = (float) -1.0;
6189 remote_cpu_utilization = (float) -1.0;
6190 remote_service_demand = (float) -1.0;
6191 }
6192
6193 /* at this point, we want to calculate the confidence information.
6194 if debugging is on, calculate_confidence will print-out the
6195 parameters we pass it */
6196
6197 calculate_confidence(confidence_iteration,
6198 elapsed_time,
6199 thruput,
6200 local_cpu_utilization,
6201 remote_cpu_utilization,
6202 local_service_demand,
6203 remote_service_demand);
6204
6205
6206 confidence_iteration++;
6207
6208 /* we are now done with the socket, so close it */
6209 close(send_socket);
6210
6211 }
6212
6213 retrieve_confident_values(&elapsed_time,
6214 &thruput,
6215 &local_cpu_utilization,
6216 &remote_cpu_utilization,
6217 &local_service_demand,
6218 &remote_service_demand);
6219
6220 /* We are now ready to print all the information. If the user has
6221 specified zero-level verbosity, we will just print the local
6222 service demand, or the remote service demand. If the user has
6223 requested verbosity level 1, he will get the basic "streamperf"
6224 numbers. If the user has specified a verbosity of greater than 1,
6225 we will display a veritable plethora of background information
6226 from outside of this block as it it not cpu_measurement
6227 specific... */
6228
6229 if (confidence < 0) {
6230 /* we did not hit confidence, but were we asked to look for it? */
6231 if (iteration_max > 1) {
6232 display_confidence();
6233 }
6234 }
6235
6236 if (local_cpu_usage || remote_cpu_usage) {
6237 local_cpu_method = format_cpu_method(cpu_method);
6238 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
6239
6240 switch (verbosity) {
6241 case 0:
6242 if (local_cpu_usage) {
6243 fprintf(where,
6244 cpu_fmt_0,
6245 local_service_demand,
6246 local_cpu_method,
6247 ((print_headers) ||
6248 (result_brand == NULL)) ? "" : result_brand);
6249 }
6250 else {
6251 fprintf(where,
6252 cpu_fmt_0,
6253 remote_service_demand,
6254 remote_cpu_method,
6255 ((print_headers) ||
6256 (result_brand == NULL)) ? "" : result_brand);
6257 }
6258 break;
6259 case 1:
6260 case 2:
6261 if (print_headers) {
6262 if ('x' == libfmt) {
6263 fprintf(where,
6264 cpu_title,
6265 local_cpu_method,
6266 remote_cpu_method);
6267 }
6268 else {
6269 fprintf(where,
6270 cpu_title_tput,
6271 format_units(),
6272 local_cpu_method,
6273 remote_cpu_method);
6274 }
6275 }
6276
6277 fprintf(where,
6278 cpu_fmt_1_line_1, /* the format string */
6279 lss_size, /* local sendbuf size */
6280 lsr_size,
6281 req_size, /* how large were the requests */
6282 rsp_size, /* guess */
6283 elapsed_time, /* how long was the test */
6284 ('x' == libfmt) ? thruput :
6285 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6286 1.0),
6287 local_cpu_utilization, /* local cpu */
6288 remote_cpu_utilization, /* remote cpu */
6289 local_service_demand, /* local service demand */
6290 remote_service_demand, /* remote service demand */
6291 ((print_headers) ||
6292 (result_brand == NULL)) ? "" : result_brand);
6293 fprintf(where,
6294 cpu_fmt_1_line_2,
6295 rss_size,
6296 rsr_size);
6297 break;
6298 }
6299 }
6300 else {
6301 /* The tester did not wish to measure service demand. */
6302
6303 switch (verbosity) {
6304 case 0:
6305 fprintf(where,
6306 tput_fmt_0,
6307 ('x' == libfmt) ? thruput :
6308 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6309 1.0),
6310 ((print_headers) ||
6311 (result_brand == NULL)) ? "" : result_brand);
6312 break;
6313 case 1:
6314 case 2:
6315 if (print_headers) {
6316 fprintf(where,
6317 ('x' == libfmt) ? tput_title : tput_title_band,
6318 format_units());
6319 }
6320
6321 fprintf(where,
6322 tput_fmt_1_line_1, /* the format string */
6323 lss_size,
6324 lsr_size,
6325 req_size, /* how large were the requests */
6326 rsp_size, /* how large were the responses */
6327 elapsed_time, /* how long did it take */
6328 /* are we trans or do we need to convert to bytes then
6329 bits? at this point, thruput is in our "confident"
6330 transactions per second. we can convert to a
6331 bidirectional bitrate by multiplying that by the sum
6332 of the req_size and rsp_size. we pass that to
6333 calc_thruput_interval_omni with an elapsed time of
6334 1.0 s to get it converted to [kmg]bits/s or
6335 [KMG]Bytes/s */
6336 ('x' == libfmt) ? thruput :
6337 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
6338 1.0),
6339 ((print_headers) ||
6340 (result_brand == NULL)) ? "" : result_brand);
6341 fprintf(where,
6342 tput_fmt_1_line_2,
6343 rss_size, /* remote recvbuf size */
6344 rsr_size);
6345
6346 break;
6347 }
6348 }
6349
6350 /* it would be a good thing to include information about some of the */
6351 /* other parameters that may have been set for this test, but at the */
6352 /* moment, I do not wish to figure-out all the formatting, so I will */
6353 /* just put this comment here to help remind me that it is something */
6354 /* that should be done at a later time. */
6355
6356 /* how to handle the verbose information in the presence of */
6357 /* confidence intervals is yet to be determined... raj 11/94 */
6358 if (verbosity > 1) {
6359 /* The user wanted to know it all, so we will give it to him. */
6360 /* This information will include as much as we can find about */
6361 /* TCP statistics, the alignments of the sends and receives */
6362 /* and all that sort of rot... */
6363
6364 /* normally, you might think that if we were messing about with
6365 the value of libfmt we would need to put it back again, but
6366 since this is basically the last thing we are going to do with
6367 it, it does not matter. so there :) raj 2007-06-08 */
6368 /* if the user was asking for transactions, then we report
6369 megabits per second for the unidirectional throughput,
6370 otherwise we use the desired units. */
6371 if ('x' == libfmt) {
6372 libfmt = 'm';
6373 }
6374
6375 fprintf(where,
6376 ksink_fmt,
6377 format_units(),
6378 local_send_align,
6379 remote_recv_offset,
6380 local_send_offset,
6381 remote_recv_offset,
6382 /* if the user has enable burst mode, we have to remember
6383 to account for that in the number of transactions
6384 outstanding at any one time. otherwise we will
6385 underreport the latency of individual
6386 transactions. learned from saf by raj 2007-06-08 */
6387 (((double)1.0/thruput)*(double)1000000.0) *
6388 (double) (1 + ((first_burst_size > 0) ? first_burst_size : 0)),
6389 thruput,
6390 calc_thruput_interval_omni(thruput * (double)req_size,1.0),
6391 calc_thruput_interval_omni(thruput * (double)rsp_size,1.0));
6392
6393 #ifdef WANT_HISTOGRAM
6394 fprintf(where,"\nHistogram of request/response times\n");
6395 fflush(where);
6396 HIST_report(time_hist);
6397 #endif /* WANT_HISTOGRAM */
6398
6399 }
6400
6401 }
6402 #endif /* WANT_MIGRATION */
6403
6404 #if defined(__linux)
6405 /*
6406 * Linux has this odd behavior where if the socket buffers are larger than
6407 * a device's txqueuelen, the kernel will silently drop transmits which would
6408 * not fit into the tx queue, and not pass an ENOBUFS error back to the
6409 * application. As a result, a UDP stream test can report absurd transmit
6410 * bandwidths (like 20Gb/s on a 1GbE NIC). This behavior can be avoided if
6411 * you request extended error reporting on the socket. This is done by
6412 * setting the IP_RECVERR socket option at the IP level.
6413 */
6414 static void
enable_enobufs(int s)6415 enable_enobufs(int s)
6416 {
6417 struct protoent *pr;
6418 int on = 1;
6419
6420 if ((pr = getprotobyname("ip")) == NULL) {
6421 fprintf(where, "enable_enobufs failed: getprotobyname\n");
6422 fflush(where);
6423 return;
6424 }
6425 if (setsockopt(s, pr->p_proto, IP_RECVERR, (char *)&on, sizeof(on)) < 0) {
6426 fprintf(where, "enable_enobufs failed: setsockopt\n");
6427 fflush(where);
6428 return;
6429 }
6430 }
6431 #endif
6432
6433 #ifndef WANT_MIGRATION
6434 void
send_udp_stream(char remote_host[])6435 send_udp_stream(char remote_host[])
6436 {
6437 /**********************************************************************/
6438 /* */
6439 /* UDP Unidirectional Send Test */
6440 /* */
6441 /**********************************************************************/
6442
6443 #define UDP_LENGTH_MAX 0XFFFF - 28
6444
6445 char *tput_title = "\
6446 Socket Message Elapsed Messages \n\
6447 Size Size Time Okay Errors Throughput\n\
6448 bytes bytes secs # # %s/sec\n\n";
6449
6450 char *tput_fmt_0 =
6451 "%7.2f\n";
6452
6453 char *tput_fmt_1 = "\
6454 %6d %6d %-7.2f %7d %6d %7.2f\n\
6455 %6d %-7.2f %7d %7.2f\n\n";
6456
6457
6458 char *cpu_title = "\
6459 Socket Message Elapsed Messages CPU Service\n\
6460 Size Size Time Okay Errors Throughput Util Demand\n\
6461 bytes bytes secs # # %s/sec %% %c%c us/KB\n\n";
6462
6463 char *cpu_fmt_0 =
6464 "%6.2f %c\n";
6465
6466 char *cpu_fmt_1 = "\
6467 %6d %6d %-7.2f %7d %6d %7.1f %-6.2f %-6.3f\n\
6468 %6d %-7.2f %7d %7.1f %-6.2f %-6.3f\n\n";
6469
6470 unsigned int messages_recvd;
6471 unsigned int messages_sent;
6472 unsigned int failed_sends;
6473
6474 float elapsed_time,
6475 local_cpu_utilization,
6476 remote_cpu_utilization;
6477
6478 float local_service_demand, remote_service_demand;
6479 double local_thruput, remote_thruput;
6480 double bytes_sent;
6481 double bytes_recvd;
6482
6483
6484 int len;
6485 struct ring_elt *send_ring;
6486 SOCKET data_socket;
6487
6488 unsigned int sum_messages_sent;
6489 unsigned int sum_messages_recvd;
6490 unsigned int sum_failed_sends;
6491 double sum_local_thruput;
6492
6493 struct addrinfo *local_res;
6494 struct addrinfo *remote_res;
6495
6496 struct udp_stream_request_struct *udp_stream_request;
6497 struct udp_stream_response_struct *udp_stream_response;
6498 struct udp_stream_results_struct *udp_stream_results;
6499
6500 udp_stream_request =
6501 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
6502 udp_stream_response =
6503 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
6504 udp_stream_results =
6505 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
6506
6507 #ifdef WANT_HISTOGRAM
6508 if (verbosity > 1) {
6509 time_hist = HIST_new();
6510 }
6511 #endif /* WANT_HISTOGRAM */
6512
6513 /* since we are now disconnected from the code that established the */
6514 /* control socket, and since we want to be able to use different */
6515 /* protocols and such, we are passed the name of the remote host and */
6516 /* must turn that into the test specific addressing information. */
6517
6518 complete_addrinfos(&remote_res,
6519 &local_res,
6520 remote_host,
6521 SOCK_DGRAM,
6522 IPPROTO_UDP,
6523 0);
6524
6525 if ( print_headers ) {
6526 print_top_test_header("UDP UNIDIRECTIONAL SEND TEST",local_res,remote_res);
6527 }
6528
6529 send_ring = NULL;
6530 confidence_iteration = 1;
6531 init_stat();
6532 sum_messages_sent = 0;
6533 sum_messages_recvd = 0;
6534 sum_failed_sends = 0;
6535 sum_local_thruput = 0.0;
6536
6537 /* we have a great-big while loop which controls the number of times */
6538 /* we run a particular test. this is for the calculation of a */
6539 /* confidence interval (I really should have stayed awake during */
6540 /* probstats :). If the user did not request confidence measurement */
6541 /* (no confidence is the default) then we will only go though the */
6542 /* loop once. the confidence stuff originates from the folks at IBM */
6543
6544 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
6545 (confidence_iteration <= iteration_min)) {
6546
6547 /* initialize a few counters. we have to remember that we might be */
6548 /* going through the loop more than once. */
6549 messages_sent = 0;
6550 messages_recvd = 0;
6551 failed_sends = 0;
6552 times_up = 0;
6553
6554 /*set up the data socket */
6555 data_socket = create_data_socket(local_res);
6556
6557 if (data_socket == INVALID_SOCKET){
6558 perror("udp_send: data socket");
6559 exit(1);
6560 }
6561
6562 /* now, we want to see if we need to set the send_size */
6563 if (send_size == 0) {
6564 if (lss_size > 0) {
6565 send_size = (lss_size < UDP_LENGTH_MAX ? lss_size : UDP_LENGTH_MAX);
6566 }
6567 else {
6568 send_size = 4096;
6569 }
6570 }
6571
6572
6573 /* set-up the data buffer with the requested alignment and offset, */
6574 /* most of the numbers here are just a hack to pick something nice */
6575 /* and big in an attempt to never try to send a buffer a second time */
6576 /* before it leaves the node...unless the user set the width */
6577 /* explicitly. */
6578 if (send_width == 0) send_width = 32;
6579
6580 if (send_ring == NULL ) {
6581 send_ring = allocate_buffer_ring(send_width,
6582 send_size,
6583 local_send_align,
6584 local_send_offset);
6585 }
6586
6587
6588 /* if the user supplied a cpu rate, this call will complete rather */
6589 /* quickly, otherwise, the cpu rate will be retured to us for */
6590 /* possible display. The Library will keep it's own copy of this data */
6591 /* for use elsewhere. We will only display it. (Does that make it */
6592 /* "opaque" to us?) */
6593
6594 if (local_cpu_usage)
6595 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
6596
6597 if (!no_control) {
6598 /* Tell the remote end to set up the data connection. The server
6599 sends back the port number and alters the socket parameters
6600 there. Of course this is a datagram service so no connection
6601 is actually set up, the server just sets up the socket and
6602 binds it. */
6603
6604 netperf_request.content.request_type = DO_UDP_STREAM;
6605 udp_stream_request->recv_buf_size = rsr_size_req;
6606 udp_stream_request->message_size = send_size;
6607 udp_stream_request->recv_connected = remote_connected;
6608 udp_stream_request->recv_alignment = remote_recv_align;
6609 udp_stream_request->recv_offset = remote_recv_offset;
6610 udp_stream_request->measure_cpu = remote_cpu_usage;
6611 udp_stream_request->cpu_rate = remote_cpu_rate;
6612 udp_stream_request->test_length = test_time;
6613 udp_stream_request->so_rcvavoid = rem_rcvavoid;
6614 udp_stream_request->so_sndavoid = rem_sndavoid;
6615 udp_stream_request->port = atoi(remote_data_port);
6616 udp_stream_request->ipfamily = af_to_nf(remote_res->ai_family);
6617
6618 send_request();
6619
6620 recv_response();
6621
6622 if (!netperf_response.content.serv_errno) {
6623 if (debug)
6624 fprintf(where,"send_udp_stream: remote data connection done.\n");
6625 }
6626 else {
6627 Set_errno(netperf_response.content.serv_errno);
6628 perror("send_udp_stream: error on remote");
6629 exit(1);
6630 }
6631
6632 /* Place the port number returned by the remote into the sockaddr */
6633 /* structure so our sends can be sent to the correct place. Also get */
6634 /* some of the returned socket buffer information for user display. */
6635
6636 /* make sure that port numbers are in the proper order */
6637 set_port_number(remote_res,(short)udp_stream_response->data_port_number);
6638
6639 rsr_size = udp_stream_response->recv_buf_size;
6640 rss_size = udp_stream_response->send_buf_size;
6641 remote_cpu_rate = udp_stream_response->cpu_rate;
6642 }
6643
6644 #ifdef WANT_DEMO
6645 demo_stream_setup(lss_size,rsr_size);
6646 #endif
6647
6648 /* We "connect" up to the remote post to allow is to use the send */
6649 /* call instead of the sendto call. Presumeably, this is a little */
6650 /* simpler, and a little more efficient. I think that it also means */
6651 /* that we can be informed of certain things, but am not sure */
6652 /* yet...also, this is the way I would expect a client to behave */
6653 /* when talking to a server */
6654 if (local_connected) {
6655 if (connect(data_socket,
6656 remote_res->ai_addr,
6657 remote_res->ai_addrlen) == INVALID_SOCKET){
6658 perror("send_udp_stream: data socket connect failed");
6659 exit(1);
6660 } else if (debug) {
6661 fprintf(where,"send_udp_stream: connected data socket.\n");
6662 fflush(where);
6663 }
6664 }
6665
6666 #if defined (__linux)
6667 enable_enobufs(data_socket);
6668 #endif
6669
6670 #ifdef WIN32
6671 /* this is used so the timer thread can close the socket out from */
6672 /* under us, which to date is the easiest/cleanest/least */
6673 /* Windows-specific way I can find to force the winsock calls to */
6674 /* return WSAEINTR with the test is over. anything that will run on */
6675 /* 95 and NT and is closer to what netperf expects from Unix signals */
6676 /* and such would be appreciated raj 1/96 */
6677 win_kludge_socket = data_socket;
6678 #endif /* WIN32 */
6679
6680 /* set up the timer to call us after test_time. one of these days, */
6681 /* it might be nice to figure-out a nice reliable way to have the */
6682 /* test controlled by a byte count as well, but since UDP is not */
6683 /* reliable, that could prove difficult. so, in the meantime, we */
6684 /* only allow a UDP_STREAM test to be a timed test. */
6685
6686 if (test_time) {
6687 times_up = 0;
6688 start_timer(test_time);
6689 }
6690 else {
6691 fprintf(where,"Sorry, UDP_STREAM tests must be timed.\n");
6692 fflush(where);
6693 }
6694
6695 /* Get the start count for the idle counter and the start time */
6696
6697 cpu_start(local_cpu_usage);
6698
6699 #ifdef WANT_INTERVALS
6700 INTERVALS_INIT();
6701 #endif /* WANT_INTERVALS */
6702
6703 #ifdef WANT_DEMO
6704 if (demo_mode) {
6705 demo_first_timestamp();
6706 }
6707 #endif
6708
6709 /* Send datagrams like there was no tomorrow. at somepoint it might */
6710 /* be nice to set this up so that a quantity of bytes could be sent, */
6711 /* but we still need some sort of end of test trigger on the receive */
6712 /* side. that could be a select with a one second timeout, but then */
6713 /* if there is a test where none of the data arrives for awile and */
6714 /* then starts again, we would end the test too soon. something to */
6715 /* think about... */
6716 while (!times_up) {
6717
6718 #ifdef DIRTY
6719 /* we want to dirty some number of consecutive integers in the buffer */
6720 /* we are about to send. we may also want to bring some number of */
6721 /* them cleanly into the cache. The clean ones will follow any dirty */
6722 /* ones into the cache. */
6723
6724 access_buffer(send_ring->buffer_ptr,
6725 send_size,
6726 loc_dirty_count,
6727 loc_clean_count);
6728 #endif /* DIRTY */
6729
6730 #ifdef WANT_HISTOGRAM
6731 if (verbosity > 1) {
6732 HIST_timestamp(&time_one);
6733 }
6734 #endif /* WANT_HISTOGRAM */
6735
6736 if (local_connected) {
6737 len = send(data_socket,
6738 send_ring->buffer_ptr,
6739 send_size,
6740 0);
6741 } else {
6742 len = sendto(data_socket,
6743 send_ring->buffer_ptr,
6744 send_size,
6745 0,
6746 remote_res->ai_addr,
6747 remote_res->ai_addrlen);
6748 }
6749
6750 if (len != send_size) {
6751 if ((len >= 0) ||
6752 SOCKET_EINTR(len))
6753 break;
6754 if (errno == ENOBUFS) {
6755 failed_sends++;
6756 continue;
6757 }
6758 perror("udp_send: data send error");
6759 exit(1);
6760 }
6761 messages_sent++;
6762
6763 /* now we want to move our pointer to the next position in the */
6764 /* data buffer... */
6765
6766 send_ring = send_ring->next;
6767
6768
6769 #ifdef WANT_HISTOGRAM
6770 if (verbosity > 1) {
6771 /* get the second timestamp */
6772 HIST_timestamp(&time_two);
6773 HIST_add(time_hist,delta_micro(&time_one,&time_two));
6774 }
6775 #endif /* WANT_HISTOGRAM */
6776
6777 #ifdef WANT_DEMO
6778 demo_stream_interval(send_size);
6779 #endif
6780
6781 #ifdef WANT_INTERVALS
6782 INTERVALS_WAIT();
6783 #endif /* WANT_INTERVALS */
6784
6785 }
6786
6787 /* This is a timed test, so the remote will be returning to us after */
6788 /* a time. We should not need to send any "strange" messages to tell */
6789 /* the remote that the test is completed, unless we decide to add a */
6790 /* number of messages to the test. */
6791
6792 /* the test is over, so get stats and stuff */
6793 cpu_stop(local_cpu_usage,
6794 &elapsed_time);
6795
6796 #if defined(WANT_INTERVALS)
6797 #ifdef WIN32
6798 stop_itimer();
6799 #endif
6800 #endif /* WANT_INTERVALS */
6801
6802 if (!no_control) {
6803 /* Get the statistics from the remote end */
6804 recv_response();
6805 if (!netperf_response.content.serv_errno) {
6806 if (debug)
6807 fprintf(where,"send_udp_stream: remote results obtained\n");
6808 }
6809 else {
6810 Set_errno(netperf_response.content.serv_errno);
6811 perror("send_udp_stream: error on remote");
6812 exit(1);
6813 }
6814 messages_recvd = udp_stream_results->messages_recvd;
6815 bytes_recvd = (double) send_size * (double) messages_recvd;
6816 }
6817 else {
6818 /* since there was no control connection, we've no idea what was
6819 actually received. raj 2007-02-08 */
6820 messages_recvd = -1;
6821 bytes_recvd = -1.0;
6822 }
6823
6824 bytes_sent = (double) send_size * (double) messages_sent;
6825 local_thruput = calc_thruput(bytes_sent);
6826
6827
6828 /* we asume that the remote ran for as long as we did */
6829
6830 remote_thruput = calc_thruput(bytes_recvd);
6831
6832 /* print the results for this socket and message size */
6833
6834 if (local_cpu_usage || remote_cpu_usage) {
6835 /* We must now do a little math for service demand and cpu */
6836 /* utilization for the system(s) We pass zeros for the local */
6837 /* cpu utilization and elapsed time to tell the routine to use */
6838 /* the libraries own values for those. */
6839 if (local_cpu_usage) {
6840 local_cpu_utilization = calc_cpu_util(0.0);
6841 /* shouldn't this really be based on bytes_recvd, since that is */
6842 /* the effective throughput of the test? I think that it should, */
6843 /* so will make the change raj 11/94 */
6844 local_service_demand = calc_service_demand(bytes_recvd,
6845 0.0,
6846 0.0,
6847 0);
6848 }
6849 else {
6850 local_cpu_utilization = (float) -1.0;
6851 local_service_demand = (float) -1.0;
6852 }
6853
6854 /* The local calculations could use variables being kept by */
6855 /* the local netlib routines. The remote calcuations need to */
6856 /* have a few things passed to them. */
6857 if (remote_cpu_usage) {
6858 remote_cpu_utilization = udp_stream_results->cpu_util;
6859 remote_service_demand = calc_service_demand(bytes_recvd,
6860 0.0,
6861 remote_cpu_utilization,
6862 udp_stream_results->num_cpus);
6863 }
6864 else {
6865 remote_cpu_utilization = (float) -1.0;
6866 remote_service_demand = (float) -1.0;
6867 }
6868 }
6869 else {
6870 /* we were not measuring cpu, for the confidence stuff, we */
6871 /* should make it -1.0 */
6872 local_cpu_utilization = (float) -1.0;
6873 local_service_demand = (float) -1.0;
6874 remote_cpu_utilization = (float) -1.0;
6875 remote_service_demand = (float) -1.0;
6876 }
6877
6878 /* at this point, we want to calculate the confidence information. */
6879 /* if debugging is on, calculate_confidence will print-out the */
6880 /* parameters we pass it */
6881
6882 calculate_confidence(confidence_iteration,
6883 elapsed_time,
6884 remote_thruput,
6885 local_cpu_utilization,
6886 remote_cpu_utilization,
6887 local_service_demand,
6888 remote_service_demand);
6889
6890 /* since the routine calculate_confidence is rather generic, and */
6891 /* we have a few other parms of interest, we will do a little work */
6892 /* here to caclulate their average. */
6893 sum_messages_sent += messages_sent;
6894 sum_messages_recvd += messages_recvd;
6895 sum_failed_sends += failed_sends;
6896 sum_local_thruput += local_thruput;
6897
6898 confidence_iteration++;
6899
6900 /* this datapoint is done, so we don't need the socket any longer */
6901 close(data_socket);
6902
6903 }
6904
6905 /* we should reach this point once the test is finished */
6906
6907 retrieve_confident_values(&elapsed_time,
6908 &remote_thruput,
6909 &local_cpu_utilization,
6910 &remote_cpu_utilization,
6911 &local_service_demand,
6912 &remote_service_demand);
6913
6914 /* some of the interesting values aren't covered by the generic */
6915 /* confidence routine */
6916 messages_sent = sum_messages_sent / (confidence_iteration -1);
6917 messages_recvd = sum_messages_recvd / (confidence_iteration -1);
6918 failed_sends = sum_failed_sends / (confidence_iteration -1);
6919 local_thruput = sum_local_thruput / (confidence_iteration -1);
6920
6921 /* We are now ready to print all the information. If the user */
6922 /* has specified zero-level verbosity, we will just print the */
6923 /* local service demand, or the remote service demand. If the */
6924 /* user has requested verbosity level 1, he will get the basic */
6925 /* "streamperf" numbers. If the user has specified a verbosity */
6926 /* of greater than 1, we will display a veritable plethora of */
6927 /* background information from outside of this block as it it */
6928 /* not cpu_measurement specific... */
6929
6930
6931 if (confidence < 0) {
6932 /* we did not hit confidence, but were we asked to look for it? */
6933 if (iteration_max > 1) {
6934 display_confidence();
6935 }
6936 }
6937
6938 if (local_cpu_usage || remote_cpu_usage) {
6939 local_cpu_method = format_cpu_method(cpu_method);
6940 remote_cpu_method = format_cpu_method(udp_stream_results->cpu_method);
6941
6942 switch (verbosity) {
6943 case 0:
6944 if (local_cpu_usage) {
6945 fprintf(where,
6946 cpu_fmt_0,
6947 local_service_demand,
6948 local_cpu_method);
6949 }
6950 else {
6951 fprintf(where,
6952 cpu_fmt_0,
6953 remote_service_demand,
6954 local_cpu_method);
6955 }
6956 break;
6957 case 1:
6958 case 2:
6959 if (print_headers) {
6960 fprintf(where,
6961 cpu_title,
6962 format_units(),
6963 local_cpu_method,
6964 remote_cpu_method);
6965 }
6966
6967 fprintf(where,
6968 cpu_fmt_1, /* the format string */
6969 lss_size, /* local sendbuf size */
6970 send_size, /* how large were the sends */
6971 elapsed_time, /* how long was the test */
6972 messages_sent,
6973 failed_sends,
6974 local_thruput, /* what was the xfer rate */
6975 local_cpu_utilization, /* local cpu */
6976 local_service_demand, /* local service demand */
6977 rsr_size,
6978 elapsed_time,
6979 messages_recvd,
6980 remote_thruput,
6981 remote_cpu_utilization, /* remote cpu */
6982 remote_service_demand); /* remote service demand */
6983 break;
6984 }
6985 }
6986 else {
6987 /* The tester did not wish to measure service demand. */
6988 switch (verbosity) {
6989 case 0:
6990 fprintf(where,
6991 tput_fmt_0,
6992 local_thruput);
6993 break;
6994 case 1:
6995 case 2:
6996 if (print_headers) {
6997 fprintf(where,tput_title,format_units());
6998 }
6999 fprintf(where,
7000 tput_fmt_1, /* the format string */
7001 lss_size, /* local sendbuf size */
7002 send_size, /* how large were the sends */
7003 elapsed_time, /* how long did it take */
7004 messages_sent,
7005 failed_sends,
7006 local_thruput,
7007 rsr_size, /* remote recvbuf size */
7008 elapsed_time,
7009 messages_recvd,
7010 remote_thruput);
7011 break;
7012 }
7013 }
7014
7015 fflush(where);
7016 #ifdef WANT_HISTOGRAM
7017 if (verbosity > 1) {
7018 fprintf(where,"\nHistogram of time spent in send() call\n");
7019 fflush(where);
7020 HIST_report(time_hist);
7021 }
7022 #endif /* WANT_HISTOGRAM */
7023
7024 }
7025 #endif /* WANT_MIGRATION */
7026
7027
7028 /* this routine implements the receive side (netserver) of the */
7029 /* UDP_STREAM performance test. */
7030
7031 void
recv_udp_stream()7032 recv_udp_stream()
7033 {
7034 struct ring_elt *recv_ring;
7035 struct addrinfo *local_res;
7036 char local_name[BUFSIZ];
7037 char port_buffer[PORTBUFSIZE];
7038
7039 struct sockaddr_storage myaddr_in;
7040 SOCKET s_data;
7041 netperf_socklen_t addrlen;
7042 struct sockaddr_storage remote_addr;
7043 netperf_socklen_t remote_addrlen;
7044
7045 int len = 0;
7046 unsigned int bytes_received = 0;
7047 float elapsed_time;
7048
7049 int message_size;
7050 unsigned int messages_recvd = 0;
7051
7052 struct udp_stream_request_struct *udp_stream_request;
7053 struct udp_stream_response_struct *udp_stream_response;
7054 struct udp_stream_results_struct *udp_stream_results;
7055
7056 udp_stream_request =
7057 (struct udp_stream_request_struct *)netperf_request.content.test_specific_data;
7058 udp_stream_response =
7059 (struct udp_stream_response_struct *)netperf_response.content.test_specific_data;
7060 udp_stream_results =
7061 (struct udp_stream_results_struct *)netperf_response.content.test_specific_data;
7062
7063 if (debug) {
7064 fprintf(where,"netserver: recv_udp_stream: entered...\n");
7065 fflush(where);
7066 }
7067
7068 /* We want to set-up the listen socket with all the desired */
7069 /* parameters and then let the initiator know that all is ready. If */
7070 /* socket size defaults are to be used, then the initiator will have */
7071 /* sent us 0's. If the socket sizes cannot be changed, then we will */
7072 /* send-back what they are. If that information cannot be determined, */
7073 /* then we send-back -1's for the sizes. If things go wrong for any */
7074 /* reason, we will drop back ten yards and punt. */
7075
7076 /* If anything goes wrong, we want the remote to know about it. It */
7077 /* would be best if the error that the remote reports to the user is */
7078 /* the actual error we encountered, rather than some bogus unexpected */
7079 /* response type message. */
7080
7081 if (debug > 1) {
7082 fprintf(where,"recv_udp_stream: setting the response type...\n");
7083 fflush(where);
7084 }
7085
7086 netperf_response.content.response_type = UDP_STREAM_RESPONSE;
7087
7088 if (debug > 2) {
7089 fprintf(where,"recv_udp_stream: the response type is set...\n");
7090 fflush(where);
7091 }
7092
7093 /* We now alter the message_ptr variable to be at the desired */
7094 /* alignment with the desired offset. */
7095
7096 if (debug > 1) {
7097 fprintf(where,"recv_udp_stream: requested alignment of %d\n",
7098 udp_stream_request->recv_alignment);
7099 fflush(where);
7100 }
7101
7102 if (recv_width == 0) recv_width = 1;
7103
7104 recv_ring = allocate_buffer_ring(recv_width,
7105 udp_stream_request->message_size,
7106 udp_stream_request->recv_alignment,
7107 udp_stream_request->recv_offset);
7108
7109 if (debug > 1) {
7110 fprintf(where,"recv_udp_stream: receive alignment and offset set...\n");
7111 fflush(where);
7112 }
7113
7114 /* Grab a socket to listen on, and then listen on it. */
7115
7116 if (debug > 1) {
7117 fprintf(where,"recv_udp_stream: grabbing a socket...\n");
7118 fflush(where);
7119 }
7120
7121 /* create_data_socket expects to find some things in the global */
7122 /* variables, so set the globals based on the values in the request. */
7123 /* once the socket has been created, we will set the response values */
7124 /* based on the updated value of those globals. raj 7/94 */
7125 lsr_size_req = udp_stream_request->recv_buf_size;
7126 loc_rcvavoid = udp_stream_request->so_rcvavoid;
7127 loc_sndavoid = udp_stream_request->so_sndavoid;
7128 local_connected = udp_stream_request->recv_connected;
7129
7130 set_hostname_and_port(local_name,
7131 port_buffer,
7132 nf_to_af(udp_stream_request->ipfamily),
7133 udp_stream_request->port);
7134
7135 local_res = complete_addrinfo(local_name,
7136 local_name,
7137 port_buffer,
7138 nf_to_af(udp_stream_request->ipfamily),
7139 SOCK_DGRAM,
7140 IPPROTO_UDP,
7141 0);
7142
7143 s_data = create_data_socket(local_res);
7144
7145 if (s_data == INVALID_SOCKET) {
7146 netperf_response.content.serv_errno = errno;
7147 send_response();
7148 exit(1);
7149 }
7150
7151 udp_stream_response->test_length = udp_stream_request->test_length;
7152
7153 /* now get the port number assigned by the system */
7154 addrlen = sizeof(myaddr_in);
7155 if (getsockname(s_data,
7156 (struct sockaddr *)&myaddr_in,
7157 &addrlen) == SOCKET_ERROR){
7158 netperf_response.content.serv_errno = errno;
7159 close(s_data);
7160 send_response();
7161
7162 exit(1);
7163 }
7164
7165 /* Now myaddr_in contains the port and the internet address this is */
7166 /* returned to the sender also implicitly telling the sender that the */
7167 /* socket buffer sizing has been done. */
7168
7169 udp_stream_response->data_port_number =
7170 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
7171 netperf_response.content.serv_errno = 0;
7172
7173 /* But wait, there's more. If the initiator wanted cpu measurements, */
7174 /* then we must call the calibrate routine, which will return the max */
7175 /* rate back to the initiator. If the CPU was not to be measured, or */
7176 /* something went wrong with the calibration, we will return a -1 to */
7177 /* the initiator. */
7178
7179 udp_stream_response->cpu_rate = (float)0.0; /* assume no cpu */
7180 udp_stream_response->measure_cpu = 0;
7181 if (udp_stream_request->measure_cpu) {
7182 /* We will pass the rate into the calibration routine. If the */
7183 /* user did not specify one, it will be 0.0, and we will do a */
7184 /* "real" calibration. Otherwise, all it will really do is */
7185 /* store it away... */
7186 udp_stream_response->measure_cpu = 1;
7187 udp_stream_response->cpu_rate =
7188 calibrate_local_cpu(udp_stream_request->cpu_rate);
7189 }
7190
7191 message_size = udp_stream_request->message_size;
7192 test_time = udp_stream_request->test_length;
7193
7194 /* before we send the response back to the initiator, pull some of */
7195 /* the socket parms from the globals */
7196 udp_stream_response->send_buf_size = lss_size;
7197 udp_stream_response->recv_buf_size = lsr_size;
7198 udp_stream_response->so_rcvavoid = loc_rcvavoid;
7199 udp_stream_response->so_sndavoid = loc_sndavoid;
7200
7201 send_response();
7202
7203 /* Now it's time to start receiving data on the connection. We will */
7204 /* first grab the apropriate counters and then start grabbing. */
7205
7206 cpu_start(udp_stream_request->measure_cpu);
7207
7208 #ifdef WIN32
7209 /* this is used so the timer thread can close the socket out from */
7210 /* under us, which to date is the easiest/cleanest/least */
7211 /* Windows-specific way I can find to force the winsock calls to */
7212 /* return WSAEINTR with the test is over. anything that will run on */
7213 /* 95 and NT and is closer to what netperf expects from Unix signals */
7214 /* and such would be appreciated raj 1/96 */
7215 win_kludge_socket = s_data;
7216 #endif /* WIN32 */
7217
7218 /* The loop will exit when the timer pops, or if we happen to recv a */
7219 /* message of less than send_size bytes... */
7220
7221 times_up = 0;
7222
7223 start_timer(test_time + PAD_TIME);
7224
7225 if (debug) {
7226 fprintf(where,"recv_udp_stream: about to enter inner sanctum.\n");
7227 fflush(where);
7228 }
7229
7230 /* We "connect" up to the remote post to allow us to use the recv */
7231 /* call instead of the recvfrom call. Presumeably, this is a little */
7232 /* simpler, and a little more efficient. */
7233
7234 if (local_connected) {
7235
7236 /* Receive the first message using recvfrom to find the remote address */
7237 remote_addrlen = sizeof(remote_addr);
7238 len = recvfrom(s_data, recv_ring->buffer_ptr,
7239 message_size, 0,
7240 (struct sockaddr*)&remote_addr, &remote_addrlen);
7241 if (len != message_size) {
7242 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
7243 netperf_response.content.serv_errno = errno;
7244 send_response();
7245 exit(1);
7246 }
7247 }
7248 messages_recvd++;
7249 recv_ring = recv_ring->next;
7250
7251
7252 /* Now connect with the remote socket address */
7253 if (connect(s_data,
7254 (struct sockaddr*)&remote_addr,
7255 remote_addrlen )== INVALID_SOCKET) {
7256 netperf_response.content.serv_errno = errno;
7257 close(s_data);
7258 send_response();
7259 exit(1);
7260 }
7261
7262 if (debug) {
7263 fprintf(where,"recv_udp_stream: connected data socket\n");
7264 fflush(where);
7265 }
7266 }
7267
7268 while (!times_up) {
7269 if(local_connected) {
7270 len = recv(s_data,
7271 recv_ring->buffer_ptr,
7272 message_size,
7273 0);
7274 } else {
7275 len = recvfrom(s_data,
7276 recv_ring->buffer_ptr,
7277 message_size,
7278 0,0,0);
7279 }
7280
7281 if (len != message_size) {
7282 if ((len == SOCKET_ERROR) && !SOCKET_EINTR(len)) {
7283 netperf_response.content.serv_errno = errno;
7284 send_response();
7285 exit(1);
7286 }
7287 break;
7288 }
7289 messages_recvd++;
7290 recv_ring = recv_ring->next;
7291 }
7292
7293 if (debug) {
7294 fprintf(where,"recv_udp_stream: got %d messages.\n",messages_recvd);
7295 fflush(where);
7296 }
7297
7298
7299 /* The loop now exits due timer or < send_size bytes received. in */
7300 /* reality, we only really support a timed UDP_STREAM test. raj */
7301 /* 12/95 */
7302
7303 cpu_stop(udp_stream_request->measure_cpu,&elapsed_time);
7304
7305 if (times_up) {
7306 /* we ended on a timer, subtract the PAD_TIME */
7307 elapsed_time -= (float)PAD_TIME;
7308 }
7309 else {
7310 stop_timer();
7311 }
7312
7313 if (debug) {
7314 fprintf(where,"recv_udp_stream: test ended in %f seconds.\n",elapsed_time);
7315 fflush(where);
7316 }
7317
7318
7319 /* We will count the "off" message that got us out of the loop */
7320 bytes_received = (messages_recvd * message_size) + len;
7321
7322 /* send the results to the sender */
7323
7324 if (debug) {
7325 fprintf(where,
7326 "recv_udp_stream: got %d bytes\n",
7327 bytes_received);
7328 fflush(where);
7329 }
7330
7331 netperf_response.content.response_type = UDP_STREAM_RESULTS;
7332 udp_stream_results->bytes_received = bytes_received;
7333 udp_stream_results->messages_recvd = messages_recvd;
7334 udp_stream_results->elapsed_time = elapsed_time;
7335 udp_stream_results->cpu_method = cpu_method;
7336 udp_stream_results->num_cpus = lib_num_loc_cpus;
7337 if (udp_stream_request->measure_cpu) {
7338 udp_stream_results->cpu_util = calc_cpu_util(elapsed_time);
7339 }
7340 else {
7341 udp_stream_results->cpu_util = (float) -1.0;
7342 }
7343
7344 if (debug > 1) {
7345 fprintf(where,
7346 "recv_udp_stream: test complete, sending results.\n");
7347 fflush(where);
7348 }
7349
7350 send_response();
7351
7352 close(s_data);
7353
7354 }
7355
7356 #ifndef WANT_MIGRATION
7357 void
send_udp_rr(char remote_host[])7358 send_udp_rr(char remote_host[])
7359 {
7360
7361 char *tput_title = "\
7362 Local /Remote\n\
7363 Socket Size Request Resp. Elapsed Trans.\n\
7364 Send Recv Size Size Time Rate \n\
7365 bytes Bytes bytes bytes secs. per sec \n\n";
7366
7367 char *tput_title_band = "\
7368 Local /Remote\n\
7369 Socket Size Request Resp. Elapsed \n\
7370 Send Recv Size Size Time Throughput \n\
7371 bytes Bytes bytes bytes secs. %s/sec \n\n";
7372
7373 char *tput_fmt_0 =
7374 "%7.2f %s\n";
7375
7376 char *tput_fmt_1_line_1 = "\
7377 %-6d %-6d %-6d %-6d %-6.2f %7.2f %s\n";
7378
7379 char *tput_fmt_1_line_2 = "\
7380 %-6d %-6d\n";
7381
7382 char *cpu_title = "\
7383 Local /Remote\n\
7384 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
7385 Send Recv Size Size Time Rate local remote local remote\n\
7386 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
7387
7388 char *cpu_title_tput = "\
7389 Local /Remote\n\
7390 Socket Size Request Resp. Elapsed Tput CPU CPU S.dem S.dem\n\
7391 Send Recv Size Size Time %-8.8s local remote local remote\n\
7392 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
7393
7394 char *cpu_fmt_0 =
7395 "%6.3f %c %s\n";
7396
7397 char *cpu_fmt_1_line_1 = "\
7398 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f %s\n";
7399
7400 char *cpu_fmt_1_line_2 = "\
7401 %-6d %-6d\n";
7402
7403 float elapsed_time;
7404
7405 struct ring_elt *send_ring;
7406 struct ring_elt *recv_ring;
7407
7408 int len;
7409 int nummessages;
7410 SOCKET send_socket;
7411 int trans_remaining;
7412 int bytes_xferd;
7413
7414 int rsp_bytes_recvd;
7415
7416 float local_cpu_utilization;
7417 float local_service_demand;
7418 float remote_cpu_utilization;
7419 float remote_service_demand;
7420 double thruput;
7421
7422 struct addrinfo *local_res;
7423 struct addrinfo *remote_res;
7424
7425 struct udp_rr_request_struct *udp_rr_request;
7426 struct udp_rr_response_struct *udp_rr_response;
7427 struct udp_rr_results_struct *udp_rr_result;
7428
7429 udp_rr_request =
7430 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
7431 udp_rr_response =
7432 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
7433 udp_rr_result =
7434 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
7435
7436 #ifdef WANT_HISTOGRAM
7437 if (verbosity > 1) {
7438 time_hist = HIST_new();
7439 }
7440 #endif
7441
7442 /* since we are now disconnected from the code that established the */
7443 /* control socket, and since we want to be able to use different */
7444 /* protocols and such, we are passed the name of the remote host and */
7445 /* must turn that into the test specific addressing information. */
7446
7447 complete_addrinfos(&remote_res,
7448 &local_res,
7449 remote_host,
7450 SOCK_DGRAM,
7451 IPPROTO_UDP,
7452 0);
7453
7454 if ( print_headers ) {
7455 print_top_test_header("UDP REQUEST/RESPONSE TEST",local_res,remote_res);
7456 }
7457
7458 /* initialize a few counters */
7459
7460 send_ring = NULL;
7461 recv_ring = NULL;
7462 nummessages = 0;
7463 bytes_xferd = 0;
7464 times_up = 0;
7465 confidence_iteration = 1;
7466 init_stat();
7467
7468 /* we have a great-big while loop which controls the number of times */
7469 /* we run a particular test. this is for the calculation of a */
7470 /* confidence interval (I really should have stayed awake during */
7471 /* probstats :). If the user did not request confidence measurement */
7472 /* (no confidence is the default) then we will only go though the */
7473 /* loop once. the confidence stuff originates from the folks at IBM */
7474
7475 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
7476 (confidence_iteration <= iteration_min)) {
7477
7478 nummessages = 0;
7479 bytes_xferd = 0;
7480 times_up = 0;
7481 trans_remaining = 0;
7482
7483 /* set-up the data buffers with the requested alignment and offset */
7484
7485 if (send_width == 0) send_width = 1;
7486 if (recv_width == 0) recv_width = 1;
7487
7488 if (send_ring == NULL) {
7489 send_ring = allocate_buffer_ring(send_width,
7490 req_size,
7491 local_send_align,
7492 local_send_offset);
7493 }
7494
7495 if (recv_ring == NULL) {
7496 recv_ring = allocate_buffer_ring(recv_width,
7497 rsp_size,
7498 local_recv_align,
7499 local_recv_offset);
7500 }
7501
7502 /*set up the data socket */
7503 send_socket = create_data_socket(local_res);
7504
7505 if (send_socket == INVALID_SOCKET){
7506 perror("netperf: send_udp_rr: udp rr data socket");
7507 exit(1);
7508 }
7509
7510 if (debug) {
7511 fprintf(where,"send_udp_rr: send_socket obtained...\n");
7512 }
7513
7514 /* If the user has requested cpu utilization measurements, we must */
7515 /* calibrate the cpu(s). We will perform this task within the tests */
7516 /* themselves. If the user has specified the cpu rate, then */
7517 /* calibrate_local_cpu will return rather quickly as it will have */
7518 /* nothing to do. If local_cpu_rate is zero, then we will go through */
7519 /* all the "normal" calibration stuff and return the rate back. If */
7520 /* there is no idle counter in the kernel idle loop, the */
7521 /* local_cpu_rate will be set to -1. */
7522
7523 if (local_cpu_usage) {
7524 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
7525 }
7526
7527 if (!no_control) {
7528 /* Tell the remote end to do a listen. The server alters the
7529 socket paramters on the other side at this point, hence the
7530 reason for all the values being passed in the setup
7531 message. If the user did not specify any of the parameters,
7532 they will be passed as 0, which will indicate to the remote
7533 that no changes beyond the system's default should be
7534 used. Alignment is the exception, it will default to 8, which
7535 will be no alignment alterations. */
7536
7537 netperf_request.content.request_type = DO_UDP_RR;
7538 udp_rr_request->recv_buf_size = rsr_size_req;
7539 udp_rr_request->send_buf_size = rss_size_req;
7540 udp_rr_request->recv_alignment = remote_recv_align;
7541 udp_rr_request->recv_offset = remote_recv_offset;
7542 udp_rr_request->send_alignment = remote_send_align;
7543 udp_rr_request->send_offset = remote_send_offset;
7544 udp_rr_request->request_size = req_size;
7545 udp_rr_request->response_size = rsp_size;
7546 udp_rr_request->measure_cpu = remote_cpu_usage;
7547 udp_rr_request->cpu_rate = remote_cpu_rate;
7548 udp_rr_request->so_rcvavoid = rem_rcvavoid;
7549 udp_rr_request->so_sndavoid = rem_sndavoid;
7550 if (test_time) {
7551 udp_rr_request->test_length = test_time;
7552 }
7553 else {
7554 udp_rr_request->test_length = test_trans * -1;
7555 }
7556 udp_rr_request->port = atoi(remote_data_port);
7557 udp_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
7558
7559 if (debug > 1) {
7560 fprintf(where,"netperf: send_udp_rr: requesting UDP r/r test\n");
7561 }
7562
7563 send_request();
7564
7565 /* The response from the remote will contain all of the relevant
7566 socket parameters for this test type. We will put them back
7567 into the variables here so they can be displayed if desired.
7568 The remote will have calibrated CPU if necessary, and will
7569 have done all the needed set-up we will have calibrated the
7570 cpu locally before sending the request, and will grab the
7571 counter value right after the connect returns. The remote
7572 will grab the counter right after the accept call. This saves
7573 the hassle of extra messages being sent for the UDP
7574 tests. */
7575
7576 recv_response();
7577
7578 if (!netperf_response.content.serv_errno) {
7579 if (debug)
7580 fprintf(where,"remote listen done.\n");
7581 rsr_size = udp_rr_response->recv_buf_size;
7582 rss_size = udp_rr_response->send_buf_size;
7583 remote_cpu_usage = udp_rr_response->measure_cpu;
7584 remote_cpu_rate = udp_rr_response->cpu_rate;
7585 /* port numbers in proper order */
7586 set_port_number(remote_res,(short)udp_rr_response->data_port_number);
7587 }
7588 else {
7589 Set_errno(netperf_response.content.serv_errno);
7590 fprintf(where,
7591 "netperf: remote error %d",
7592 netperf_response.content.serv_errno);
7593 perror("");
7594 fflush(where);
7595 exit(1);
7596 }
7597 }
7598
7599 #ifdef WANT_DEMO
7600 demo_rr_setup(100);
7601 #endif
7602
7603 /* Connect up to the remote port on the data socket. This will set */
7604 /* the default destination address on this socket. With UDP, this */
7605 /* does make a performance difference as we may not have to do as */
7606 /* many routing lookups, however, I expect that a client would */
7607 /* behave this way. raj 1/94 */
7608
7609 if ( connect(send_socket,
7610 remote_res->ai_addr,
7611 remote_res->ai_addrlen) == INVALID_SOCKET ) {
7612 perror("netperf: data socket connect failed");
7613 exit(1);
7614 }
7615
7616 #ifdef WIN32
7617 /* this is used so the timer thread can close the socket out from */
7618 /* under us, which to date is the easiest/cleanest/least */
7619 /* Windows-specific way I can find to force the winsock calls to */
7620 /* return WSAEINTR with the test is over. anything that will run on */
7621 /* 95 and NT and is closer to what netperf expects from Unix signals */
7622 /* and such would be appreciated raj 1/96 */
7623 win_kludge_socket = send_socket;
7624 #endif /* WIN32 */
7625
7626 /* Data Socket set-up is finished. If there were problems, either the */
7627 /* connect would have failed, or the previous response would have */
7628 /* indicated a problem. I failed to see the value of the extra */
7629 /* message after the accept on the remote. If it failed, we'll see it */
7630 /* here. If it didn't, we might as well start pumping data. */
7631
7632 /* Set-up the test end conditions. For a request/response test, they */
7633 /* can be either time or transaction based. */
7634
7635 if (test_time) {
7636 /* The user wanted to end the test after a period of time. */
7637 times_up = 0;
7638 trans_remaining = 0;
7639 start_timer(test_time);
7640 }
7641 else {
7642 /* The tester wanted to send a number of bytes. */
7643 trans_remaining = test_bytes;
7644 times_up = 1;
7645 }
7646
7647 /* The cpu_start routine will grab the current time and possibly */
7648 /* value of the idle counter for later use in measuring cpu */
7649 /* utilization and/or service demand and thruput. */
7650
7651 cpu_start(local_cpu_usage);
7652
7653 #ifdef WANT_DEMO
7654 if (demo_mode) {
7655 demo_first_timestamp();
7656 }
7657 #endif
7658
7659 #ifdef WANT_INTERVALS
7660 INTERVALS_INIT();
7661 #endif /* WANT_INTERVALS */
7662
7663 /* We use an "OR" to control test execution. When the test is */
7664 /* controlled by time, the byte count check will always return */
7665 /* false. When the test is controlled by byte count, the time test */
7666 /* will always return false. When the test is finished, the whole */
7667 /* expression will go false and we will stop sending data. I think */
7668 /* I just arbitrarily decrement trans_remaining for the timed */
7669 /* test, but will not do that just yet... One other question is */
7670 /* whether or not the send buffer and the receive buffer should be */
7671 /* the same buffer. */
7672
7673 #ifdef WANT_FIRST_BURST
7674 {
7675 int i;
7676 for (i = 0; i < first_burst_size; i++) {
7677 if((len=send(send_socket,
7678 send_ring->buffer_ptr,
7679 req_size,
7680 0)) != req_size) {
7681 /* we should never hit the end of the test in the first burst */
7682 perror("send_udp_rr: initial burst data send error");
7683 exit(-1);
7684 }
7685 }
7686 }
7687 #endif /* WANT_FIRST_BURST */
7688
7689 while ((!times_up) || (trans_remaining > 0)) {
7690 /* send the request */
7691 #ifdef WANT_HISTOGRAM
7692 if (verbosity > 1) {
7693 HIST_timestamp(&time_one);
7694 }
7695 #endif
7696 if((len=send(send_socket,
7697 send_ring->buffer_ptr,
7698 req_size,
7699 0)) != req_size) {
7700 if (SOCKET_EINTR(len)) {
7701 /* We likely hit */
7702 /* test-end time. */
7703 break;
7704 }
7705 perror("send_udp_rr: data send error");
7706 exit(1);
7707 }
7708 send_ring = send_ring->next;
7709
7710 /* receive the response. with UDP we will get it all, or nothing */
7711
7712 if((rsp_bytes_recvd=recv(send_socket,
7713 recv_ring->buffer_ptr,
7714 rsp_size,
7715 0)) != rsp_size) {
7716 if (SOCKET_EINTR(rsp_bytes_recvd))
7717 {
7718 /* Again, we have likely hit test-end time */
7719 break;
7720 }
7721 perror("send_udp_rr: data recv error");
7722 exit(1);
7723 }
7724 recv_ring = recv_ring->next;
7725
7726 #ifdef WANT_HISTOGRAM
7727 if (verbosity > 1) {
7728 HIST_timestamp(&time_two);
7729 HIST_add(time_hist,delta_micro(&time_one,&time_two));
7730 }
7731
7732 #endif
7733
7734 /* at this point, we may wish to sleep for some period of */
7735 /* time, so we see how long that last transaction just took, */
7736 /* and sleep for the difference of that and the interval. We */
7737 /* will not sleep if the time would be less than a */
7738 /* millisecond. */
7739
7740 #ifdef WANT_DEMO
7741 demo_rr_interval(1);
7742 #endif
7743
7744 #ifdef WANT_INTERVALS
7745 INTERVALS_WAIT();
7746 #endif /* WANT_INTERVALS */
7747
7748 nummessages++;
7749 if (trans_remaining) {
7750 trans_remaining--;
7751 }
7752
7753 if (debug > 3) {
7754 if ((nummessages % 100) == 0) {
7755 fprintf(where,"Transaction %d completed\n",nummessages);
7756 fflush(where);
7757 }
7758 }
7759
7760 }
7761
7762 /* for some strange reason, I used to call shutdown on the UDP */
7763 /* data socket here. I'm not sure why, because it would not have */
7764 /* any effect... raj 11/94 */
7765
7766 /* this call will always give us the elapsed time for the test, and */
7767 /* will also store-away the necessaries for cpu utilization */
7768
7769 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
7770 /* measured? how long */
7771 /* did we really run? */
7772
7773 #if defined(WANT_INTERVALS)
7774 #ifdef WIN32
7775 stop_itimer();
7776 #endif
7777 #endif /* WANT_INTERVALS */
7778
7779 if (!no_control) {
7780 /* Get the statistics from the remote end. The remote will have
7781 calculated service demand and all those interesting
7782 things. If it wasn't supposed to care, it will return obvious
7783 values. */
7784
7785 recv_response();
7786 if (!netperf_response.content.serv_errno) {
7787 if (debug)
7788 fprintf(where,"remote results obtained\n");
7789 }
7790 else {
7791 Set_errno(netperf_response.content.serv_errno);
7792 fprintf(where,
7793 "netperf: remote error %d",
7794 netperf_response.content.serv_errno);
7795 perror("");
7796 fflush(where);
7797 exit(1);
7798 }
7799 }
7800
7801 /* We now calculate what our thruput was for the test. In the */
7802 /* future, we may want to include a calculation of the thruput */
7803 /* measured by the remote, but it should be the case that for a */
7804 /* UDP rr test, that the two numbers should be *very* close... */
7805 /* We calculate bytes_sent regardless of the way the test length */
7806 /* was controlled. */
7807
7808 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
7809 thruput = nummessages / elapsed_time;
7810
7811 if (local_cpu_usage || remote_cpu_usage) {
7812
7813 /* We must now do a little math for service demand and cpu */
7814 /* utilization for the system(s) Of course, some of the */
7815 /* information might be bogus because there was no idle counter */
7816 /* in the kernel(s). We need to make a note of this for the */
7817 /* user's benefit by placing a code for the metod used in the */
7818 /* test banner */
7819
7820 if (local_cpu_usage) {
7821 local_cpu_utilization = calc_cpu_util(0.0);
7822
7823 /* since calc_service demand is doing ms/Kunit we will */
7824 /* multiply the number of transaction by 1024 to get */
7825 /* "good" numbers */
7826
7827 local_service_demand = calc_service_demand((double) nummessages*1024,
7828 0.0,
7829 0.0,
7830 0);
7831 }
7832 else {
7833 local_cpu_utilization = (float) -1.0;
7834 local_service_demand = (float) -1.0;
7835 }
7836
7837 if (remote_cpu_usage) {
7838 remote_cpu_utilization = udp_rr_result->cpu_util;
7839
7840 /* since calc_service demand is doing ms/Kunit we will */
7841 /* multiply the number of transaction by 1024 to get */
7842 /* "good" numbers */
7843
7844 remote_service_demand = calc_service_demand((double) nummessages*1024,
7845 0.0,
7846 remote_cpu_utilization,
7847 udp_rr_result->num_cpus);
7848 }
7849 else {
7850 remote_cpu_utilization = (float) -1.0;
7851 remote_service_demand = (float) -1.0;
7852 }
7853 }
7854 else {
7855 /* we were not measuring cpu, for the confidence stuff, we */
7856 /* should make it -1.0 */
7857 local_cpu_utilization = (float) -1.0;
7858 local_service_demand = (float) -1.0;
7859 remote_cpu_utilization = (float) -1.0;
7860 remote_service_demand = (float) -1.0;
7861 }
7862
7863 /* at this point, we want to calculate the confidence information. */
7864 /* if debugging is on, calculate_confidence will print-out the */
7865 /* parameters we pass it */
7866
7867 calculate_confidence(confidence_iteration,
7868 elapsed_time,
7869 thruput,
7870 local_cpu_utilization,
7871 remote_cpu_utilization,
7872 local_service_demand,
7873 remote_service_demand);
7874
7875
7876 confidence_iteration++;
7877
7878 /* we are done with the socket */
7879 close(send_socket);
7880 }
7881
7882 /* at this point, we have made all the iterations we are going to */
7883 /* make. */
7884 retrieve_confident_values(&elapsed_time,
7885 &thruput,
7886 &local_cpu_utilization,
7887 &remote_cpu_utilization,
7888 &local_service_demand,
7889 &remote_service_demand);
7890
7891 /* We are now ready to print all the information. If the user */
7892 /* has specified zero-level verbosity, we will just print the */
7893 /* local service demand, or the remote service demand. If the */
7894 /* user has requested verbosity level 1, he will get the basic */
7895 /* "streamperf" numbers. If the user has specified a verbosity */
7896 /* of greater than 1, we will display a veritable plethora of */
7897 /* background information from outside of this block as it it */
7898 /* not cpu_measurement specific... */
7899
7900 if (confidence < 0) {
7901 /* we did not hit confidence, but were we asked to look for it? */
7902 if (iteration_max > 1) {
7903 display_confidence();
7904 }
7905 }
7906
7907 if (local_cpu_usage || remote_cpu_usage) {
7908 local_cpu_method = format_cpu_method(cpu_method);
7909 remote_cpu_method = format_cpu_method(udp_rr_result->cpu_method);
7910
7911 switch (verbosity) {
7912 case 0:
7913 if (local_cpu_usage) {
7914 fprintf(where,
7915 cpu_fmt_0,
7916 local_service_demand,
7917 local_cpu_method,
7918 ((print_headers) ||
7919 (result_brand == NULL)) ? "" : result_brand);
7920
7921 }
7922 else {
7923 fprintf(where,
7924 cpu_fmt_0,
7925 remote_service_demand,
7926 remote_cpu_method,
7927 ((print_headers) ||
7928 (result_brand == NULL)) ? "" : result_brand);
7929
7930 }
7931 break;
7932 case 1:
7933 case 2:
7934 if (print_headers) {
7935 if ('x' == libfmt) {
7936 fprintf(where,
7937 cpu_title,
7938 local_cpu_method,
7939 remote_cpu_method);
7940 }
7941 else {
7942 fprintf(where,
7943 cpu_title_tput,
7944 format_units(),
7945 local_cpu_method,
7946 remote_cpu_method);
7947 }
7948 }
7949
7950 fprintf(where,
7951 cpu_fmt_1_line_1, /* the format string */
7952 lss_size, /* local sendbuf size */
7953 lsr_size,
7954 req_size, /* how large were the requests */
7955 rsp_size, /* guess */
7956 elapsed_time, /* how long was the test */
7957 ('x' == libfmt) ? thruput :
7958 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
7959 1.0),
7960 local_cpu_utilization, /* local cpu */
7961 remote_cpu_utilization, /* remote cpu */
7962 local_service_demand, /* local service demand */
7963 remote_service_demand, /* remote service demand */
7964 ((print_headers) ||
7965 (result_brand == NULL)) ? "" : result_brand);
7966 fprintf(where,
7967 cpu_fmt_1_line_2,
7968 rss_size,
7969 rsr_size);
7970 break;
7971 }
7972 }
7973 else {
7974 /* The tester did not wish to measure service demand. */
7975 switch (verbosity) {
7976 case 0:
7977 fprintf(where,
7978 tput_fmt_0,
7979 ('x' == libfmt) ? thruput :
7980 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
7981 1.0),
7982 ((print_headers) ||
7983 (result_brand == NULL)) ? "" : result_brand);
7984 break;
7985 case 1:
7986 case 2:
7987 if (print_headers) {
7988 fprintf(where,
7989 ('x' == libfmt) ? tput_title : tput_title_band,
7990 format_units());
7991 }
7992
7993 fprintf(where,
7994 tput_fmt_1_line_1, /* the format string */
7995 lss_size,
7996 lsr_size,
7997 req_size, /* how large were the requests */
7998 rsp_size, /* how large were the responses */
7999 elapsed_time, /* how long did it take */
8000 ('x' == libfmt) ? thruput :
8001 calc_thruput_interval_omni(thruput * (req_size+rsp_size),
8002 1.0),
8003 ((print_headers) ||
8004 (result_brand == NULL)) ? "" : result_brand);
8005 fprintf(where,
8006 tput_fmt_1_line_2,
8007 rss_size, /* remote recvbuf size */
8008 rsr_size);
8009
8010 break;
8011 }
8012 }
8013 fflush(where);
8014
8015 /* it would be a good thing to include information about some of the */
8016 /* other parameters that may have been set for this test, but at the */
8017 /* moment, I do not wish to figure-out all the formatting, so I will */
8018 /* just put this comment here to help remind me that it is something */
8019 /* that should be done at a later time. */
8020
8021 /* how to handle the verbose information in the presence of */
8022 /* confidence intervals is yet to be determined... raj 11/94 */
8023
8024 if (verbosity > 1) {
8025 /* The user wanted to know it all, so we will give it to him. */
8026 /* This information will include as much as we can find about */
8027 /* UDP statistics, the alignments of the sends and receives */
8028 /* and all that sort of rot... */
8029
8030 #ifdef WANT_HISTOGRAM
8031 fprintf(where,"\nHistogram of request/reponse times.\n");
8032 fflush(where);
8033 HIST_report(time_hist);
8034 #endif /* WANT_HISTOGRAM */
8035 }
8036 }
8037 #endif /* WANT_MIGRATION */
8038
8039 /* this routine implements the receive side (netserver) of a UDP_RR */
8040 /* test. */
8041 void
recv_udp_rr()8042 recv_udp_rr()
8043 {
8044
8045 struct ring_elt *recv_ring;
8046 struct ring_elt *send_ring;
8047
8048 struct addrinfo *local_res;
8049 char local_name[BUFSIZ];
8050 char port_buffer[PORTBUFSIZE];
8051
8052 struct sockaddr_storage myaddr_in;
8053 struct sockaddr_storage peeraddr;
8054 SOCKET s_data;
8055 netperf_socklen_t addrlen;
8056 int trans_received;
8057 int trans_remaining;
8058 int request_bytes_recvd;
8059 int response_bytes_sent;
8060 float elapsed_time;
8061
8062 struct udp_rr_request_struct *udp_rr_request;
8063 struct udp_rr_response_struct *udp_rr_response;
8064 struct udp_rr_results_struct *udp_rr_results;
8065
8066 udp_rr_request =
8067 (struct udp_rr_request_struct *)netperf_request.content.test_specific_data;
8068 udp_rr_response =
8069 (struct udp_rr_response_struct *)netperf_response.content.test_specific_data;
8070 udp_rr_results =
8071 (struct udp_rr_results_struct *)netperf_response.content.test_specific_data;
8072
8073 if (debug) {
8074 fprintf(where,"netserver: recv_udp_rr: entered...\n");
8075 fflush(where);
8076 }
8077
8078 /* We want to set-up the listen socket with all the desired */
8079 /* parameters and then let the initiator know that all is ready. If */
8080 /* socket size defaults are to be used, then the initiator will have */
8081 /* sent us 0's. If the socket sizes cannot be changed, then we will */
8082 /* send-back what they are. If that information cannot be determined, */
8083 /* then we send-back -1's for the sizes. If things go wrong for any */
8084 /* reason, we will drop back ten yards and punt. */
8085
8086 /* If anything goes wrong, we want the remote to know about it. It */
8087 /* would be best if the error that the remote reports to the user is */
8088 /* the actual error we encountered, rather than some bogus unexpected */
8089 /* response type message. */
8090
8091 if (debug) {
8092 fprintf(where,"recv_udp_rr: setting the response type...\n");
8093 fflush(where);
8094 }
8095
8096 netperf_response.content.response_type = UDP_RR_RESPONSE;
8097
8098 if (debug) {
8099 fprintf(where,"recv_udp_rr: the response type is set...\n");
8100 fflush(where);
8101 }
8102
8103 /* We now alter the message_ptr variables to be at the desired */
8104 /* alignments with the desired offsets. */
8105
8106 if (debug) {
8107 fprintf(where,"recv_udp_rr: requested recv alignment of %d offset %d\n",
8108 udp_rr_request->recv_alignment,
8109 udp_rr_request->recv_offset);
8110 fprintf(where,"recv_udp_rr: requested send alignment of %d offset %d\n",
8111 udp_rr_request->send_alignment,
8112 udp_rr_request->send_offset);
8113 fflush(where);
8114 }
8115
8116 if (send_width == 0) send_width = 1;
8117 if (recv_width == 0) recv_width = 1;
8118
8119 recv_ring = allocate_buffer_ring(recv_width,
8120 udp_rr_request->request_size,
8121 udp_rr_request->recv_alignment,
8122 udp_rr_request->recv_offset);
8123
8124 send_ring = allocate_buffer_ring(send_width,
8125 udp_rr_request->response_size,
8126 udp_rr_request->send_alignment,
8127 udp_rr_request->send_offset);
8128
8129 if (debug) {
8130 fprintf(where,"recv_udp_rr: receive alignment and offset set...\n");
8131 fflush(where);
8132 }
8133
8134 /* Grab a socket to listen on, and then listen on it. */
8135
8136 if (debug) {
8137 fprintf(where,"recv_udp_rr: grabbing a socket...\n");
8138 fflush(where);
8139 }
8140
8141
8142 /* create_data_socket expects to find some things in the global */
8143 /* variables, so set the globals based on the values in the request. */
8144 /* once the socket has been created, we will set the response values */
8145 /* based on the updated value of those globals. raj 7/94 */
8146 lss_size_req = udp_rr_request->send_buf_size;
8147 lsr_size_req = udp_rr_request->recv_buf_size;
8148 loc_rcvavoid = udp_rr_request->so_rcvavoid;
8149 loc_sndavoid = udp_rr_request->so_sndavoid;
8150
8151 set_hostname_and_port(local_name,
8152 port_buffer,
8153 nf_to_af(udp_rr_request->ipfamily),
8154 udp_rr_request->port);
8155
8156 local_res = complete_addrinfo(local_name,
8157 local_name,
8158 port_buffer,
8159 nf_to_af(udp_rr_request->ipfamily),
8160 SOCK_DGRAM,
8161 IPPROTO_UDP,
8162 0);
8163
8164 s_data = create_data_socket(local_res);
8165
8166 if (s_data == INVALID_SOCKET) {
8167 netperf_response.content.serv_errno = errno;
8168 send_response();
8169
8170 exit(1);
8171 }
8172
8173 /* now get the port number assigned by the system */
8174 addrlen = sizeof(myaddr_in);
8175 if (getsockname(s_data,
8176 (struct sockaddr *)&myaddr_in,
8177 &addrlen) == SOCKET_ERROR){
8178 netperf_response.content.serv_errno = errno;
8179 close(s_data);
8180 send_response();
8181
8182 exit(1);
8183 }
8184
8185 /* Now myaddr_in contains the port and the internet address this is */
8186 /* returned to the sender also implicitly telling the sender that the */
8187 /* socket buffer sizing has been done. */
8188
8189 udp_rr_response->data_port_number =
8190 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
8191 netperf_response.content.serv_errno = 0;
8192
8193 if (debug) {
8194 fprintf(where,
8195 "recv port number %d\n",
8196 ((struct sockaddr_in *)&myaddr_in)->sin_port);
8197 fflush(where);
8198 }
8199
8200 /* But wait, there's more. If the initiator wanted cpu measurements, */
8201 /* then we must call the calibrate routine, which will return the max */
8202 /* rate back to the initiator. If the CPU was not to be measured, or */
8203 /* something went wrong with the calibration, we will return a 0.0 to */
8204 /* the initiator. */
8205
8206 udp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
8207 udp_rr_response->measure_cpu = 0;
8208 if (udp_rr_request->measure_cpu) {
8209 udp_rr_response->measure_cpu = 1;
8210 udp_rr_response->cpu_rate = calibrate_local_cpu(udp_rr_request->cpu_rate);
8211 }
8212
8213 /* before we send the response back to the initiator, pull some of */
8214 /* the socket parms from the globals */
8215 udp_rr_response->send_buf_size = lss_size;
8216 udp_rr_response->recv_buf_size = lsr_size;
8217 udp_rr_response->so_rcvavoid = loc_rcvavoid;
8218 udp_rr_response->so_sndavoid = loc_sndavoid;
8219
8220 send_response();
8221
8222
8223 /* Now it's time to start receiving data on the connection. We will */
8224 /* first grab the apropriate counters and then start grabbing. */
8225
8226 cpu_start(udp_rr_request->measure_cpu);
8227
8228 #ifdef WIN32
8229 /* this is used so the timer thread can close the socket out from */
8230 /* under us, which to date is the easiest/cleanest/least */
8231 /* Windows-specific way I can find to force the winsock calls to */
8232 /* return WSAEINTR with the test is over. anything that will run on */
8233 /* 95 and NT and is closer to what netperf expects from Unix signals */
8234 /* and such would be appreciated raj 1/96 */
8235 win_kludge_socket = s_data;
8236 #endif /* WIN32 */
8237
8238 if (udp_rr_request->test_length > 0) {
8239 times_up = 0;
8240 trans_remaining = 0;
8241 start_timer(udp_rr_request->test_length + PAD_TIME);
8242 }
8243 else {
8244 times_up = 1;
8245 trans_remaining = udp_rr_request->test_length * -1;
8246 }
8247
8248 addrlen = sizeof(peeraddr);
8249 bzero((char *)&peeraddr, addrlen);
8250
8251 trans_received = 0;
8252
8253 while ((!times_up) || (trans_remaining > 0)) {
8254
8255 /* receive the request from the other side */
8256 if ((request_bytes_recvd = recvfrom(s_data,
8257 recv_ring->buffer_ptr,
8258 udp_rr_request->request_size,
8259 0,
8260 (struct sockaddr *)&peeraddr,
8261 &addrlen)) != udp_rr_request->request_size) {
8262 if ( SOCKET_EINTR(request_bytes_recvd) )
8263 {
8264 /* we must have hit the end of test time. */
8265 break;
8266 }
8267 netperf_response.content.serv_errno = errno;
8268 send_response();
8269 exit(1);
8270 }
8271 recv_ring = recv_ring->next;
8272
8273 /* Now, send the response to the remote */
8274 if ((response_bytes_sent = sendto(s_data,
8275 send_ring->buffer_ptr,
8276 udp_rr_request->response_size,
8277 0,
8278 (struct sockaddr *)&peeraddr,
8279 addrlen)) !=
8280 udp_rr_request->response_size) {
8281 if ( SOCKET_EINTR(response_bytes_sent) )
8282 {
8283 /* we have hit end of test time. */
8284 break;
8285 }
8286 netperf_response.content.serv_errno = errno;
8287 send_response();
8288 exit(1);
8289 }
8290 send_ring = send_ring->next;
8291
8292 trans_received++;
8293 if (trans_remaining) {
8294 trans_remaining--;
8295 }
8296
8297 if (debug) {
8298 fprintf(where,
8299 "recv_udp_rr: Transaction %d complete.\n",
8300 trans_received);
8301 fflush(where);
8302 }
8303
8304 }
8305
8306
8307 /* The loop now exits due to timeout or transaction count being */
8308 /* reached */
8309
8310 cpu_stop(udp_rr_request->measure_cpu,&elapsed_time);
8311
8312 if (times_up) {
8313 /* we ended the test by time, which was at least 2 seconds */
8314 /* longer than we wanted to run. so, we want to subtract */
8315 /* PAD_TIME from the elapsed_time. */
8316 elapsed_time -= PAD_TIME;
8317 }
8318 /* send the results to the sender */
8319
8320 if (debug) {
8321 fprintf(where,
8322 "recv_udp_rr: got %d transactions\n",
8323 trans_received);
8324 fflush(where);
8325 }
8326
8327 udp_rr_results->bytes_received = (trans_received *
8328 (udp_rr_request->request_size +
8329 udp_rr_request->response_size));
8330 udp_rr_results->trans_received = trans_received;
8331 udp_rr_results->elapsed_time = elapsed_time;
8332 udp_rr_results->cpu_method = cpu_method;
8333 udp_rr_results->num_cpus = lib_num_loc_cpus;
8334 if (udp_rr_request->measure_cpu) {
8335 udp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
8336 }
8337
8338 if (debug) {
8339 fprintf(where,
8340 "recv_udp_rr: test complete, sending results.\n");
8341 fflush(where);
8342 }
8343
8344 send_response();
8345
8346 /* we are done with the socket now */
8347 close(s_data);
8348
8349 }
8350
8351
8352 /* this routine implements the receive (netserver) side of a TCP_RR */
8353 /* test */
8354 void
recv_tcp_rr()8355 recv_tcp_rr()
8356 {
8357
8358 struct ring_elt *send_ring;
8359 struct ring_elt *recv_ring;
8360
8361 struct addrinfo *local_res;
8362 char local_name[BUFSIZ];
8363 char port_buffer[PORTBUFSIZE];
8364
8365 struct sockaddr_storage myaddr_in,
8366 peeraddr_in;
8367 SOCKET s_listen,s_data;
8368 netperf_socklen_t addrlen;
8369 char *temp_message_ptr;
8370 int trans_received;
8371 int trans_remaining;
8372 int bytes_sent;
8373 int request_bytes_recvd;
8374 int request_bytes_remaining;
8375 int timed_out = 0;
8376 int sock_closed = 0;
8377 float elapsed_time;
8378
8379 struct tcp_rr_request_struct *tcp_rr_request;
8380 struct tcp_rr_response_struct *tcp_rr_response;
8381 struct tcp_rr_results_struct *tcp_rr_results;
8382
8383 tcp_rr_request =
8384 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
8385 tcp_rr_response =
8386 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
8387 tcp_rr_results =
8388 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
8389
8390 if (debug) {
8391 fprintf(where,"netserver: recv_tcp_rr: entered...\n");
8392 fflush(where);
8393 }
8394
8395 /* We want to set-up the listen socket with all the desired */
8396 /* parameters and then let the initiator know that all is ready. If */
8397 /* socket size defaults are to be used, then the initiator will have */
8398 /* sent us 0's. If the socket sizes cannot be changed, then we will */
8399 /* send-back what they are. If that information cannot be determined, */
8400 /* then we send-back -1's for the sizes. If things go wrong for any */
8401 /* reason, we will drop back ten yards and punt. */
8402
8403 /* If anything goes wrong, we want the remote to know about it. It */
8404 /* would be best if the error that the remote reports to the user is */
8405 /* the actual error we encountered, rather than some bogus unexpected */
8406 /* response type message. */
8407
8408 if (debug) {
8409 fprintf(where,"recv_tcp_rr: setting the response type...\n");
8410 fflush(where);
8411 }
8412
8413 netperf_response.content.response_type = TCP_RR_RESPONSE;
8414
8415 if (debug) {
8416 fprintf(where,"recv_tcp_rr: the response type is set...\n");
8417 fflush(where);
8418 }
8419
8420 /* allocate the recv and send rings with the requested alignments */
8421 /* and offsets. raj 7/94 */
8422 if (debug) {
8423 fprintf(where,"recv_tcp_rr: requested recv alignment of %d offset %d\n",
8424 tcp_rr_request->recv_alignment,
8425 tcp_rr_request->recv_offset);
8426 fprintf(where,"recv_tcp_rr: requested send alignment of %d offset %d\n",
8427 tcp_rr_request->send_alignment,
8428 tcp_rr_request->send_offset);
8429 fflush(where);
8430 }
8431
8432 /* at some point, these need to come to us from the remote system */
8433 if (send_width == 0) send_width = 1;
8434 if (recv_width == 0) recv_width = 1;
8435
8436 send_ring = allocate_buffer_ring(send_width,
8437 tcp_rr_request->response_size,
8438 tcp_rr_request->send_alignment,
8439 tcp_rr_request->send_offset);
8440
8441 recv_ring = allocate_buffer_ring(recv_width,
8442 tcp_rr_request->request_size,
8443 tcp_rr_request->recv_alignment,
8444 tcp_rr_request->recv_offset);
8445
8446
8447 /* Grab a socket to listen on, and then listen on it. */
8448
8449 if (debug) {
8450 fprintf(where,"recv_tcp_rr: grabbing a socket...\n");
8451 fflush(where);
8452 }
8453
8454 /* create_data_socket expects to find some things in the global */
8455 /* variables, so set the globals based on the values in the request. */
8456 /* once the socket has been created, we will set the response values */
8457 /* based on the updated value of those globals. raj 7/94 */
8458 lss_size_req = tcp_rr_request->send_buf_size;
8459 lsr_size_req = tcp_rr_request->recv_buf_size;
8460 loc_nodelay = tcp_rr_request->no_delay;
8461 loc_rcvavoid = tcp_rr_request->so_rcvavoid;
8462 loc_sndavoid = tcp_rr_request->so_sndavoid;
8463
8464 set_hostname_and_port(local_name,
8465 port_buffer,
8466 nf_to_af(tcp_rr_request->ipfamily),
8467 tcp_rr_request->port);
8468
8469 local_res = complete_addrinfo(local_name,
8470 local_name,
8471 port_buffer,
8472 nf_to_af(tcp_rr_request->ipfamily),
8473 SOCK_STREAM,
8474 IPPROTO_TCP,
8475 0);
8476
8477 s_listen = create_data_socket(local_res);
8478
8479 if (s_listen == INVALID_SOCKET) {
8480 netperf_response.content.serv_errno = errno;
8481 send_response();
8482
8483 exit(1);
8484 }
8485
8486
8487 #ifdef WIN32
8488 /* The test timer can fire during operations on the listening socket,
8489 so to make the start_timer below work we have to move
8490 it to close s_listen while we are blocked on accept. */
8491 win_kludge_socket2 = s_listen;
8492 #endif
8493
8494
8495 /* Now, let's set-up the socket to listen for connections */
8496 if (listen(s_listen, 5) == SOCKET_ERROR) {
8497 netperf_response.content.serv_errno = errno;
8498 close(s_listen);
8499 send_response();
8500
8501 exit(1);
8502 }
8503
8504
8505 /* now get the port number assigned by the system */
8506 addrlen = sizeof(myaddr_in);
8507 if (getsockname(s_listen,
8508 (struct sockaddr *)&myaddr_in,
8509 &addrlen) == SOCKET_ERROR) {
8510 netperf_response.content.serv_errno = errno;
8511 close(s_listen);
8512 send_response();
8513
8514 exit(1);
8515 }
8516
8517 /* Now myaddr_in contains the port and the internet address this is */
8518 /* returned to the sender also implicitly telling the sender that the */
8519 /* socket buffer sizing has been done. */
8520
8521 tcp_rr_response->data_port_number =
8522 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
8523 netperf_response.content.serv_errno = 0;
8524
8525 /* But wait, there's more. If the initiator wanted cpu measurements, */
8526 /* then we must call the calibrate routine, which will return the max */
8527 /* rate back to the initiator. If the CPU was not to be measured, or */
8528 /* something went wrong with the calibration, we will return a 0.0 to */
8529 /* the initiator. */
8530
8531 tcp_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
8532 tcp_rr_response->measure_cpu = 0;
8533
8534 if (tcp_rr_request->measure_cpu) {
8535 tcp_rr_response->measure_cpu = 1;
8536 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
8537 }
8538
8539
8540 /* before we send the response back to the initiator, pull some of */
8541 /* the socket parms from the globals */
8542 tcp_rr_response->send_buf_size = lss_size;
8543 tcp_rr_response->recv_buf_size = lsr_size;
8544 tcp_rr_response->no_delay = loc_nodelay;
8545 tcp_rr_response->so_rcvavoid = loc_rcvavoid;
8546 tcp_rr_response->so_sndavoid = loc_sndavoid;
8547 tcp_rr_response->test_length = tcp_rr_request->test_length;
8548 send_response();
8549
8550 addrlen = sizeof(peeraddr_in);
8551
8552 if ((s_data = accept(s_listen,
8553 (struct sockaddr *)&peeraddr_in,
8554 &addrlen)) == INVALID_SOCKET) {
8555 /* Let's just punt. The remote will be given some information */
8556 close(s_listen);
8557
8558 exit(1);
8559 }
8560
8561 #ifdef KLUDGE_SOCKET_OPTIONS
8562 /* this is for those systems which *INCORRECTLY* fail to pass */
8563 /* attributes across an accept() call. Including this goes against */
8564 /* my better judgement :( raj 11/95 */
8565
8566 kludge_socket_options(s_data);
8567
8568 #endif /* KLUDGE_SOCKET_OPTIONS */
8569
8570 #ifdef WIN32
8571 /* this is used so the timer thread can close the socket out from */
8572 /* under us, which to date is the easiest/cleanest/least */
8573 /* Windows-specific way I can find to force the winsock calls to */
8574 /* return WSAEINTR with the test is over. anything that will run on */
8575 /* 95 and NT and is closer to what netperf expects from Unix signals */
8576 /* and such would be appreciated raj 1/96 */
8577 win_kludge_socket = s_data;
8578 win_kludge_socket2 = INVALID_SOCKET;
8579 #endif /* WIN32 */
8580
8581 if (debug) {
8582 fprintf(where,"recv_tcp_rr: accept completes on the data connection.\n");
8583 fflush(where);
8584 }
8585
8586 /* Now it's time to start receiving data on the connection. We will */
8587 /* first grab the apropriate counters and then start grabbing. */
8588
8589 cpu_start(tcp_rr_request->measure_cpu);
8590
8591 /* The loop will exit when we hit the end of the test time, or when */
8592 /* we have exchanged the requested number of transactions. */
8593
8594 if (tcp_rr_request->test_length > 0) {
8595 times_up = 0;
8596 trans_remaining = 0;
8597 start_timer(tcp_rr_request->test_length + PAD_TIME);
8598 }
8599 else {
8600 times_up = 1;
8601 trans_remaining = tcp_rr_request->test_length * -1;
8602 }
8603
8604 trans_received = 0;
8605
8606 while ((!times_up) || (trans_remaining > 0)) {
8607 temp_message_ptr = recv_ring->buffer_ptr;
8608 request_bytes_remaining = tcp_rr_request->request_size;
8609 while(request_bytes_remaining > 0) {
8610 if((request_bytes_recvd=recv(s_data,
8611 temp_message_ptr,
8612 request_bytes_remaining,
8613 0)) == SOCKET_ERROR) {
8614 if (SOCKET_EINTR(request_bytes_recvd))
8615 {
8616 timed_out = 1;
8617 break;
8618 }
8619
8620 netperf_response.content.serv_errno = errno;
8621 send_response();
8622 exit(1);
8623 }
8624 else if( request_bytes_recvd == 0 ) {
8625 if (debug) {
8626 fprintf(where,"zero is my hero\n");
8627 fflush(where);
8628 }
8629 sock_closed = 1;
8630 break;
8631 }
8632 else {
8633 request_bytes_remaining -= request_bytes_recvd;
8634 temp_message_ptr += request_bytes_recvd;
8635 }
8636 }
8637
8638 recv_ring = recv_ring->next;
8639
8640 if ((timed_out) || (sock_closed)) {
8641 /* we hit the end of the test based on time - or the socket
8642 closed on us along the way. bail out of here now... */
8643 if (debug) {
8644 fprintf(where,"yo5\n");
8645 fflush(where);
8646 }
8647 break;
8648 }
8649
8650 /* Now, send the response to the remote */
8651 if((bytes_sent=send(s_data,
8652 send_ring->buffer_ptr,
8653 tcp_rr_request->response_size,
8654 0)) == SOCKET_ERROR) {
8655 if (SOCKET_EINTR(bytes_sent)) {
8656 /* the test timer has popped */
8657 timed_out = 1;
8658 fprintf(where,"yo6\n");
8659 fflush(where);
8660 break;
8661 }
8662 netperf_response.content.serv_errno = 992;
8663 send_response();
8664 exit(1);
8665 }
8666
8667 send_ring = send_ring->next;
8668
8669 trans_received++;
8670 if (trans_remaining) {
8671 trans_remaining--;
8672 }
8673 }
8674
8675
8676 /* The loop now exits due to timeout or transaction count being */
8677 /* reached */
8678
8679 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
8680
8681 stop_timer();
8682
8683 if (timed_out) {
8684 /* we ended the test by time, which was at least 2 seconds */
8685 /* longer than we wanted to run. so, we want to subtract */
8686 /* PAD_TIME from the elapsed_time. */
8687 elapsed_time -= PAD_TIME;
8688 }
8689
8690 /* send the results to the sender */
8691
8692 if (debug) {
8693 fprintf(where,
8694 "recv_tcp_rr: got %d transactions\n",
8695 trans_received);
8696 fflush(where);
8697 }
8698
8699 tcp_rr_results->bytes_received = (trans_received *
8700 (tcp_rr_request->request_size +
8701 tcp_rr_request->response_size));
8702 tcp_rr_results->trans_received = trans_received;
8703 tcp_rr_results->elapsed_time = elapsed_time;
8704 tcp_rr_results->cpu_method = cpu_method;
8705 tcp_rr_results->num_cpus = lib_num_loc_cpus;
8706 if (tcp_rr_request->measure_cpu) {
8707 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
8708 }
8709
8710 if (debug) {
8711 fprintf(where,
8712 "recv_tcp_rr: test complete, sending results.\n");
8713 fflush(where);
8714 }
8715
8716 /* we are now done with the sockets */
8717 close(s_data);
8718 close(s_listen);
8719
8720 send_response();
8721
8722 }
8723
8724
8725 void
loc_cpu_rate()8726 loc_cpu_rate()
8727 {
8728 #if defined(USE_LOOPER)
8729 float dummy;
8730 #endif
8731
8732 /* a rather simple little test - it merely calibrates the local cpu */
8733 /* and prints the results. There are no headers to allow someone to */
8734 /* find a rate and use it in other tests automagically by setting a */
8735 /* variable equal to the output of this test. We ignore any rates */
8736 /* that may have been specified. In fact, we ignore all of the */
8737 /* command line args! */
8738
8739 fprintf(where,
8740 "%g",
8741 calibrate_local_cpu(0.0));
8742
8743 if (verbosity > 1)
8744 fprintf(where,
8745 "\nThere %s %d local %s\n",
8746 (lib_num_loc_cpus > 1) ? "are" : "is",
8747 lib_num_loc_cpus,
8748 (lib_num_loc_cpus > 1) ? "cpus" : "cpu");
8749
8750 /* we need the cpu_start, cpu_stop in the looper case to kill the */
8751 /* child proceses raj 4/95 */
8752
8753 #ifdef USE_LOOPER
8754 cpu_start(1);
8755 cpu_stop(1,&dummy);
8756 #endif /* USE_LOOPER */
8757
8758 }
8759
8760 void
rem_cpu_rate()8761 rem_cpu_rate()
8762 {
8763 /* this test is much like the local variant, except that it works for */
8764 /* the remote system, so in this case, we do pay attention to the */
8765 /* value of the '-H' command line argument. */
8766
8767 fprintf(where,
8768 "%g",
8769 calibrate_remote_cpu());
8770
8771 if (verbosity > 1)
8772 fprintf(where,
8773 "\nThere %s %d remote %s\n",
8774 (lib_num_rem_cpus > 1) ? "are" : "is",
8775 lib_num_rem_cpus,
8776 (lib_num_rem_cpus > 1) ? "cpus" : "cpu");
8777
8778 }
8779
8780
8781 #ifndef WANT_MIGRATION
8782 /* this test is intended to test the performance of establishing a
8783 connection, exchanging a request/response pair, and repeating. it
8784 is expected that this would be a good starting-point for
8785 comparision of T/TCP with classic TCP for transactional workloads.
8786 it will also look (can look) much like the communication pattern
8787 of http for www access. */
8788
8789 void
send_tcp_conn_rr(char remote_host[])8790 send_tcp_conn_rr(char remote_host[])
8791 {
8792
8793 char *tput_title = "\
8794 Local /Remote\n\
8795 Socket Size Request Resp. Elapsed Trans.\n\
8796 Send Recv Size Size Time Rate \n\
8797 bytes Bytes bytes bytes secs. per sec \n\n";
8798
8799 char *tput_fmt_0 =
8800 "%7.2f\n";
8801
8802 char *tput_fmt_1_line_1 = "\
8803 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
8804 char *tput_fmt_1_line_2 = "\
8805 %-6d %-6d\n";
8806
8807 char *cpu_title = "\
8808 Local /Remote\n\
8809 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
8810 Send Recv Size Size Time Rate local remote local remote\n\
8811 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
8812
8813 char *cpu_fmt_0 =
8814 "%6.3f\n";
8815
8816 char *cpu_fmt_1_line_1 = "\
8817 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
8818
8819 char *cpu_fmt_1_line_2 = "\
8820 %-6d %-6d\n";
8821
8822 char *ksink_fmt = "\n\
8823 Alignment Offset\n\
8824 Local Remote Local Remote\n\
8825 Send Recv Send Recv\n\
8826 %5d %5d %5d %5d\n";
8827
8828
8829 int timed_out = 0;
8830 float elapsed_time;
8831
8832 int len;
8833 struct ring_elt *send_ring;
8834 struct ring_elt *recv_ring;
8835 char *temp_message_ptr;
8836 int nummessages;
8837 SOCKET send_socket;
8838 int trans_remaining;
8839 double bytes_xferd;
8840 int rsp_bytes_left;
8841 int rsp_bytes_recvd;
8842
8843 float local_cpu_utilization;
8844 float local_service_demand;
8845 float remote_cpu_utilization;
8846 float remote_service_demand;
8847 double thruput;
8848
8849 struct addrinfo *local_res;
8850 struct addrinfo *remote_res;
8851
8852 int myport;
8853 int ret;
8854
8855 struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
8856 struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
8857 struct tcp_conn_rr_results_struct *tcp_conn_rr_result;
8858
8859 tcp_conn_rr_request =
8860 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
8861 tcp_conn_rr_response =
8862 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
8863 tcp_conn_rr_result =
8864 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
8865
8866
8867 #ifdef WANT_HISTOGRAM
8868 if (verbosity > 1) {
8869 time_hist = HIST_new();
8870 }
8871 #endif /* WANT_HISTOGRAM */
8872
8873 /* since we are now disconnected from the code that established the */
8874 /* control socket, and since we want to be able to use different */
8875 /* protocols and such, we are passed the name of the remote host and */
8876 /* must turn that into the test specific addressing information. */
8877
8878 complete_addrinfos(&remote_res,
8879 &local_res,
8880 remote_host,
8881 SOCK_STREAM,
8882 IPPROTO_TCP,
8883 0);
8884
8885 if ( print_headers ) {
8886 print_top_test_header("TCP Connect/Request/Response TEST",local_res,remote_res);
8887 }
8888
8889 /* initialize a few counters */
8890
8891 nummessages = 0;
8892 bytes_xferd = 0.0;
8893 times_up = 0;
8894
8895 /* set-up the data buffers with the requested alignment and offset */
8896 if (send_width == 0) send_width = 1;
8897 if (recv_width == 0) recv_width = 1;
8898
8899 send_ring = allocate_buffer_ring(send_width,
8900 req_size,
8901 local_send_align,
8902 local_send_offset);
8903
8904 recv_ring = allocate_buffer_ring(recv_width,
8905 rsp_size,
8906 local_recv_align,
8907 local_recv_offset);
8908
8909
8910 if (debug) {
8911 fprintf(where,"send_tcp_conn_rr: send_socket obtained...\n");
8912 }
8913
8914 /* If the user has requested cpu utilization measurements, we must */
8915 /* calibrate the cpu(s). We will perform this task within the tests */
8916 /* themselves. If the user has specified the cpu rate, then */
8917 /* calibrate_local_cpu will return rather quickly as it will have */
8918 /* nothing to do. If local_cpu_rate is zero, then we will go through */
8919 /* all the "normal" calibration stuff and return the rate back.*/
8920
8921 if (local_cpu_usage) {
8922 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
8923 }
8924
8925 if (!no_control) {
8926
8927 /* Tell the remote end to do a listen. The server alters the
8928 socket paramters on the other side at this point, hence the
8929 reason for all the values being passed in the setup message. If
8930 the user did not specify any of the parameters, they will be
8931 passed as 0, which will indicate to the remote that no changes
8932 beyond the system's default should be used. Alignment is the
8933 exception, it will default to 8, which will be no alignment
8934 alterations. */
8935
8936 netperf_request.content.request_type = DO_TCP_CRR;
8937 tcp_conn_rr_request->recv_buf_size = rsr_size_req;
8938 tcp_conn_rr_request->send_buf_size = rss_size_req;
8939 tcp_conn_rr_request->recv_alignment = remote_recv_align;
8940 tcp_conn_rr_request->recv_offset = remote_recv_offset;
8941 tcp_conn_rr_request->send_alignment = remote_send_align;
8942 tcp_conn_rr_request->send_offset = remote_send_offset;
8943 tcp_conn_rr_request->request_size = req_size;
8944 tcp_conn_rr_request->response_size = rsp_size;
8945 tcp_conn_rr_request->no_delay = rem_nodelay;
8946 tcp_conn_rr_request->measure_cpu = remote_cpu_usage;
8947 tcp_conn_rr_request->cpu_rate = remote_cpu_rate;
8948 tcp_conn_rr_request->so_rcvavoid = rem_rcvavoid;
8949 tcp_conn_rr_request->so_sndavoid = rem_sndavoid;
8950 if (test_time) {
8951 tcp_conn_rr_request->test_length = test_time;
8952 }
8953 else {
8954 tcp_conn_rr_request->test_length = test_trans * -1;
8955 }
8956 tcp_conn_rr_request->port = atoi(remote_data_port);
8957 tcp_conn_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
8958
8959 if (debug > 1) {
8960 fprintf(where,"netperf: send_tcp_conn_rr: requesting TCP crr test\n");
8961 }
8962
8963 send_request();
8964
8965 /* The response from the remote will contain all of the relevant
8966 socket parameters for this test type. We will put them back
8967 into the variables here so they can be displayed if desired.
8968 The remote will have calibrated CPU if necessary, and will have
8969 done all the needed set-up we will have calibrated the cpu
8970 locally before sending the request, and will grab the counter
8971 value right after the connect returns. The remote will grab the
8972 counter right after the accept call. This saves the hassle of
8973 extra messages being sent for the TCP tests. */
8974
8975 recv_response();
8976
8977 if (!netperf_response.content.serv_errno) {
8978 rsr_size = tcp_conn_rr_response->recv_buf_size;
8979 rss_size = tcp_conn_rr_response->send_buf_size;
8980 rem_nodelay = tcp_conn_rr_response->no_delay;
8981 remote_cpu_usage = tcp_conn_rr_response->measure_cpu;
8982 remote_cpu_rate = tcp_conn_rr_response->cpu_rate;
8983 /* make sure that port numbers are in network order */
8984 set_port_number(remote_res,
8985 (unsigned short)tcp_conn_rr_response->data_port_number);
8986
8987 if (debug) {
8988 fprintf(where,"remote listen done.\n");
8989 fprintf(where,"remote port is %u\n",get_port_number(remote_res));
8990 fflush(where);
8991 }
8992 }
8993 else {
8994 Set_errno(netperf_response.content.serv_errno);
8995 fprintf(where,
8996 "netperf: remote error %d",
8997 netperf_response.content.serv_errno);
8998 perror("");
8999 fflush(where);
9000 exit(1);
9001 }
9002 }
9003 #ifdef WANT_DEMO
9004 demo_rr_setup(100);
9005 #endif
9006
9007 /* pick a nice random spot between client_port_min and */
9008 /* client_port_max for our initial port number */
9009 srand(getpid());
9010 if (client_port_max - client_port_min) {
9011 myport = client_port_min +
9012 (rand() % (client_port_max - client_port_min));
9013 }
9014 else {
9015 myport = client_port_min;
9016 }
9017 /* there will be a ++ before the first call to bind, so subtract one */
9018 myport--;
9019 /* Set-up the test end conditions. For a request/response test, they */
9020 /* can be either time or transaction based. */
9021
9022 if (test_time) {
9023 /* The user wanted to end the test after a period of time. */
9024 times_up = 0;
9025 trans_remaining = 0;
9026 start_timer(test_time);
9027 }
9028 else {
9029 /* The tester wanted to send a number of bytes. */
9030 trans_remaining = test_bytes;
9031 times_up = 1;
9032 }
9033
9034 /* The cpu_start routine will grab the current time and possibly */
9035 /* value of the idle counter for later use in measuring cpu */
9036 /* utilization and/or service demand and thruput. */
9037
9038
9039 cpu_start(local_cpu_usage);
9040
9041 #ifdef WANT_DEMO
9042 if (demo_mode) {
9043 demo_first_timestamp();
9044 }
9045 #endif
9046
9047 /* We use an "OR" to control test execution. When the test is */
9048 /* controlled by time, the byte count check will always return false. */
9049 /* When the test is controlled by byte count, the time test will */
9050 /* always return false. When the test is finished, the whole */
9051 /* expression will go false and we will stop sending data. I think I */
9052 /* just arbitrarily decrement trans_remaining for the timed test, but */
9053 /* will not do that just yet... One other question is whether or not */
9054 /* the send buffer and the receive buffer should be the same buffer. */
9055
9056 while ((!times_up) || (trans_remaining > 0)) {
9057
9058 #ifdef WANT_HISTOGRAM
9059 if (verbosity > 1) {
9060 /* timestamp just before our call to create the socket, and then */
9061 /* again just after the receive raj 3/95 */
9062 HIST_timestamp(&time_one);
9063 }
9064 #endif /* WANT_HISTOGRAM */
9065
9066 newport:
9067 /* pick a new port number */
9068 myport++;
9069
9070 /* wrap the port number when we get to client_port_max. NOTE, some */
9071 /* broken TCP's might treat the port number as a signed 16 bit */
9072 /* quantity. we aren't interested in testing such broken */
9073 /* implementations :) so we won't make sure that it is below 32767 */
9074 /* raj 8/94 */
9075 if (myport >= client_port_max) {
9076 myport = client_port_min;
9077 }
9078
9079 /* we do not want to use the port number that the server is */
9080 /* sitting at - this would cause us to fail in a loopback test. we */
9081 /* could just rely on the failure of the bind to get us past this, */
9082 /* but I'm guessing that in this one case at least, it is much */
9083 /* faster, given that we *know* that port number is already in use */
9084 /* (or rather would be in a loopback test) */
9085
9086 if (myport == get_port_number(remote_res)) myport++;
9087
9088 if (debug) {
9089 if ((nummessages % 100) == 0) {
9090 printf("port %d\n",myport);
9091 }
9092 }
9093
9094 /* set up the data socket */
9095 set_port_number(local_res, (unsigned short)myport);
9096 send_socket = create_data_socket(local_res);
9097
9098 if (send_socket == INVALID_SOCKET) {
9099 perror("netperf: send_tcp_conn_rr: tcp stream data socket");
9100 exit(1);
9101 }
9102
9103
9104 /* we used to call bind here, but that is now taken-care-of by the
9105 create_data_socket routine. */
9106
9107 /* Connect up to the remote port on the data socket */
9108 if ((ret = connect(send_socket,
9109 remote_res->ai_addr,
9110 remote_res->ai_addrlen)) == INVALID_SOCKET){
9111 if (SOCKET_EINTR(ret))
9112 {
9113 /* we hit the end of a */
9114 /* timed test. */
9115 timed_out = 1;
9116 break;
9117 }
9118 if ((SOCKET_EADDRINUSE(ret)) || SOCKET_EADDRNOTAVAIL(ret)) {
9119 /* likely something our explicit bind() would have caught in
9120 the past, so go get another port, via create_data_socket.
9121 yes, this is a bit more overhead than before, but the
9122 condition should be rather rare. raj 2005-02-08 */
9123 close(send_socket);
9124 goto newport;
9125 }
9126 perror("netperf: data socket connect failed");
9127 printf("\tattempted to connect on socket %d to port %d",
9128 send_socket,
9129 get_port_number(remote_res));
9130 printf(" from port %d \n",get_port_number(local_res));
9131 exit(1);
9132 }
9133
9134
9135 /* send the request */
9136 if((len=send(send_socket,
9137 send_ring->buffer_ptr,
9138 req_size,
9139 0)) != req_size) {
9140 if (SOCKET_EINTR(len))
9141 {
9142 /* we hit the end of a */
9143 /* timed test. */
9144 timed_out = 1;
9145 break;
9146 }
9147 perror("send_tcp_conn_rr: data send error");
9148 exit(1);
9149 }
9150 send_ring = send_ring->next;
9151
9152 /* receive the response */
9153 rsp_bytes_left = rsp_size;
9154 temp_message_ptr = recv_ring->buffer_ptr;
9155
9156
9157 do {
9158 rsp_bytes_recvd = recv(send_socket,
9159 temp_message_ptr,
9160 rsp_bytes_left,
9161 0);
9162 if (rsp_bytes_recvd > 0) {
9163 rsp_bytes_left -= rsp_bytes_recvd;
9164 temp_message_ptr += rsp_bytes_recvd;
9165 }
9166 else {
9167 break;
9168 }
9169 } while (rsp_bytes_left);
9170
9171
9172 /* OK, we are out of the loop - now what? */
9173 if (rsp_bytes_recvd < 0) {
9174 /* did the timer hit, or was there an error? */
9175 if (SOCKET_EINTR(rsp_bytes_recvd))
9176 {
9177 /* We hit the end of a timed test. */
9178 timed_out = 1;
9179 break;
9180 }
9181 perror("send_tcp_conn_rr: data recv error");
9182 exit(1);
9183 }
9184
9185 /* if this is a no_control test, we initiate connection close,
9186 otherwise the remote netserver does it to remain just like
9187 previous behaviour. raj 2007-27-08 */
9188 if (!no_control) {
9189 shutdown(send_socket,SHUT_WR);
9190 }
9191
9192 /* we are expecting to get either a return of zero indicating
9193 connection close, or an error. */
9194 rsp_bytes_recvd = recv(send_socket,
9195 temp_message_ptr,
9196 1,
9197 0);
9198
9199 /* our exit from the while loop should generally be when */
9200 /* tmp_bytes_recvd is equal to zero, which implies the connection */
9201 /* has been closed by the server side. By waiting until we get the */
9202 /* zero return we can avoid race conditions that stick us with the */
9203 /* TIME_WAIT connection and not the server. raj 8/96 */
9204
9205 #ifdef VMWARE_UW
9206 /* why this should be for VMware I'm not sure, but it was given as
9207 part of the patches, so we include it here, but put it under an
9208 ifdef VMWARE_UW. raj 2008-07-25 */
9209 if (sp_bytes_recvd < 0 && errno == ECONNRESET) {
9210 rsp_bytes_recvd = 0;
9211 }
9212 #endif /* VMWARE_UW */
9213
9214 if (rsp_bytes_recvd == 0) {
9215 /* connection close, call close. we assume that the requisite */
9216 /* number of bytes have been received */
9217 recv_ring = recv_ring->next;
9218
9219 #ifdef WANT_HISTOGRAM
9220 if (verbosity > 1) {
9221 HIST_timestamp(&time_two);
9222 HIST_add(time_hist,delta_micro(&time_one,&time_two));
9223 }
9224 #endif /* WANT_HISTOGRAM */
9225
9226 #ifdef WANT_DEMO
9227 demo_rr_interval(1);
9228 #endif
9229
9230 nummessages++;
9231 if (trans_remaining) {
9232 trans_remaining--;
9233 }
9234
9235 if (debug > 3) {
9236 fprintf(where,
9237 "Transaction %d completed on local port %d\n",
9238 nummessages,
9239 get_port_number(local_res));
9240 fflush(where);
9241 }
9242
9243 close(send_socket);
9244
9245 }
9246 else {
9247 /* it was less than zero - an error occured */
9248 if (SOCKET_EINTR(rsp_bytes_recvd))
9249 {
9250 /* We hit the end of a timed test. */
9251 timed_out = 1;
9252 break;
9253 }
9254 perror("send_tcp_conn_rr: data recv error");
9255 exit(1);
9256 }
9257
9258 }
9259
9260
9261 /* this call will always give us the elapsed time for the test, and */
9262 /* will also store-away the necessaries for cpu utilization */
9263
9264 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
9265 /* how long did we really run? */
9266
9267 if (!no_control) {
9268 /* Get the statistics from the remote end. The remote will have
9269 calculated service demand and all those interesting things. If
9270 it wasn't supposed to care, it will return obvious values. */
9271
9272 recv_response();
9273 if (!netperf_response.content.serv_errno) {
9274 if (debug)
9275 fprintf(where,"remote results obtained\n");
9276 }
9277 else {
9278 Set_errno(netperf_response.content.serv_errno);
9279 fprintf(where,
9280 "netperf: remote error %d",
9281 netperf_response.content.serv_errno);
9282 perror("");
9283 fflush(where);
9284
9285 exit(1);
9286 }
9287 }
9288
9289 /* We now calculate what our thruput was for the test. In the future, */
9290 /* we may want to include a calculation of the thruput measured by */
9291 /* the remote, but it should be the case that for a TCP stream test, */
9292 /* that the two numbers should be *very* close... We calculate */
9293 /* bytes_sent regardless of the way the test length was controlled. */
9294 /* If it was time, we needed to, and if it was by bytes, the user may */
9295 /* have specified a number of bytes that wasn't a multiple of the */
9296 /* send_size, so we really didn't send what he asked for ;-) We use */
9297 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
9298 /* 1024. A future enhancement *might* be to choose from a couple of */
9299 /* unit selections. */
9300
9301 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
9302 thruput = calc_thruput(bytes_xferd);
9303
9304 if (local_cpu_usage || remote_cpu_usage) {
9305 /* We must now do a little math for service demand and cpu */
9306 /* utilization for the system(s) */
9307 /* Of course, some of the information might be bogus because */
9308 /* there was no idle counter in the kernel(s). We need to make */
9309 /* a note of this for the user's benefit...*/
9310 if (local_cpu_usage) {
9311 if (local_cpu_rate == 0.0) {
9312 fprintf(where,
9313 "WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
9314 fprintf(where,
9315 "Local CPU usage numbers based on process information only!\n");
9316 fflush(where);
9317 }
9318 local_cpu_utilization = calc_cpu_util(0.0);
9319 /* since calc_service demand is doing ms/Kunit we will */
9320 /* multiply the number of transaction by 1024 to get */
9321 /* "good" numbers */
9322 local_service_demand = calc_service_demand((double) nummessages*1024,
9323 0.0,
9324 0.0,
9325 0);
9326 }
9327 else {
9328 local_cpu_utilization = (float) -1.0;
9329 local_service_demand = (float) -1.0;
9330 }
9331
9332 if (remote_cpu_usage) {
9333 if (remote_cpu_rate == 0.0) {
9334 fprintf(where,
9335 "DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
9336 fprintf(where,
9337 "Remote CPU usage numbers based on process information only!\n");
9338 fflush(where);
9339 }
9340 remote_cpu_utilization = tcp_conn_rr_result->cpu_util;
9341 /* since calc_service demand is doing ms/Kunit we will */
9342 /* multiply the number of transaction by 1024 to get */
9343 /* "good" numbers */
9344 remote_service_demand = calc_service_demand((double) nummessages*1024,
9345 0.0,
9346 remote_cpu_utilization,
9347 tcp_conn_rr_result->num_cpus);
9348 }
9349 else {
9350 remote_cpu_utilization = (float) -1.0;
9351 remote_service_demand = (float) -1.0;
9352 }
9353
9354 /* We are now ready to print all the information. If the user */
9355 /* has specified zero-level verbosity, we will just print the */
9356 /* local service demand, or the remote service demand. If the */
9357 /* user has requested verbosity level 1, he will get the basic */
9358 /* "streamperf" numbers. If the user has specified a verbosity */
9359 /* of greater than 1, we will display a veritable plethora of */
9360 /* background information from outside of this block as it it */
9361 /* not cpu_measurement specific... */
9362
9363 switch (verbosity) {
9364 case 0:
9365 if (local_cpu_usage) {
9366 fprintf(where,
9367 cpu_fmt_0,
9368 local_service_demand);
9369 }
9370 else {
9371 fprintf(where,
9372 cpu_fmt_0,
9373 remote_service_demand);
9374 }
9375 break;
9376 case 1:
9377 case 2:
9378
9379 if (print_headers) {
9380 fprintf(where,
9381 cpu_title,
9382 local_cpu_method,
9383 remote_cpu_method);
9384 }
9385
9386 fprintf(where,
9387 cpu_fmt_1_line_1, /* the format string */
9388 lss_size, /* local sendbuf size */
9389 lsr_size,
9390 req_size, /* how large were the requests */
9391 rsp_size, /* guess */
9392 elapsed_time, /* how long was the test */
9393 nummessages/elapsed_time,
9394 local_cpu_utilization, /* local cpu */
9395 remote_cpu_utilization, /* remote cpu */
9396 local_service_demand, /* local service demand */
9397 remote_service_demand); /* remote service demand */
9398 fprintf(where,
9399 cpu_fmt_1_line_2,
9400 rss_size,
9401 rsr_size);
9402 break;
9403 }
9404 }
9405 else {
9406 /* The tester did not wish to measure service demand. */
9407 switch (verbosity) {
9408 case 0:
9409 fprintf(where,
9410 tput_fmt_0,
9411 nummessages/elapsed_time);
9412 break;
9413 case 1:
9414 case 2:
9415 if (print_headers) {
9416 fprintf(where,tput_title,format_units());
9417 }
9418
9419 fprintf(where,
9420 tput_fmt_1_line_1, /* the format string */
9421 lss_size,
9422 lsr_size,
9423 req_size, /* how large were the requests */
9424 rsp_size, /* how large were the responses */
9425 elapsed_time, /* how long did it take */
9426 nummessages/elapsed_time);
9427 fprintf(where,
9428 tput_fmt_1_line_2,
9429 rss_size, /* remote recvbuf size */
9430 rsr_size);
9431
9432 break;
9433 }
9434 }
9435
9436 /* it would be a good thing to include information about some of the */
9437 /* other parameters that may have been set for this test, but at the */
9438 /* moment, I do not wish to figure-out all the formatting, so I will */
9439 /* just put this comment here to help remind me that it is something */
9440 /* that should be done at a later time. */
9441
9442 if (verbosity > 1) {
9443 /* The user wanted to know it all, so we will give it to him. */
9444 /* This information will include as much as we can find about */
9445 /* TCP statistics, the alignments of the sends and receives */
9446 /* and all that sort of rot... */
9447
9448 fprintf(where,
9449 ksink_fmt,
9450 local_send_align,
9451 remote_recv_offset,
9452 local_send_offset,
9453 remote_recv_offset);
9454
9455 #ifdef WANT_HISTOGRAM
9456 fprintf(where,"\nHistogram of request/response times\n");
9457 fflush(where);
9458 HIST_report(time_hist);
9459 #endif /* WANT_HISTOGRAM */
9460
9461 }
9462
9463 }
9464 #endif /* WANT_MIGRATION */
9465
9466 void
recv_tcp_conn_rr()9467 recv_tcp_conn_rr()
9468 {
9469
9470 char *message;
9471 struct addrinfo *local_res;
9472 char local_name[BUFSIZ];
9473 char port_buffer[PORTBUFSIZE];
9474
9475 struct sockaddr_storage myaddr_in, peeraddr_in;
9476 SOCKET s_listen,s_data;
9477 netperf_socklen_t addrlen;
9478 char *recv_message_ptr;
9479 char *send_message_ptr;
9480 char *temp_message_ptr;
9481 int trans_received;
9482 int trans_remaining;
9483 int bytes_sent;
9484 int request_bytes_recvd;
9485 int request_bytes_remaining;
9486 int timed_out = 0;
9487 float elapsed_time;
9488
9489 struct tcp_conn_rr_request_struct *tcp_conn_rr_request;
9490 struct tcp_conn_rr_response_struct *tcp_conn_rr_response;
9491 struct tcp_conn_rr_results_struct *tcp_conn_rr_results;
9492
9493 tcp_conn_rr_request =
9494 (struct tcp_conn_rr_request_struct *)netperf_request.content.test_specific_data;
9495 tcp_conn_rr_response =
9496 (struct tcp_conn_rr_response_struct *)netperf_response.content.test_specific_data;
9497 tcp_conn_rr_results =
9498 (struct tcp_conn_rr_results_struct *)netperf_response.content.test_specific_data;
9499
9500 if (debug) {
9501 fprintf(where,"netserver: recv_tcp_conn_rr: entered...\n");
9502 fflush(where);
9503 }
9504
9505 /* We want to set-up the listen socket with all the desired */
9506 /* parameters and then let the initiator know that all is ready. If */
9507 /* socket size defaults are to be used, then the initiator will have */
9508 /* sent us 0's. If the socket sizes cannot be changed, then we will */
9509 /* send-back what they are. If that information cannot be determined, */
9510 /* then we send-back -1's for the sizes. If things go wrong for any */
9511 /* reason, we will drop back ten yards and punt. */
9512
9513 /* If anything goes wrong, we want the remote to know about it. It */
9514 /* would be best if the error that the remote reports to the user is */
9515 /* the actual error we encountered, rather than some bogus unexpected */
9516 /* response type message. */
9517
9518 if (debug) {
9519 fprintf(where,"recv_tcp_conn_rr: setting the response type...\n");
9520 fflush(where);
9521 }
9522
9523 netperf_response.content.response_type = TCP_CRR_RESPONSE;
9524
9525 if (debug) {
9526 fprintf(where,"recv_tcp_conn_rr: the response type is set...\n");
9527 fflush(where);
9528 }
9529
9530 /* set-up the data buffer with the requested alignment and offset */
9531 message = (char *)malloc(DATABUFFERLEN);
9532 if (message == NULL) {
9533 printf("malloc(%d) failed!\n", DATABUFFERLEN);
9534 exit(1);
9535 }
9536
9537 /* We now alter the message_ptr variables to be at the desired */
9538 /* alignments with the desired offsets. */
9539
9540 if (debug) {
9541 fprintf(where,
9542 "recv_tcp_conn_rr: requested recv alignment of %d offset %d\n",
9543 tcp_conn_rr_request->recv_alignment,
9544 tcp_conn_rr_request->recv_offset);
9545 fprintf(where,
9546 "recv_tcp_conn_rr: requested send alignment of %d offset %d\n",
9547 tcp_conn_rr_request->send_alignment,
9548 tcp_conn_rr_request->send_offset);
9549 fflush(where);
9550 }
9551
9552 recv_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->recv_alignment, tcp_conn_rr_request->recv_offset);
9553
9554 send_message_ptr = ALIGN_BUFFER(message, tcp_conn_rr_request->send_alignment, tcp_conn_rr_request->send_offset);
9555
9556 if (debug) {
9557 fprintf(where,"recv_tcp_conn_rr: receive alignment and offset set...\n");
9558 fflush(where);
9559 }
9560
9561 /* Grab a socket to listen on, and then listen on it. */
9562
9563 if (debug) {
9564 fprintf(where,"recv_tcp_conn_rr: grabbing a socket...\n");
9565 fflush(where);
9566 }
9567
9568 /* create_data_socket expects to find some things in the global */
9569 /* variables, so set the globals based on the values in the request. */
9570 /* once the socket has been created, we will set the response values */
9571 /* based on the updated value of those globals. raj 7/94 */
9572 lss_size_req = tcp_conn_rr_request->send_buf_size;
9573 lsr_size_req = tcp_conn_rr_request->recv_buf_size;
9574 loc_nodelay = tcp_conn_rr_request->no_delay;
9575 loc_rcvavoid = tcp_conn_rr_request->so_rcvavoid;
9576 loc_sndavoid = tcp_conn_rr_request->so_sndavoid;
9577
9578 set_hostname_and_port(local_name,
9579 port_buffer,
9580 nf_to_af(tcp_conn_rr_request->ipfamily),
9581 tcp_conn_rr_request->port);
9582
9583 local_res = complete_addrinfo(local_name,
9584 local_name,
9585 port_buffer,
9586 nf_to_af(tcp_conn_rr_request->ipfamily),
9587 SOCK_STREAM,
9588 IPPROTO_TCP,
9589 0);
9590
9591 s_listen = create_data_socket(local_res);
9592
9593 if (s_listen == INVALID_SOCKET) {
9594 netperf_response.content.serv_errno = errno;
9595 send_response();
9596 if (debug) {
9597 fprintf(where,"could not create data socket\n");
9598 fflush(where);
9599 }
9600 exit(1);
9601 }
9602
9603 #ifdef WIN32
9604 /* The test timer can fire during operations on the listening socket,
9605 so to make the start_timer below work we have to move
9606 it to close s_listen while we are blocked on accept. */
9607 win_kludge_socket2 = s_listen;
9608 #endif
9609
9610
9611 /* Now, let's set-up the socket to listen for connections */
9612 if (listen(s_listen, 128) == SOCKET_ERROR) {
9613 netperf_response.content.serv_errno = errno;
9614 close(s_listen);
9615 send_response();
9616 if (debug) {
9617 fprintf(where,"could not listen\n");
9618 fflush(where);
9619 }
9620 exit(1);
9621 }
9622
9623 /* now get the port number assigned by the system */
9624 addrlen = sizeof(myaddr_in);
9625 if (getsockname(s_listen,
9626 (struct sockaddr *)&myaddr_in,
9627 &addrlen) == SOCKET_ERROR){
9628 netperf_response.content.serv_errno = errno;
9629 close(s_listen);
9630 send_response();
9631 if (debug) {
9632 fprintf(where,"could not getsockname\n");
9633 fflush(where);
9634 }
9635 exit(1);
9636 }
9637
9638 /* Now myaddr_in contains the port and the internet address this is */
9639 /* returned to the sender also implicitly telling the sender that the */
9640 /* socket buffer sizing has been done. */
9641
9642 tcp_conn_rr_response->data_port_number =
9643 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
9644 if (debug) {
9645 fprintf(where,"telling the remote to call me at %d\n",
9646 tcp_conn_rr_response->data_port_number);
9647 fflush(where);
9648 }
9649 netperf_response.content.serv_errno = 0;
9650
9651 /* But wait, there's more. If the initiator wanted cpu measurements, */
9652 /* then we must call the calibrate routine, which will return the max */
9653 /* rate back to the initiator. If the CPU was not to be measured, or */
9654 /* something went wrong with the calibration, we will return a 0.0 to */
9655 /* the initiator. */
9656
9657 tcp_conn_rr_response->cpu_rate = (float)0.0; /* assume no cpu */
9658 if (tcp_conn_rr_request->measure_cpu) {
9659 tcp_conn_rr_response->measure_cpu = 1;
9660 tcp_conn_rr_response->cpu_rate =
9661 calibrate_local_cpu(tcp_conn_rr_request->cpu_rate);
9662 }
9663
9664
9665
9666 /* before we send the response back to the initiator, pull some of */
9667 /* the socket parms from the globals */
9668 tcp_conn_rr_response->send_buf_size = lss_size;
9669 tcp_conn_rr_response->recv_buf_size = lsr_size;
9670 tcp_conn_rr_response->no_delay = loc_nodelay;
9671 tcp_conn_rr_response->so_rcvavoid = loc_rcvavoid;
9672 tcp_conn_rr_response->so_sndavoid = loc_sndavoid;
9673
9674 send_response();
9675
9676 addrlen = sizeof(peeraddr_in);
9677
9678 /* Now it's time to start receiving data on the connection. We will */
9679 /* first grab the apropriate counters and then start grabbing. */
9680
9681 cpu_start(tcp_conn_rr_request->measure_cpu);
9682
9683 /* The loop will exit when the sender does a shutdown, which will */
9684 /* return a length of zero */
9685
9686 if (tcp_conn_rr_request->test_length > 0) {
9687 times_up = 0;
9688 trans_remaining = 0;
9689 start_timer(tcp_conn_rr_request->test_length + PAD_TIME);
9690 }
9691 else {
9692 times_up = 1;
9693 trans_remaining = tcp_conn_rr_request->test_length * -1;
9694 }
9695
9696 trans_received = 0;
9697
9698 while ((!times_up) || (trans_remaining > 0)) {
9699
9700 /* accept a connection from the remote */
9701 #ifdef WIN32
9702 /* The test timer will probably fire during this accept,
9703 so to make the start_timer above work we have to move
9704 it to close s_listen while we are blocked on accept. */
9705 win_kludge_socket = s_listen;
9706 #endif
9707 if ((s_data=accept(s_listen,
9708 (struct sockaddr *)&peeraddr_in,
9709 &addrlen)) == INVALID_SOCKET) {
9710 if (errno == EINTR) {
9711 /* the timer popped */
9712 timed_out = 1;
9713 break;
9714 }
9715 fprintf(where,"recv_tcp_conn_rr: accept: errno = %d\n",errno);
9716 fflush(where);
9717 close(s_listen);
9718
9719 exit(1);
9720 }
9721
9722 if (debug) {
9723 fprintf(where,"recv_tcp_conn_rr: accepted data connection.\n");
9724 fflush(where);
9725 }
9726
9727 #ifdef WIN32
9728 /* this is used so the timer thread can close the socket out from */
9729 /* under us, which to date is the easiest/cleanest/least */
9730 /* Windows-specific way I can find to force the winsock calls to */
9731 /* return WSAEINTR with the test is over. anything that will run on */
9732 /* 95 and NT and is closer to what netperf expects from Unix signals */
9733 /* and such would be appreciated raj 1/96 */
9734 win_kludge_socket = s_data;
9735 #endif /* WIN32 */
9736
9737 #ifdef KLUDGE_SOCKET_OPTIONS
9738 /* this is for those systems which *INCORRECTLY* fail to pass */
9739 /* attributes across an accept() call. Including this goes against */
9740 /* my better judgement :( raj 11/95 */
9741
9742 kludge_socket_options(s_data);
9743
9744 #endif /* KLUDGE_SOCKET_OPTIONS */
9745
9746 temp_message_ptr = recv_message_ptr;
9747 request_bytes_remaining = tcp_conn_rr_request->request_size;
9748
9749 /* receive the request from the other side */
9750 while (!times_up && (request_bytes_remaining > 0)) {
9751 if((request_bytes_recvd=recv(s_data,
9752 temp_message_ptr,
9753 request_bytes_remaining,
9754 0)) == SOCKET_ERROR) {
9755 if (SOCKET_EINTR(request_bytes_recvd))
9756 {
9757 /* the timer popped */
9758 timed_out = 1;
9759 break;
9760 }
9761 netperf_response.content.serv_errno = errno;
9762 send_response();
9763 exit(1);
9764 }
9765 else if (request_bytes_recvd > 0) {
9766 request_bytes_remaining -= request_bytes_recvd;
9767 temp_message_ptr += request_bytes_recvd;
9768 }
9769 else {
9770 /* for some reason the remote closed the connection on
9771 * us and that is unexpected so we should just close the
9772 * socket and move-on. for that we will use an evil goto
9773 * neener neener raj 20090622 */
9774 goto bail;
9775 }
9776 }
9777
9778 if (timed_out) {
9779 /* we hit the end of the test based on time - lets */
9780 /* bail out of here now... */
9781 fprintf(where,"yo5\n");
9782 fflush(where);
9783 break;
9784 }
9785
9786 /* Now, send the response to the remote */
9787 if((bytes_sent=send(s_data,
9788 send_message_ptr,
9789 tcp_conn_rr_request->response_size,
9790 0)) == SOCKET_ERROR) {
9791 if (errno == EINTR) {
9792 /* the test timer has popped */
9793 timed_out = 1;
9794 fprintf(where,"yo6\n");
9795 fflush(where);
9796 break;
9797 }
9798 netperf_response.content.serv_errno = 99;
9799 send_response();
9800 exit(1);
9801 }
9802
9803 trans_received++;
9804 if (trans_remaining) {
9805 trans_remaining--;
9806 }
9807
9808 if (debug) {
9809 fprintf(where,
9810 "recv_tcp_conn_rr: Transaction %d complete\n",
9811 trans_received);
9812 fflush(where);
9813 }
9814
9815 /* close the connection. the server will likely do a graceful */
9816 /* close of the connection, insuring that all data has arrived at */
9817 /* the client. for this it will call shutdown(), and then recv() and */
9818 /* then close(). I'm reasonably confident that this is the */
9819 /* appropriate sequence of calls - I would like to hear of */
9820 /* examples in web servers to the contrary. raj 10/95*/
9821 #ifdef TCP_CRR_SHUTDOWN
9822 shutdown(s_data,SHUT_WR);
9823 recv(s_data,
9824 recv_message_ptr,
9825 1,
9826 0);
9827 bail:
9828 close(s_data);
9829 #else
9830 bail:
9831 close(s_data);
9832 #endif /* TCP_CRR_SHUTDOWN */
9833
9834 }
9835
9836
9837 /* The loop now exits due to timeout or transaction count being */
9838 /* reached */
9839
9840 cpu_stop(tcp_conn_rr_request->measure_cpu,&elapsed_time);
9841
9842 if (timed_out) {
9843 /* we ended the test by time, which was at least 2 seconds */
9844 /* longer than we wanted to run. so, we want to subtract */
9845 /* PAD_TIME from the elapsed_time. */
9846 elapsed_time -= PAD_TIME;
9847 }
9848 /* send the results to the sender */
9849
9850 if (debug) {
9851 fprintf(where,
9852 "recv_tcp_conn_rr: got %d transactions\n",
9853 trans_received);
9854 fflush(where);
9855 }
9856
9857 tcp_conn_rr_results->bytes_received = (trans_received *
9858 (tcp_conn_rr_request->request_size +
9859 tcp_conn_rr_request->response_size));
9860 tcp_conn_rr_results->trans_received = trans_received;
9861 tcp_conn_rr_results->elapsed_time = elapsed_time;
9862 if (tcp_conn_rr_request->measure_cpu) {
9863 tcp_conn_rr_results->cpu_util = calc_cpu_util(elapsed_time);
9864 }
9865
9866 if (debug) {
9867 fprintf(where,
9868 "recv_tcp_conn_rr: test complete, sending results.\n");
9869 fflush(where);
9870 }
9871
9872 send_response();
9873
9874 }
9875
9876
9877 #ifdef DO_1644
9878
9879 /* this test is intended to test the performance of establishing a */
9880 /* connection, exchanging a request/response pair, and repeating. it */
9881 /* is expected that this would be a good starting-point for */
9882 /* comparision of T/TCP with classic TCP for transactional workloads. */
9883 /* it will also look (can look) much like the communication pattern */
9884 /* of http for www access. */
9885
9886 int
send_tcp_tran_rr(char remote_host[])9887 send_tcp_tran_rr(char remote_host[])
9888 {
9889
9890 char *tput_title = "\
9891 Local /Remote\n\
9892 Socket Size Request Resp. Elapsed Trans.\n\
9893 Send Recv Size Size Time Rate \n\
9894 bytes Bytes bytes bytes secs. per sec \n\n";
9895
9896 char *tput_fmt_0 =
9897 "%7.2f\n";
9898
9899 char *tput_fmt_1_line_1 = "\
9900 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
9901 char *tput_fmt_1_line_2 = "\
9902 %-6d %-6d\n";
9903
9904 char *cpu_title = "\
9905 Local /Remote\n\
9906 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
9907 Send Recv Size Size Time Rate local remote local remote\n\
9908 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
9909
9910 char *cpu_fmt_0 =
9911 "%6.3f\n";
9912
9913 char *cpu_fmt_1_line_1 = "\
9914 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
9915
9916 char *cpu_fmt_1_line_2 = "\
9917 %-6d %-6d\n";
9918
9919 char *ksink_fmt = "\n\
9920 Alignment Offset\n\
9921 Local Remote Local Remote\n\
9922 Send Recv Send Recv\n\
9923 %5d %5d %5d %5d\n";
9924
9925
9926 int one = 1;
9927 int timed_out = 0;
9928 float elapsed_time;
9929
9930 int len;
9931 struct ring_elt *send_ring;
9932 struct ring_elt *recv_ring;
9933 char *temp_message_ptr;
9934 int nummessages;
9935 SOCKET send_socket;
9936 int trans_remaining;
9937 double bytes_xferd;
9938 int sock_opt_len = sizeof(int);
9939 int rsp_bytes_left;
9940 int rsp_bytes_recvd;
9941
9942 float local_cpu_utilization;
9943 float local_service_demand;
9944 float remote_cpu_utilization;
9945 float remote_service_demand;
9946 double thruput;
9947
9948 struct hostent *hp;
9949 struct sockaddr_in server;
9950 struct sockaddr_in *myaddr;
9951 unsigned int addr;
9952 int myport;
9953
9954 struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
9955 struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
9956 struct tcp_tran_rr_results_struct *tcp_tran_rr_result;
9957
9958 tcp_tran_rr_request =
9959 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
9960 tcp_tran_rr_response =
9961 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
9962 tcp_tran_rr_result =
9963 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
9964
9965
9966 #ifdef WANT_HISTOGRAM
9967 if (verbosity > 1) {
9968 time_hist = HIST_new();
9969 }
9970 #endif /* WANT_HISTOGRAM */
9971
9972 /* since we are now disconnected from the code that established the */
9973 /* control socket, and since we want to be able to use different */
9974 /* protocols and such, we are passed the name of the remote host and */
9975 /* must turn that into the test specific addressing information. */
9976
9977 myaddr = (struct sockaddr_storage *)malloc(sizeof(struct sockaddr_storage));
9978 if (myaddr == NULL) {
9979 printf("malloc(%d) failed!\n", sizeof(struct sockaddr_storage));
9980 exit(1);
9981 }
9982
9983 bzero((char *)&server,
9984 sizeof(server));
9985 bzero((char *)myaddr,
9986 sizeof(struct sockaddr_storage));
9987 myaddr->sin_family = AF_INET;
9988
9989 complete_addrinfos(&remote_res,
9990 &local_res,
9991 remote_host,
9992 SOCK_STREAM,
9993 IPPROTO_TCP,
9994 0);
9995
9996 if ( print_headers ) {
9997 print_top_test_header("TCP Transactional/Request/Response TEST",local_res,remote_res);
9998 }
9999
10000 /* initialize a few counters */
10001
10002 nummessages = 0;
10003 bytes_xferd = 0.0;
10004 times_up = 0;
10005
10006 /* set-up the data buffers with the requested alignment and offset */
10007 if (send_width == 0) send_width = 1;
10008 if (recv_width == 0) recv_width = 1;
10009
10010 send_ring = allocate_buffer_ring(send_width,
10011 req_size,
10012 local_send_align,
10013 local_send_offset);
10014
10015 recv_ring = allocate_buffer_ring(recv_width,
10016 rsp_size,
10017 local_recv_align,
10018 local_recv_offset);
10019
10020
10021 if (debug) {
10022 fprintf(where,"send_tcp_tran_rr: send_socket obtained...\n");
10023 }
10024
10025 /* If the user has requested cpu utilization measurements, we must */
10026 /* calibrate the cpu(s). We will perform this task within the tests */
10027 /* themselves. If the user has specified the cpu rate, then */
10028 /* calibrate_local_cpu will return rather quickly as it will have */
10029 /* nothing to do. If local_cpu_rate is zero, then we will go through */
10030 /* all the "normal" calibration stuff and return the rate back.*/
10031
10032 if (local_cpu_usage) {
10033 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
10034 }
10035
10036 /* Tell the remote end to do a listen. The server alters the socket */
10037 /* paramters on the other side at this point, hence the reason for */
10038 /* all the values being passed in the setup message. If the user did */
10039 /* not specify any of the parameters, they will be passed as 0, which */
10040 /* will indicate to the remote that no changes beyond the system's */
10041 /* default should be used. Alignment is the exception, it will */
10042 /* default to 8, which will be no alignment alterations. */
10043
10044 netperf_request.content.request_type = DO_TCP_TRR;
10045 tcp_tran_rr_request->recv_buf_size = rsr_size_req;
10046 tcp_tran_rr_request->send_buf_size = rss_size_req;
10047 tcp_tran_rr_request->recv_alignment = remote_recv_align;
10048 tcp_tran_rr_request->recv_offset = remote_recv_offset;
10049 tcp_tran_rr_request->send_alignment = remote_send_align;
10050 tcp_tran_rr_request->send_offset = remote_send_offset;
10051 tcp_tran_rr_request->request_size = req_size;
10052 tcp_tran_rr_request->response_size = rsp_size;
10053 tcp_tran_rr_request->no_delay = rem_nodelay;
10054 tcp_tran_rr_request->measure_cpu = remote_cpu_usage;
10055 tcp_tran_rr_request->cpu_rate = remote_cpu_rate;
10056 tcp_tran_rr_request->so_rcvavoid = rem_rcvavoid;
10057 tcp_tran_rr_request->so_sndavoid = rem_sndavoid;
10058 if (test_time) {
10059 tcp_tran_rr_request->test_length = test_time;
10060 }
10061 else {
10062 tcp_tran_rr_request->test_length = test_trans * -1;
10063 }
10064 tcp_tran_rr_request->port = atoi(remote_data_port);
10065 tcp_tran_rr_request->ipfamily = af_to_nf(remote_res->ai_family);
10066
10067 if (debug > 1) {
10068 fprintf(where,"netperf: send_tcp_tran_rr: requesting TCP_TRR test\n");
10069 }
10070
10071 send_request();
10072
10073 /* The response from the remote will contain all of the relevant */
10074 /* socket parameters for this test type. We will put them back into */
10075 /* the variables here so they can be displayed if desired. The */
10076 /* remote will have calibrated CPU if necessary, and will have done */
10077 /* all the needed set-up we will have calibrated the cpu locally */
10078 /* before sending the request, and will grab the counter value right */
10079 /* after the connect returns. The remote will grab the counter right */
10080 /* after the accept call. This saves the hassle of extra messages */
10081 /* being sent for the TCP tests. */
10082
10083 recv_response();
10084
10085 if (!netperf_response.content.serv_errno) {
10086 rsr_size = tcp_tran_rr_response->recv_buf_size;
10087 rss_size = tcp_tran_rr_response->send_buf_size;
10088 rem_nodelay = tcp_tran_rr_response->no_delay;
10089 remote_cpu_usage= tcp_tran_rr_response->measure_cpu;
10090 remote_cpu_rate = tcp_tran_rr_response->cpu_rate;
10091 /* make sure that port numbers are in network order */
10092 server.sin_port = tcp_tran_rr_response->data_port_number;
10093 server.sin_port = htons(server.sin_port);
10094 if (debug) {
10095 fprintf(where,"remote listen done.\n");
10096 fprintf(where,"remote port is %d\n",ntohs(server.sin_port));
10097 fflush(where);
10098 }
10099 }
10100 else {
10101 Set_errno(netperf_response.content.serv_errno);
10102 fprintf(where,
10103 "netperf: remote error %d",
10104 netperf_response.content.serv_errno);
10105 perror("");
10106 fflush(where);
10107 exit(1);
10108 }
10109
10110 /* pick a nice random spot between client_port_min and */
10111 /* client_port_max for our initial port number. if they are the */
10112 /* same, then just set to _min */
10113 if (client_port_max - client_port_min) {
10114 srand(getpid());
10115 myport = client_port_min +
10116 (rand() % (client_port_max - client_port_min));
10117 }
10118 else {
10119 myport = client_port_min;
10120 }
10121
10122 /* there will be a ++ before the first call to bind, so subtract one */
10123 myport--;
10124 myaddr->sin_port = htons((unsigned short)myport);
10125
10126 /* Set-up the test end conditions. For a request/response test, they */
10127 /* can be either time or transaction based. */
10128
10129 if (test_time) {
10130 /* The user wanted to end the test after a period of time. */
10131 times_up = 0;
10132 trans_remaining = 0;
10133 start_timer(test_time);
10134 }
10135 else {
10136 /* The tester wanted to send a number of bytes. */
10137 trans_remaining = test_bytes;
10138 times_up = 1;
10139 }
10140
10141 /* The cpu_start routine will grab the current time and possibly */
10142 /* value of the idle counter for later use in measuring cpu */
10143 /* utilization and/or service demand and thruput. */
10144
10145 cpu_start(local_cpu_usage);
10146
10147 /* We use an "OR" to control test execution. When the test is */
10148 /* controlled by time, the byte count check will always return false. */
10149 /* When the test is controlled by byte count, the time test will */
10150 /* always return false. When the test is finished, the whole */
10151 /* expression will go false and we will stop sending data. I think I */
10152 /* just arbitrarily decrement trans_remaining for the timed test, but */
10153 /* will not do that just yet... One other question is whether or not */
10154 /* the send buffer and the receive buffer should be the same buffer. */
10155
10156 while ((!times_up) || (trans_remaining > 0)) {
10157
10158 #ifdef WANT_HISTOGRAM
10159 if (verbosity > 1) {
10160 /* timestamp just before our call to create the socket, and then */
10161 /* again just after the receive raj 3/95 */
10162 HIST_timestamp(&time_one);
10163 }
10164 #endif /* WANT_HISTOGRAM */
10165
10166 /* set up the data socket - is this really necessary or can I just */
10167 /* re-use the same socket and move this cal out of the while loop. */
10168 /* it does introcudea *boatload* of system calls. I guess that it */
10169 /* all depends on "reality of programming." keeping it this way is */
10170 /* a bit more conservative I imagine - raj 3/95 */
10171 send_socket = create_data_socket(local_res);
10172
10173 if (send_socket == INVALID_SOCKET) {
10174 perror("netperf: send_tcp_tran_rr: tcp stream data socket");
10175 exit(1);
10176 }
10177
10178 /* we set SO_REUSEADDR on the premis that no unreserved port */
10179 /* number on the local system is going to be already connected to */
10180 /* the remote netserver's port number. One thing that I might */
10181 /* try later is to have the remote actually allocate a couple of */
10182 /* port numbers and cycle through those as well. depends on if we */
10183 /* can get through all the unreserved port numbers in less than */
10184 /* the length of the TIME_WAIT state raj 8/94 */
10185 one = 1;
10186 if(setsockopt(send_socket, SOL_SOCKET, SO_REUSEADDR,
10187 (char *)&one, sock_opt_len) == SOCKET_ERROR) {
10188 perror("netperf: send_tcp_tran_rr: so_reuseaddr");
10189 exit(1);
10190 }
10191
10192 newport:
10193 /* pick a new port number */
10194 myport = ntohs(myaddr->sin_port);
10195 myport++;
10196
10197 /* we do not want to use the port number that the server is */
10198 /* sitting at - this would cause us to fail in a loopback test. we */
10199 /* could just rely on the failure of the bind to get us past this, */
10200 /* but I'm guessing that in this one case at least, it is much */
10201 /* faster, given that we *know* that port number is already in use */
10202 /* (or rather would be in a loopback test) */
10203
10204 if (myport == ntohs(server.sin_port)) myport++;
10205
10206 /* wrap the port number when we get to 65535. NOTE, some broken */
10207 /* TCP's might treat the port number as a signed 16 bit quantity. */
10208 /* we aren't interested in testing such broken implementations :) */
10209 /* raj 8/94 */
10210 if (myport >= client_port_max) {
10211 myport = client_port_min;
10212 }
10213 myaddr->sin_port = htons((unsigned short)myport);
10214
10215 if (debug) {
10216 if ((nummessages % 100) == 0) {
10217 printf("port %d\n",myport);
10218 }
10219 }
10220
10221 /* we want to bind our socket to a particular port number. */
10222 if (bind(send_socket,
10223 (struct sockaddr *)myaddr,
10224 sizeof(struct sockaddr_storage)) == SOCKET_ERROR) {
10225 /* if the bind failed, someone else must have that port number */
10226 /* - perhaps in the listen state. since we can't use it, skip to */
10227 /* the next port number. we may have to do this again later, but */
10228 /* that's just too bad :) */
10229 if (debug > 1) {
10230 fprintf(where,
10231 "send_tcp_tran_rr: tried to bind to port %d errno %d\n",
10232 ntohs(myaddr->sin_port),
10233 errno);
10234 fflush(where);
10235 }
10236 /* yes, goto's are supposed to be evil, but they do have their */
10237 /* uses from time to time. the real world doesn't always have */
10238 /* to code to ge tthe A in CS 101 :) raj 3/95 */
10239 goto newport;
10240 }
10241
10242 /* Connect up to the remote port on the data socket. Since this is */
10243 /* a test for RFC_1644-style transactional TCP, we can use the */
10244 /* sendto() call instead of calling connect and then send() */
10245
10246 /* send the request */
10247 if((len=sendto(send_socket,
10248 send_ring->buffer_ptr,
10249 req_size,
10250 MSG_EOF,
10251 (struct sockaddr *)&server,
10252 sizeof(server))) != req_size) {
10253 if (SOCKET_EINTR(len))
10254 {
10255 /* we hit the end of a */
10256 /* timed test. */
10257 timed_out = 1;
10258 break;
10259 }
10260 perror("send_tcp_tran_rr: data send error");
10261 exit(1);
10262 }
10263 send_ring = send_ring->next;
10264
10265 /* receive the response */
10266 rsp_bytes_left = rsp_size;
10267 temp_message_ptr = recv_ring->buffer_ptr;
10268 while(rsp_bytes_left > 0) {
10269 if((rsp_bytes_recvd=recv(send_socket,
10270 temp_message_ptr,
10271 rsp_bytes_left,
10272 0)) == SOCKET_ERROR) {
10273 if (SOCKET_EINTR(rsp_bytes_recvd))
10274 {
10275 /* We hit the end of a timed test. */
10276 timed_out = 1;
10277 break;
10278 }
10279 perror("send_tcp_tran_rr: data recv error");
10280 exit(1);
10281 }
10282 rsp_bytes_left -= rsp_bytes_recvd;
10283 temp_message_ptr += rsp_bytes_recvd;
10284 }
10285 recv_ring = recv_ring->next;
10286
10287 if (timed_out) {
10288 /* we may have been in a nested while loop - we need */
10289 /* another call to break. */
10290 break;
10291 }
10292
10293 close(send_socket);
10294
10295 #ifdef WANT_HISTOGRAM
10296 if (verbosity > 1) {
10297 HIST_timestamp(&time_two);
10298 HIST_add(time_hist,delta_micro(&time_one,&time_two));
10299 }
10300 #endif /* WANT_HISTOGRAM */
10301
10302 nummessages++;
10303 if (trans_remaining) {
10304 trans_remaining--;
10305 }
10306
10307 if (debug > 3) {
10308 fprintf(where,
10309 "Transaction %d completed on local port %d\n",
10310 nummessages,
10311 ntohs(myaddr->sin_port));
10312 fflush(where);
10313 }
10314
10315
10316 }
10317
10318 /* this call will always give us the elapsed time for the test, and */
10319 /* will also store-away the necessaries for cpu utilization */
10320
10321 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
10322 /* how long did we really run? */
10323
10324 /* Get the statistics from the remote end. The remote will have */
10325 /* calculated service demand and all those interesting things. If it */
10326 /* wasn't supposed to care, it will return obvious values. */
10327
10328 recv_response();
10329 if (!netperf_response.content.serv_errno) {
10330 if (debug)
10331 fprintf(where,"remote results obtained\n");
10332 }
10333 else {
10334 Set_errno(netperf_response.content.serv_errno);
10335 fprintf(where,
10336 "netperf: remote error %d",
10337 netperf_response.content.serv_errno);
10338 perror("");
10339 fflush(where);
10340 exit(1);
10341 }
10342
10343 /* We now calculate what our thruput was for the test. In the future, */
10344 /* we may want to include a calculation of the thruput measured by */
10345 /* the remote, but it should be the case that for a TCP stream test, */
10346 /* that the two numbers should be *very* close... We calculate */
10347 /* bytes_sent regardless of the way the test length was controlled. */
10348 /* If it was time, we needed to, and if it was by bytes, the user may */
10349 /* have specified a number of bytes that wasn't a multiple of the */
10350 /* send_size, so we really didn't send what he asked for ;-) We use */
10351 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
10352 /* 1024. A future enhancement *might* be to choose from a couple of */
10353 /* unit selections. */
10354
10355 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
10356 thruput = calc_thruput(bytes_xferd);
10357
10358 if (local_cpu_usage || remote_cpu_usage) {
10359 /* We must now do a little math for service demand and cpu */
10360 /* utilization for the system(s) */
10361 /* Of course, some of the information might be bogus because */
10362 /* there was no idle counter in the kernel(s). We need to make */
10363 /* a note of this for the user's benefit...*/
10364 if (local_cpu_usage) {
10365 if (local_cpu_rate == 0.0) {
10366 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
10367 fprintf(where,"Local CPU usage numbers based on process information only!\n");
10368 fflush(where);
10369 }
10370 local_cpu_utilization = calc_cpu_util(0.0);
10371 /* since calc_service demand is doing ms/Kunit we will */
10372 /* multiply the number of transaction by 1024 to get */
10373 /* "good" numbers */
10374 local_service_demand = calc_service_demand((double) nummessages*1024,
10375 0.0,
10376 0.0,
10377 0);
10378 }
10379 else {
10380 local_cpu_utilization = (float) -1.0;
10381 local_service_demand = (float) -1.0;
10382 }
10383
10384 if (remote_cpu_usage) {
10385 if (remote_cpu_rate == 0.0) {
10386 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
10387 fprintf(where,"Remote CPU usage numbers based on process information only!\n");
10388 fflush(where);
10389 }
10390 remote_cpu_utilization = tcp_tran_rr_result->cpu_util;
10391 /* since calc_service demand is doing ms/Kunit we will */
10392 /* multiply the number of transaction by 1024 to get */
10393 /* "good" numbers */
10394 remote_service_demand = calc_service_demand((double) nummessages*1024,
10395 0.0,
10396 remote_cpu_utilization,
10397 tcp_tran_rr_result->num_cpus);
10398 }
10399 else {
10400 remote_cpu_utilization = (float) -1.0;
10401 remote_service_demand = (float) -1.0;
10402 }
10403
10404 /* We are now ready to print all the information. If the user */
10405 /* has specified zero-level verbosity, we will just print the */
10406 /* local service demand, or the remote service demand. If the */
10407 /* user has requested verbosity level 1, he will get the basic */
10408 /* "streamperf" numbers. If the user has specified a verbosity */
10409 /* of greater than 1, we will display a veritable plethora of */
10410 /* background information from outside of this block as it it */
10411 /* not cpu_measurement specific... */
10412
10413 switch (verbosity) {
10414 case 0:
10415 if (local_cpu_usage) {
10416 fprintf(where,
10417 cpu_fmt_0,
10418 local_service_demand);
10419 }
10420 else {
10421 fprintf(where,
10422 cpu_fmt_0,
10423 remote_service_demand);
10424 }
10425 break;
10426 case 1:
10427 case 2:
10428
10429 if (print_headers) {
10430 fprintf(where,
10431 cpu_title,
10432 local_cpu_method,
10433 remote_cpu_method);
10434 }
10435
10436 fprintf(where,
10437 cpu_fmt_1_line_1, /* the format string */
10438 lss_size, /* local sendbuf size */
10439 lsr_size,
10440 req_size, /* how large were the requests */
10441 rsp_size, /* guess */
10442 elapsed_time, /* how long was the test */
10443 nummessages/elapsed_time,
10444 local_cpu_utilization, /* local cpu */
10445 remote_cpu_utilization, /* remote cpu */
10446 local_service_demand, /* local service demand */
10447 remote_service_demand); /* remote service demand */
10448 fprintf(where,
10449 cpu_fmt_1_line_2,
10450 rss_size,
10451 rsr_size);
10452 break;
10453 }
10454 }
10455 else {
10456 /* The tester did not wish to measure service demand. */
10457 switch (verbosity) {
10458 case 0:
10459 fprintf(where,
10460 tput_fmt_0,
10461 nummessages/elapsed_time);
10462 break;
10463 case 1:
10464 case 2:
10465 if (print_headers) {
10466 fprintf(where,tput_title,format_units());
10467 }
10468
10469 fprintf(where,
10470 tput_fmt_1_line_1, /* the format string */
10471 lss_size,
10472 lsr_size,
10473 req_size, /* how large were the requests */
10474 rsp_size, /* how large were the responses */
10475 elapsed_time, /* how long did it take */
10476 nummessages/elapsed_time);
10477 fprintf(where,
10478 tput_fmt_1_line_2,
10479 rss_size, /* remote recvbuf size */
10480 rsr_size);
10481
10482 break;
10483 }
10484 }
10485
10486 /* it would be a good thing to include information about some of the */
10487 /* other parameters that may have been set for this test, but at the */
10488 /* moment, I do not wish to figure-out all the formatting, so I will */
10489 /* just put this comment here to help remind me that it is something */
10490 /* that should be done at a later time. */
10491
10492 if (verbosity > 1) {
10493 /* The user wanted to know it all, so we will give it to him. */
10494 /* This information will include as much as we can find about */
10495 /* TCP statistics, the alignments of the sends and receives */
10496 /* and all that sort of rot... */
10497
10498 fprintf(where,
10499 ksink_fmt,
10500 local_send_align,
10501 remote_recv_offset,
10502 local_send_offset,
10503 remote_recv_offset);
10504
10505 #ifdef WANT_HISTOGRAM
10506 fprintf(where,"\nHistogram of request/response times\n");
10507 fflush(where);
10508 HIST_report(time_hist);
10509 #endif /* WANT_HISTOGRAM */
10510
10511 }
10512
10513 }
10514
10515
10516 int
recv_tcp_tran_rr()10517 recv_tcp_tran_rr()
10518 {
10519
10520 char *message;
10521 struct sockaddr_in myaddr_in,
10522 peeraddr_in;
10523 SOCKET s_listen,s_data;
10524 netperf_socklen_t addrlen;
10525 int NoPush = 1;
10526
10527 char *recv_message_ptr;
10528 char *send_message_ptr;
10529 char *temp_message_ptr;
10530 int trans_received;
10531 int trans_remaining;
10532 int bytes_sent;
10533 int request_bytes_recvd;
10534 int request_bytes_remaining;
10535 int timed_out = 0;
10536 float elapsed_time;
10537
10538 struct tcp_tran_rr_request_struct *tcp_tran_rr_request;
10539 struct tcp_tran_rr_response_struct *tcp_tran_rr_response;
10540 struct tcp_tran_rr_results_struct *tcp_tran_rr_results;
10541
10542 tcp_tran_rr_request =
10543 (struct tcp_tran_rr_request_struct *)netperf_request.content.test_specific_data;
10544 tcp_tran_rr_response =
10545 (struct tcp_tran_rr_response_struct *)netperf_response.content.test_specific_data;
10546 tcp_tran_rr_results =
10547 (struct tcp_tran_rr_results_struct *)netperf_response.content.test_specific_data;
10548
10549 if (debug) {
10550 fprintf(where,"netserver: recv_tcp_tran_rr: entered...\n");
10551 fflush(where);
10552 }
10553
10554 /* We want to set-up the listen socket with all the desired */
10555 /* parameters and then let the initiator know that all is ready. If */
10556 /* socket size defaults are to be used, then the initiator will have */
10557 /* sent us 0's. If the socket sizes cannot be changed, then we will */
10558 /* send-back what they are. If that information cannot be determined, */
10559 /* then we send-back -1's for the sizes. If things go wrong for any */
10560 /* reason, we will drop back ten yards and punt. */
10561
10562 /* If anything goes wrong, we want the remote to know about it. It */
10563 /* would be best if the error that the remote reports to the user is */
10564 /* the actual error we encountered, rather than some bogus unexpected */
10565 /* response type message. */
10566
10567 if (debug) {
10568 fprintf(where,"recv_tcp_tran_rr: setting the response type...\n");
10569 fflush(where);
10570 }
10571
10572 netperf_response.content.response_type = TCP_TRR_RESPONSE;
10573
10574 if (debug) {
10575 fprintf(where,"recv_tcp_tran_rr: the response type is set...\n");
10576 fflush(where);
10577 }
10578
10579 /* set-up the data buffer with the requested alignment and offset */
10580 message = (char *)malloc(DATABUFFERLEN);
10581 if (message == NULL) {
10582 printf("malloc(%d) failed!\n", DATABUFFERLEN);
10583 exit(1);
10584 }
10585
10586 /* We now alter the message_ptr variables to be at the desired */
10587 /* alignments with the desired offsets. */
10588
10589 if (debug) {
10590 fprintf(where,
10591 "recv_tcp_tran_rr: requested recv alignment of %d offset %d\n",
10592 tcp_tran_rr_request->recv_alignment,
10593 tcp_tran_rr_request->recv_offset);
10594 fprintf(where,
10595 "recv_tcp_tran_rr: requested send alignment of %d offset %d\n",
10596 tcp_tran_rr_request->send_alignment,
10597 tcp_tran_rr_request->send_offset);
10598 fflush(where);
10599 }
10600
10601 recv_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->recv_alignment, tcp_tran_rr_request->recv_offset);
10602
10603 send_message_ptr = ALIGN_BUFFER(message, tcp_tran_rr_request->send_alignment, tcp_tran_rr_request->send_offset);
10604
10605 if (debug) {
10606 fprintf(where,"recv_tcp_tran_rr: receive alignment and offset set...\n");
10607 fflush(where);
10608 }
10609
10610 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
10611 /* can put in OUR values !-) At some point, we may want to nail this */
10612 /* socket to a particular network-level address, but for now, */
10613 /* INADDR_ANY should be just fine. */
10614
10615 bzero((char *)&myaddr_in,
10616 sizeof(myaddr_in));
10617 myaddr_in.sin_family = AF_INET;
10618 myaddr_in.sin_addr.s_addr = INADDR_ANY;
10619 myaddr_in.sin_port = htons((unsigned short)tcp_tran_rr_request->port);
10620
10621 /* Grab a socket to listen on, and then listen on it. */
10622
10623 if (debug) {
10624 fprintf(where,"recv_tcp_tran_rr: grabbing a socket...\n");
10625 fflush(where);
10626 }
10627
10628 /* create_data_socket expects to find some things in the global */
10629 /* variables, so set the globals based on the values in the request. */
10630 /* once the socket has been created, we will set the response values */
10631 /* based on the updated value of those globals. raj 7/94 */
10632 lss_size_req = tcp_tran_rr_request->send_buf_size;
10633 lsr_size_req = tcp_tran_rr_request->recv_buf_size;
10634 loc_nodelay = tcp_tran_rr_request->no_delay;
10635 loc_rcvavoid = tcp_tran_rr_request->so_rcvavoid;
10636 loc_sndavoid = tcp_tran_rr_request->so_sndavoid;
10637
10638 set_hostname_and_port(local_name,
10639 port_buffer,
10640 nf_to_af(tcp_tran_rr_request->ipfamily),
10641 tcp_tran_rr_request->port);
10642
10643 local_res = complete_addrinfo(local_name,
10644 local_name,
10645 port_buffer,
10646 nf_to_af(tcp_tran_rr_request->ipfamily),
10647 SOCK_STREAM,
10648 IPPROTO_TCP,
10649 0);
10650
10651 s_listen = create_data_socket(local_res);
10652
10653 if (s_listen == INVALID_SOCKET) {
10654 netperf_response.content.serv_errno = errno;
10655 send_response();
10656 if (debug) {
10657 fprintf(where,"could not create data socket\n");
10658 fflush(where);
10659 }
10660 exit(1);
10661 }
10662
10663 #ifdef WIN32
10664 /* The test timer can fire during operations on the listening socket,
10665 so to make the start_timer below work we have to move
10666 it to close s_listen while we are blocked on accept. */
10667 win_kludge_socket2 = s_listen;
10668 #endif
10669
10670
10671 /* Let's get an address assigned to this socket so we can tell the */
10672 /* initiator how to reach the data socket. There may be a desire to */
10673 /* nail this socket to a specific IP address in a multi-homed, */
10674 /* multi-connection situation, but for now, we'll ignore the issue */
10675 /* and concentrate on single connection testing. */
10676
10677 if (bind(s_listen,
10678 (struct sockaddr *)&myaddr_in,
10679 sizeof(myaddr_in)) == SOCKET_ERROR) {
10680 netperf_response.content.serv_errno = errno;
10681 close(s_listen);
10682 send_response();
10683 if (debug) {
10684 fprintf(where,"could not bind\n");
10685 fflush(where);
10686 }
10687 exit(1);
10688 }
10689
10690 /* we want to disable the implicit PUSH on all sends. at some point, */
10691 /* this might want to be a parm to the test raj 3/95 */
10692 if (setsockopt(s_listen,
10693 IPPROTO_TCP,
10694 TCP_NOPUSH,
10695 (const char *)&NoPush,
10696 sizeof(int)) == SOCKET_ERROR) {
10697 fprintf(where,
10698 "recv_tcp_tran_rr: could not set TCP_NOPUSH errno %d\n",
10699 errno);
10700 fflush(where);
10701 netperf_response.content.serv_errno = errno;
10702 close(s_listen);
10703 send_response();
10704 }
10705
10706 /* Now, let's set-up the socket to listen for connections */
10707 if (listen(s_listen, 5) == SOCKET_ERROR) {
10708 netperf_response.content.serv_errno = errno;
10709 close(s_listen);
10710 send_response();
10711 if (debug) {
10712 fprintf(where,"could not listen\n");
10713 fflush(where);
10714 }
10715 exit(1);
10716 }
10717
10718 /* now get the port number assigned by the system */
10719 addrlen = sizeof(myaddr_in);
10720 if (getsockname(s_listen,
10721 (struct sockaddr *)&myaddr_in,
10722 &addrlen) == SOCKET_ERROR){
10723 netperf_response.content.serv_errno = errno;
10724 close(s_listen);
10725 send_response();
10726 if (debug) {
10727 fprintf(where,"could not geetsockname\n");
10728 fflush(where);
10729 }
10730 exit(1);
10731 }
10732
10733 /* Now myaddr_in contains the port and the internet address this is */
10734 /* returned to the sender also implicitly telling the sender that the */
10735 /* socket buffer sizing has been done. */
10736
10737 tcp_tran_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
10738 if (debug) {
10739 fprintf(where,"telling the remote to call me at %d\n",
10740 tcp_tran_rr_response->data_port_number);
10741 fflush(where);
10742 }
10743 netperf_response.content.serv_errno = 0;
10744
10745 /* But wait, there's more. If the initiator wanted cpu measurements, */
10746 /* then we must call the calibrate routine, which will return the max */
10747 /* rate back to the initiator. If the CPU was not to be measured, or */
10748 /* something went wrong with the calibration, we will return a 0.0 to */
10749 /* the initiator. */
10750
10751 tcp_tran_rr_response->cpu_rate = 0.0; /* assume no cpu */
10752 if (tcp_tran_rr_request->measure_cpu) {
10753 tcp_tran_rr_response->measure_cpu = 1;
10754 tcp_tran_rr_response->cpu_rate =
10755 calibrate_local_cpu(tcp_tran_rr_request->cpu_rate);
10756 }
10757
10758
10759
10760 /* before we send the response back to the initiator, pull some of */
10761 /* the socket parms from the globals */
10762 tcp_tran_rr_response->send_buf_size = lss_size;
10763 tcp_tran_rr_response->recv_buf_size = lsr_size;
10764 tcp_tran_rr_response->no_delay = loc_nodelay;
10765 tcp_tran_rr_response->so_rcvavoid = loc_rcvavoid;
10766 tcp_tran_rr_response->so_sndavoid = loc_sndavoid;
10767
10768 send_response();
10769
10770 addrlen = sizeof(peeraddr_in);
10771
10772 /* Now it's time to start receiving data on the connection. We will */
10773 /* first grab the apropriate counters and then start grabbing. */
10774
10775 cpu_start(tcp_tran_rr_request->measure_cpu);
10776
10777 /* The loop will exit when the sender does a shutdown, which will */
10778 /* return a length of zero */
10779
10780 if (tcp_tran_rr_request->test_length > 0) {
10781 times_up = 0;
10782 trans_remaining = 0;
10783 start_timer(tcp_tran_rr_request->test_length + PAD_TIME);
10784 }
10785 else {
10786 times_up = 1;
10787 trans_remaining = tcp_tran_rr_request->test_length * -1;
10788 }
10789
10790 trans_received = 0;
10791
10792 while ((!times_up) || (trans_remaining > 0)) {
10793
10794 /* accept a connection from the remote */
10795 if ((s_data=accept(s_listen,
10796 (struct sockaddr *)&peeraddr_in,
10797 &addrlen)) == INVALID_SOCKET) {
10798 if (errno == EINTR) {
10799 /* the timer popped */
10800 timed_out = 1;
10801 break;
10802 }
10803 fprintf(where,"recv_tcp_tran_rr: accept: errno = %d\n",errno);
10804 fflush(where);
10805 close(s_listen);
10806
10807 exit(1);
10808 }
10809
10810 if (debug) {
10811 fprintf(where,"recv_tcp_tran_rr: accepted data connection.\n");
10812 fflush(where);
10813 }
10814
10815 #ifdef WIN32
10816 /* this is used so the timer thread can close the socket out from */
10817 /* under us, which to date is the easiest/cleanest/least */
10818 /* Windows-specific way I can find to force the winsock calls to */
10819 /* return WSAEINTR with the test is over. anything that will run on */
10820 /* 95 and NT and is closer to what netperf expects from Unix signals */
10821 /* and such would be appreciated raj 1/96 */
10822 win_kludge_socket = s_data;
10823 #endif /* WIN32 */
10824
10825 #ifdef KLUDGE_SOCKET_OPTIONS
10826 /* this is for those systems which *INCORRECTLY* fail to pass */
10827 /* attributes across an accept() call. Including this goes against */
10828 /* my better judgement :( raj 11/95 */
10829
10830 kludge_socket_options(s_data);
10831
10832 #endif /* KLUDGE_SOCKET_OPTIONS */
10833
10834 temp_message_ptr = recv_message_ptr;
10835 request_bytes_remaining = tcp_tran_rr_request->request_size;
10836
10837 /* receive the request from the other side. we can just receive */
10838 /* until we get zero bytes, but that would be a slight structure */
10839 /* change in the code, with minimal perfomance effects. If */
10840 /* however, I has variable-length messages, I would want to do */
10841 /* this to avoid needing "double reads" - one for the message */
10842 /* length, and one for the rest of the message raj 3/95 */
10843 while(request_bytes_remaining > 0) {
10844 if((request_bytes_recvd=recv(s_data,
10845 temp_message_ptr,
10846 request_bytes_remaining,
10847 0)) == SOCKET_ERROR) {
10848 if ( SOCKET_EINTR(request_bytes_recvd) )
10849 {
10850 /* the timer popped */
10851 timed_out = 1;
10852 break;
10853 }
10854 netperf_response.content.serv_errno = errno;
10855 send_response();
10856 exit(1);
10857 }
10858 else {
10859 request_bytes_remaining -= request_bytes_recvd;
10860 temp_message_ptr += request_bytes_recvd;
10861 }
10862 }
10863
10864 if (timed_out) {
10865 /* we hit the end of the test based on time - lets */
10866 /* bail out of here now... */
10867 fprintf(where,"yo5\n");
10868 fflush(where);
10869 break;
10870 }
10871
10872 /* Now, send the response to the remote we can use sendto here to */
10873 /* help remind people that this is an rfc 1644 style of test */
10874 if((bytes_sent=sendto(s_data,
10875 send_message_ptr,
10876 tcp_tran_rr_request->response_size,
10877 MSG_EOF,
10878 (struct sockaddr *)&peeraddr_in,
10879 sizeof(struct sockaddr_storage))) == SOCKET_ERROR) {
10880 if (SOCKET_EINTR(bytes_sent)) {
10881 /* the test timer has popped */
10882 timed_out = 1;
10883 fprintf(where,"yo6\n");
10884 fflush(where);
10885 break;
10886 }
10887 netperf_response.content.serv_errno = 99;
10888 send_response();
10889 exit(1);
10890 }
10891
10892 trans_received++;
10893 if (trans_remaining) {
10894 trans_remaining--;
10895 }
10896
10897 if (debug) {
10898 fprintf(where,
10899 "recv_tcp_tran_rr: Transaction %d complete\n",
10900 trans_received);
10901 fflush(where);
10902 }
10903
10904 /* close the connection. since we have disable PUSH on sends, the */
10905 /* FIN should be tacked-onto our last send instead of being */
10906 /* standalone */
10907 close(s_data);
10908
10909 }
10910
10911
10912 /* The loop now exits due to timeout or transaction count being */
10913 /* reached */
10914
10915 cpu_stop(tcp_tran_rr_request->measure_cpu,&elapsed_time);
10916
10917 if (timed_out) {
10918 /* we ended the test by time, which was at least 2 seconds */
10919 /* longer than we wanted to run. so, we want to subtract */
10920 /* PAD_TIME from the elapsed_time. */
10921 elapsed_time -= PAD_TIME;
10922 }
10923 /* send the results to the sender */
10924
10925 if (debug) {
10926 fprintf(where,
10927 "recv_tcp_tran_rr: got %d transactions\n",
10928 trans_received);
10929 fflush(where);
10930 }
10931
10932 tcp_tran_rr_results->bytes_received = (trans_received *
10933 (tcp_tran_rr_request->request_size +
10934 tcp_tran_rr_request->response_size));
10935 tcp_tran_rr_results->trans_received = trans_received;
10936 tcp_tran_rr_results->elapsed_time = elapsed_time;
10937 if (tcp_tran_rr_request->measure_cpu) {
10938 tcp_tran_rr_results->cpu_util = calc_cpu_util(elapsed_time);
10939 }
10940
10941 if (debug) {
10942 fprintf(where,
10943 "recv_tcp_tran_rr: test complete, sending results.\n");
10944 fflush(where);
10945 }
10946
10947 send_response();
10948
10949 }
10950 #endif /* DO_1644 */
10951
10952 #ifdef DO_NBRR
10953 /* this routine implements the sending (netperf) side of the TCP_RR */
10954 /* test using POSIX-style non-blocking sockets. */
10955
10956 void
send_tcp_nbrr(char remote_host[])10957 send_tcp_nbrr(char remote_host[])
10958 {
10959
10960 char *tput_title = "\
10961 Local /Remote\n\
10962 Socket Size Request Resp. Elapsed Trans.\n\
10963 Send Recv Size Size Time Rate \n\
10964 bytes Bytes bytes bytes secs. per sec \n\n";
10965
10966 char *tput_fmt_0 =
10967 "%7.2f\n";
10968
10969 char *tput_fmt_1_line_1 = "\
10970 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
10971 char *tput_fmt_1_line_2 = "\
10972 %-6d %-6d\n";
10973
10974 char *cpu_title = "\
10975 Local /Remote\n\
10976 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
10977 Send Recv Size Size Time Rate local remote local remote\n\
10978 bytes bytes bytes bytes secs. per sec %% %c %% %c us/Tr us/Tr\n\n";
10979
10980 char *cpu_fmt_0 =
10981 "%6.3f %c\n";
10982
10983 char *cpu_fmt_1_line_1 = "\
10984 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
10985
10986 char *cpu_fmt_1_line_2 = "\
10987 %-6d %-6d\n";
10988
10989 char *ksink_fmt = "\
10990 Alignment Offset\n\
10991 Local Remote Local Remote\n\
10992 Send Recv Send Recv\n\
10993 %5d %5d %5d %5d\n";
10994
10995
10996 int timed_out = 0;
10997 float elapsed_time;
10998
10999 int len;
11000 char *temp_message_ptr;
11001 int nummessages;
11002 SOCKET send_socket;
11003 int trans_remaining;
11004 double bytes_xferd;
11005
11006 struct ring_elt *send_ring;
11007 struct ring_elt *recv_ring;
11008
11009 int rsp_bytes_left;
11010 int rsp_bytes_recvd;
11011
11012 float local_cpu_utilization;
11013 float local_service_demand;
11014 float remote_cpu_utilization;
11015 float remote_service_demand;
11016 double thruput;
11017
11018 struct hostent *hp;
11019 struct sockaddr_storage server;
11020 unsigned int addr;
11021
11022 struct tcp_rr_request_struct *tcp_rr_request;
11023 struct tcp_rr_response_struct *tcp_rr_response;
11024 struct tcp_rr_results_struct *tcp_rr_result;
11025
11026 struct addrinfo *remote_res;
11027 struct addrinfo *local_res;
11028
11029 tcp_rr_request =
11030 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
11031 tcp_rr_response=
11032 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
11033 tcp_rr_result =
11034 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
11035
11036 #ifdef WANT_HISTOGRAM
11037 if (verbosity > 1) {
11038 time_hist = HIST_new();
11039 }
11040 #endif /* WANT_HISTOGRAM */
11041
11042 /* since we are now disconnected from the code that established the */
11043 /* control socket, and since we want to be able to use different */
11044 /* protocols and such, we are passed the name of the remote host and */
11045 /* must turn that into the test specific addressing information. */
11046
11047 bzero((char *)&server,
11048 sizeof(server));
11049
11050 complete_addrinfos(&remote_res,
11051 &local_res,
11052 remote_host,
11053 SOCK_STREAM,
11054 IPPROTO_TCP,
11055 0);
11056
11057 if ( print_headers ) {
11058 print_top_test_header("TCP Non-Blocking REQUEST/RESPONSE TEST",local_res,remote_res);
11059 }
11060
11061 /* initialize a few counters */
11062
11063 send_ring = NULL;
11064 recv_ring = NULL;
11065 confidence_iteration = 1;
11066 init_stat();
11067
11068 /* we have a great-big while loop which controls the number of times */
11069 /* we run a particular test. this is for the calculation of a */
11070 /* confidence interval (I really should have stayed awake during */
11071 /* probstats :). If the user did not request confidence measurement */
11072 /* (no confidence is the default) then we will only go though the */
11073 /* loop once. the confidence stuff originates from the folks at IBM */
11074
11075 while (((confidence < 0) && (confidence_iteration < iteration_max)) ||
11076 (confidence_iteration <= iteration_min)) {
11077
11078 /* initialize a few counters. we have to remember that we might be */
11079 /* going through the loop more than once. */
11080
11081 nummessages = 0;
11082 bytes_xferd = 0.0;
11083 times_up = 0;
11084 timed_out = 0;
11085 trans_remaining = 0;
11086
11087 /* set-up the data buffers with the requested alignment and offset. */
11088 /* since this is a request/response test, default the send_width and */
11089 /* recv_width to 1 and not two raj 7/94 */
11090
11091 if (send_width == 0) send_width = 1;
11092 if (recv_width == 0) recv_width = 1;
11093
11094 if (send_ring == NULL) {
11095 send_ring = allocate_buffer_ring(send_width,
11096 req_size,
11097 local_send_align,
11098 local_send_offset);
11099 }
11100
11101 if (recv_ring == NULL) {
11102 recv_ring = allocate_buffer_ring(recv_width,
11103 rsp_size,
11104 local_recv_align,
11105 local_recv_offset);
11106 }
11107
11108 /*set up the data socket */
11109 send_socket = create_data_socket(local_res);
11110
11111 if (send_socket == INVALID_SOCKET){
11112 perror("netperf: send_tcp_nbrr: tcp stream data socket");
11113 exit(1);
11114 }
11115
11116 if (debug) {
11117 fprintf(where,"send_tcp_nbrr: send_socket obtained...\n");
11118 }
11119
11120 /* If the user has requested cpu utilization measurements, we must */
11121 /* calibrate the cpu(s). We will perform this task within the tests */
11122 /* themselves. If the user has specified the cpu rate, then */
11123 /* calibrate_local_cpu will return rather quickly as it will have */
11124 /* nothing to do. If local_cpu_rate is zero, then we will go through */
11125 /* all the "normal" calibration stuff and return the rate back.*/
11126
11127 if (local_cpu_usage) {
11128 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
11129 }
11130
11131 /* Tell the remote end to do a listen. The server alters the socket */
11132 /* paramters on the other side at this point, hence the reason for */
11133 /* all the values being passed in the setup message. If the user did */
11134 /* not specify any of the parameters, they will be passed as 0, which */
11135 /* will indicate to the remote that no changes beyond the system's */
11136 /* default should be used. Alignment is the exception, it will */
11137 /* default to 8, which will be no alignment alterations. */
11138
11139 netperf_request.content.request_type = DO_TCP_NBRR;
11140 tcp_rr_request->recv_buf_size = rsr_size_req;
11141 tcp_rr_request->send_buf_size = rss_size_req;
11142 tcp_rr_request->recv_alignment = remote_recv_align;
11143 tcp_rr_request->recv_offset = remote_recv_offset;
11144 tcp_rr_request->send_alignment = remote_send_align;
11145 tcp_rr_request->send_offset = remote_send_offset;
11146 tcp_rr_request->request_size = req_size;
11147 tcp_rr_request->response_size = rsp_size;
11148 tcp_rr_request->no_delay = rem_nodelay;
11149 tcp_rr_request->measure_cpu = remote_cpu_usage;
11150 tcp_rr_request->cpu_rate = remote_cpu_rate;
11151 tcp_rr_request->so_rcvavoid = rem_rcvavoid;
11152 tcp_rr_request->so_sndavoid = rem_sndavoid;
11153 if (test_time) {
11154 tcp_rr_request->test_length = test_time;
11155 }
11156 else {
11157 tcp_rr_request->test_length = test_trans * -1;
11158 }
11159
11160 if (debug > 1) {
11161 fprintf(where,"netperf: send_tcp_nbrr: requesting TCP rr test\n");
11162 }
11163
11164 send_request();
11165
11166 /* The response from the remote will contain all of the relevant */
11167 /* socket parameters for this test type. We will put them back into */
11168 /* the variables here so they can be displayed if desired. The */
11169 /* remote will have calibrated CPU if necessary, and will have done */
11170 /* all the needed set-up we will have calibrated the cpu locally */
11171 /* before sending the request, and will grab the counter value right*/
11172 /* after the connect returns. The remote will grab the counter right*/
11173 /* after the accept call. This saves the hassle of extra messages */
11174 /* being sent for the TCP tests. */
11175
11176 recv_response();
11177
11178 if (!netperf_response.content.serv_errno) {
11179 if (debug)
11180 fprintf(where,"remote listen done.\n");
11181 rsr_size = tcp_rr_response->recv_buf_size;
11182 rss_size = tcp_rr_response->send_buf_size;
11183 rem_nodelay = tcp_rr_response->no_delay;
11184 remote_cpu_usage = tcp_rr_response->measure_cpu;
11185 remote_cpu_rate = tcp_rr_response->cpu_rate;
11186 /* make sure that port numbers are in network order */
11187 server.sin_port = (unsigned short)tcp_rr_response->data_port_number;
11188 server.sin_port = htons(server.sin_port);
11189 }
11190 else {
11191 Set_errno(netperf_response.content.serv_errno);
11192 fprintf(where,
11193 "netperf: remote error %d",
11194 netperf_response.content.serv_errno);
11195 perror("");
11196 fflush(where);
11197 exit(1);
11198 }
11199
11200 /*Connect up to the remote port on the data socket */
11201 if (connect(send_socket,
11202 remote_res->ai_addr,
11203 remote_res->ai_addrlen) == INVALID_SOCKET){
11204 perror("netperf: data socket connect failed");
11205
11206 exit(1);
11207 }
11208
11209 /* now that we are connected, mark the socket as non-blocking */
11210 if (!set_nonblock(send_socket)) {
11211 perror("netperf: set_nonblock");
11212 exit(1);
11213 }
11214
11215 #ifdef WIN32
11216 /* this is used so the timer thread can close the socket out from */
11217 /* under us, which to date is the easiest/cleanest/least */
11218 /* Windows-specific way I can find to force the winsock calls to */
11219 /* return WSAEINTR with the test is over. anything that will run on */
11220 /* 95 and NT and is closer to what netperf expects from Unix signals */
11221 /* and such would be appreciated raj 1/96 */
11222 win_kludge_socket = send_socket;
11223 #endif /* WIN32 */
11224
11225 /* Data Socket set-up is finished. If there were problems, either the */
11226 /* connect would have failed, or the previous response would have */
11227 /* indicated a problem. I failed to see the value of the extra */
11228 /* message after the accept on the remote. If it failed, we'll see it */
11229 /* here. If it didn't, we might as well start pumping data. */
11230
11231 /* Set-up the test end conditions. For a request/response test, they */
11232 /* can be either time or transaction based. */
11233
11234 if (test_time) {
11235 /* The user wanted to end the test after a period of time. */
11236 times_up = 0;
11237 trans_remaining = 0;
11238 start_timer(test_time);
11239 }
11240 else {
11241 /* The tester wanted to send a number of bytes. */
11242 trans_remaining = test_bytes;
11243 times_up = 1;
11244 }
11245
11246 /* The cpu_start routine will grab the current time and possibly */
11247 /* value of the idle counter for later use in measuring cpu */
11248 /* utilization and/or service demand and thruput. */
11249
11250 cpu_start(local_cpu_usage);
11251
11252 #ifdef WANT_INTERVALS
11253 INTERVALS_INIT();
11254 #endif /* WANT_INTERVALS */
11255
11256 /* We use an "OR" to control test execution. When the test is */
11257 /* controlled by time, the byte count check will always return false. */
11258 /* When the test is controlled by byte count, the time test will */
11259 /* always return false. When the test is finished, the whole */
11260 /* expression will go false and we will stop sending data. I think I */
11261 /* just arbitrarily decrement trans_remaining for the timed test, but */
11262 /* will not do that just yet... One other question is whether or not */
11263 /* the send buffer and the receive buffer should be the same buffer. */
11264
11265 while ((!times_up) || (trans_remaining > 0)) {
11266 /* send the request. we assume that if we use a blocking socket, */
11267 /* the request will be sent at one shot. */
11268
11269 #ifdef WANT_HISTOGRAM
11270 if (verbosity > 1) {
11271 /* timestamp just before our call to send, and then again just */
11272 /* after the receive raj 8/94 */
11273 HIST_timestamp(&time_one);
11274 }
11275 #endif /* WANT_HISTOGRAM */
11276
11277 /* even though this is a non-blocking socket, we will assume for */
11278 /* the time being that we will be able to send an entire request */
11279 /* without getting an EAGAIN */
11280 if((len=send(send_socket,
11281 send_ring->buffer_ptr,
11282 req_size,
11283 0)) != req_size) {
11284 if (SOCKET_EINTR(len)) {
11285 /* we hit the end of a */
11286 /* timed test. */
11287 timed_out = 1;
11288 break;
11289 }
11290 perror("send_tcp_nbrr: data send error");
11291 exit(1);
11292 }
11293 send_ring = send_ring->next;
11294
11295 /* receive the response. since we are using non-blocking I/O, we */
11296 /* will "spin" on the recvs */
11297 rsp_bytes_left = rsp_size;
11298 temp_message_ptr = recv_ring->buffer_ptr;
11299 while(rsp_bytes_left > 0) {
11300 if((rsp_bytes_recvd=recv(send_socket,
11301 temp_message_ptr,
11302 rsp_bytes_left,
11303 0)) == SOCKET_ERROR) {
11304 if (SOCKET_EINTR(rsp_bytes_recvd))
11305 {
11306 /* We hit the end of a timed test. */
11307 timed_out = 1;
11308 break;
11309 }
11310 #ifndef WIN32 // But what does WinNT indicate in this situation...
11311 else if (errno == EAGAIN) {
11312 Set_errno(0);
11313 continue;
11314 }
11315 #endif
11316 else {
11317 perror("send_tcp_nbrr: data recv error");
11318 exit(1);
11319 }
11320 }
11321 rsp_bytes_left -= rsp_bytes_recvd;
11322 temp_message_ptr += rsp_bytes_recvd;
11323 }
11324 recv_ring = recv_ring->next;
11325
11326 if (timed_out) {
11327 /* we may have been in a nested while loop - we need */
11328 /* another call to break. */
11329 break;
11330 }
11331
11332 #ifdef WANT_HISTOGRAM
11333 if (verbosity > 1) {
11334 HIST_timestamp(&time_two);
11335 HIST_add(time_hist,delta_micro(&time_one,&time_two));
11336 }
11337 #endif /* WANT_HISTOGRAM */
11338 #ifdef WANT_INTERVALS
11339 INTERVALS_WAIT();
11340 #endif /* WANT_INTERVALS */
11341
11342 nummessages++;
11343 if (trans_remaining) {
11344 trans_remaining--;
11345 }
11346
11347 if (debug > 3) {
11348 if ((nummessages % 100) == 0) {
11349 fprintf(where,
11350 "Transaction %d completed\n",
11351 nummessages);
11352 fflush(where);
11353 }
11354 }
11355 }
11356
11357 /* At this point we used to call shutdown on the data socket to be */
11358 /* sure all the data was delivered, but this was not germane in a */
11359 /* request/response test, and it was causing the tests to "hang" when */
11360 /* they were being controlled by time. So, I have replaced this */
11361 /* shutdown call with a call to close that can be found later in the */
11362 /* procedure. */
11363
11364 /* this call will always give us the elapsed time for the test, and */
11365 /* will also store-away the necessaries for cpu utilization */
11366
11367 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being */
11368 /* measured? how long */
11369 /* did we really run? */
11370
11371 /* Get the statistics from the remote end. The remote will have */
11372 /* calculated service demand and all those interesting things. If it */
11373 /* wasn't supposed to care, it will return obvious values. */
11374
11375 #if defined(WANT_INTERVALS)
11376 #ifdef WIN32
11377 stop_itimer();
11378 #endif
11379 #endif /* WANT_INTERVALS */
11380
11381 recv_response();
11382 if (!netperf_response.content.serv_errno) {
11383 if (debug)
11384 fprintf(where,"remote results obtained\n");
11385 }
11386 else {
11387 Set_errno(netperf_response.content.serv_errno);
11388 fprintf(where,
11389 "netperf: remote error %d",
11390 netperf_response.content.serv_errno);
11391 perror("");
11392 fflush(where);
11393
11394 exit(1);
11395 }
11396
11397 /* We now calculate what our thruput was for the test. */
11398
11399 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
11400 thruput = nummessages/elapsed_time;
11401
11402 if (local_cpu_usage || remote_cpu_usage) {
11403 /* We must now do a little math for service demand and cpu */
11404 /* utilization for the system(s) */
11405 /* Of course, some of the information might be bogus because */
11406 /* there was no idle counter in the kernel(s). We need to make */
11407 /* a note of this for the user's benefit...*/
11408 if (local_cpu_usage) {
11409 local_cpu_utilization = calc_cpu_util(0.0);
11410 /* since calc_service demand is doing ms/Kunit we will */
11411 /* multiply the number of transaction by 1024 to get */
11412 /* "good" numbers */
11413 local_service_demand = calc_service_demand((double) nummessages*1024,
11414 0.0,
11415 0.0,
11416 0);
11417 }
11418 else {
11419 local_cpu_utilization = (float) -1.0;
11420 local_service_demand = (float) -1.0;
11421 }
11422
11423 if (remote_cpu_usage) {
11424 remote_cpu_utilization = tcp_rr_result->cpu_util;
11425 /* since calc_service demand is doing ms/Kunit we will */
11426 /* multiply the number of transaction by 1024 to get */
11427 /* "good" numbers */
11428 remote_service_demand = calc_service_demand((double) nummessages*1024,
11429 0.0,
11430 remote_cpu_utilization,
11431 tcp_rr_result->num_cpus);
11432 }
11433 else {
11434 remote_cpu_utilization = (float) -1.0;
11435 remote_service_demand = (float) -1.0;
11436 }
11437
11438 }
11439 else {
11440 /* we were not measuring cpu, for the confidence stuff, we */
11441 /* should make it -1.0 */
11442 local_cpu_utilization = (float) -1.0;
11443 local_service_demand = (float) -1.0;
11444 remote_cpu_utilization = (float) -1.0;
11445 remote_service_demand = (float) -1.0;
11446 }
11447
11448 /* at this point, we want to calculate the confidence information. */
11449 /* if debugging is on, calculate_confidence will print-out the */
11450 /* parameters we pass it */
11451
11452 calculate_confidence(confidence_iteration,
11453 elapsed_time,
11454 thruput,
11455 local_cpu_utilization,
11456 remote_cpu_utilization,
11457 local_service_demand,
11458 remote_service_demand);
11459
11460
11461 confidence_iteration++;
11462
11463 /* we are now done with the socket, so close it */
11464 close(send_socket);
11465
11466 }
11467
11468 retrieve_confident_values(&elapsed_time,
11469 &thruput,
11470 &local_cpu_utilization,
11471 &remote_cpu_utilization,
11472 &local_service_demand,
11473 &remote_service_demand);
11474
11475 /* We are now ready to print all the information. If the user */
11476 /* has specified zero-level verbosity, we will just print the */
11477 /* local service demand, or the remote service demand. If the */
11478 /* user has requested verbosity level 1, he will get the basic */
11479 /* "streamperf" numbers. If the user has specified a verbosity */
11480 /* of greater than 1, we will display a veritable plethora of */
11481 /* background information from outside of this block as it it */
11482 /* not cpu_measurement specific... */
11483
11484 if (confidence < 0) {
11485 /* we did not hit confidence, but were we asked to look for it? */
11486 if (iteration_max > 1) {
11487 display_confidence();
11488 }
11489 }
11490
11491 if (local_cpu_usage || remote_cpu_usage) {
11492 local_cpu_method = format_cpu_method(cpu_method);
11493 remote_cpu_method = format_cpu_method(tcp_rr_result->cpu_method);
11494
11495 switch (verbosity) {
11496 case 0:
11497 if (local_cpu_usage) {
11498 fprintf(where,
11499 cpu_fmt_0,
11500 local_service_demand,
11501 local_cpu_method);
11502 }
11503 else {
11504 fprintf(where,
11505 cpu_fmt_0,
11506 remote_service_demand,
11507 remote_cpu_method);
11508 }
11509 break;
11510 case 1:
11511 case 2:
11512 if (print_headers) {
11513 fprintf(where,
11514 cpu_title,
11515 local_cpu_method,
11516 remote_cpu_method);
11517 }
11518
11519 fprintf(where,
11520 cpu_fmt_1_line_1, /* the format string */
11521 lss_size, /* local sendbuf size */
11522 lsr_size,
11523 req_size, /* how large were the requests */
11524 rsp_size, /* guess */
11525 elapsed_time, /* how long was the test */
11526 thruput,
11527 local_cpu_utilization, /* local cpu */
11528 remote_cpu_utilization, /* remote cpu */
11529 local_service_demand, /* local service demand */
11530 remote_service_demand); /* remote service demand */
11531 fprintf(where,
11532 cpu_fmt_1_line_2,
11533 rss_size,
11534 rsr_size);
11535 break;
11536 }
11537 }
11538 else {
11539 /* The tester did not wish to measure service demand. */
11540
11541 switch (verbosity) {
11542 case 0:
11543 fprintf(where,
11544 tput_fmt_0,
11545 thruput);
11546 break;
11547 case 1:
11548 case 2:
11549 if (print_headers) {
11550 fprintf(where,tput_title,format_units());
11551 }
11552
11553 fprintf(where,
11554 tput_fmt_1_line_1, /* the format string */
11555 lss_size,
11556 lsr_size,
11557 req_size, /* how large were the requests */
11558 rsp_size, /* how large were the responses */
11559 elapsed_time, /* how long did it take */
11560 thruput);
11561 fprintf(where,
11562 tput_fmt_1_line_2,
11563 rss_size, /* remote recvbuf size */
11564 rsr_size);
11565
11566 break;
11567 }
11568 }
11569
11570 /* it would be a good thing to include information about some of the */
11571 /* other parameters that may have been set for this test, but at the */
11572 /* moment, I do not wish to figure-out all the formatting, so I will */
11573 /* just put this comment here to help remind me that it is something */
11574 /* that should be done at a later time. */
11575
11576 /* how to handle the verbose information in the presence of */
11577 /* confidence intervals is yet to be determined... raj 11/94 */
11578 if (verbosity > 1) {
11579 /* The user wanted to know it all, so we will give it to him. */
11580 /* This information will include as much as we can find about */
11581 /* TCP statistics, the alignments of the sends and receives */
11582 /* and all that sort of rot... */
11583
11584 fprintf(where,
11585 ksink_fmt,
11586 local_send_align,
11587 remote_recv_offset,
11588 local_send_offset,
11589 remote_recv_offset);
11590
11591 #ifdef WANT_HISTOGRAM
11592 fprintf(where,"\nHistogram of request/response times\n");
11593 fflush(where);
11594 HIST_report(time_hist);
11595 #endif /* WANT_HISTOGRAM */
11596
11597 }
11598
11599 }
11600
11601 /* this routine implements the receive (netserver) side of a TCP_RR */
11602 /* test */
11603 void
recv_tcp_nbrr()11604 recv_tcp_nbrr()
11605 {
11606
11607 struct ring_elt *send_ring;
11608 struct ring_elt *recv_ring;
11609
11610 struct sockaddr_in myaddr_in,
11611 peeraddr_in;
11612 SOCKET s_listen,s_data;
11613 netperf_socklen_t addrlen;
11614 char *temp_message_ptr;
11615 int trans_received;
11616 int trans_remaining;
11617 int bytes_sent;
11618 int request_bytes_recvd;
11619 int request_bytes_remaining;
11620 int timed_out = 0;
11621 float elapsed_time;
11622
11623 struct addrinfo *local_res;
11624 char local_name[BUFSIZ];
11625 char port_buffer[PORTBUFSIZE];
11626
11627 struct tcp_rr_request_struct *tcp_rr_request;
11628 struct tcp_rr_response_struct *tcp_rr_response;
11629 struct tcp_rr_results_struct *tcp_rr_results;
11630
11631 tcp_rr_request =
11632 (struct tcp_rr_request_struct *)netperf_request.content.test_specific_data;
11633 tcp_rr_response =
11634 (struct tcp_rr_response_struct *)netperf_response.content.test_specific_data;
11635 tcp_rr_results =
11636 (struct tcp_rr_results_struct *)netperf_response.content.test_specific_data;
11637
11638 if (debug) {
11639 fprintf(where,"netserver: recv_tcp_nbrr: entered...\n");
11640 fflush(where);
11641 }
11642
11643 /* We want to set-up the listen socket with all the desired */
11644 /* parameters and then let the initiator know that all is ready. If */
11645 /* socket size defaults are to be used, then the initiator will have */
11646 /* sent us 0's. If the socket sizes cannot be changed, then we will */
11647 /* send-back what they are. If that information cannot be determined, */
11648 /* then we send-back -1's for the sizes. If things go wrong for any */
11649 /* reason, we will drop back ten yards and punt. */
11650
11651 /* If anything goes wrong, we want the remote to know about it. It */
11652 /* would be best if the error that the remote reports to the user is */
11653 /* the actual error we encountered, rather than some bogus unexpected */
11654 /* response type message. */
11655
11656 if (debug) {
11657 fprintf(where,"recv_tcp_nbrr: setting the response type...\n");
11658 fflush(where);
11659 }
11660
11661 netperf_response.content.response_type = TCP_RR_RESPONSE;
11662
11663 if (debug) {
11664 fprintf(where,"recv_tcp_nbrr: the response type is set...\n");
11665 fflush(where);
11666 }
11667
11668 /* allocate the recv and send rings with the requested alignments */
11669 /* and offsets. raj 7/94 */
11670 if (debug) {
11671 fprintf(where,"recv_tcp_nbrr: requested recv alignment of %d offset %d\n",
11672 tcp_rr_request->recv_alignment,
11673 tcp_rr_request->recv_offset);
11674 fprintf(where,"recv_tcp_nbrr: requested send alignment of %d offset %d\n",
11675 tcp_rr_request->send_alignment,
11676 tcp_rr_request->send_offset);
11677 fflush(where);
11678 }
11679
11680 /* at some point, these need to come to us from the remote system */
11681 if (send_width == 0) send_width = 1;
11682 if (recv_width == 0) recv_width = 1;
11683
11684 send_ring = allocate_buffer_ring(send_width,
11685 tcp_rr_request->response_size,
11686 tcp_rr_request->send_alignment,
11687 tcp_rr_request->send_offset);
11688
11689 recv_ring = allocate_buffer_ring(recv_width,
11690 tcp_rr_request->request_size,
11691 tcp_rr_request->recv_alignment,
11692 tcp_rr_request->recv_offset);
11693
11694
11695 /* Let's clear-out our sockaddr for the sake of cleanlines. Then we */
11696 /* can put in OUR values !-) At some point, we may want to nail this */
11697 /* socket to a particular network-level address, but for now, */
11698 /* INADDR_ANY should be just fine. */
11699
11700 bzero((char *)&myaddr_in,
11701 sizeof(myaddr_in));
11702 myaddr_in.sin_family = AF_INET;
11703 myaddr_in.sin_addr.s_addr = INADDR_ANY;
11704 myaddr_in.sin_port = htons((unsigned short)tcp_rr_request->port);
11705
11706 /* Grab a socket to listen on, and then listen on it. */
11707
11708 if (debug) {
11709 fprintf(where,"recv_tcp_nbrr: grabbing a socket...\n");
11710 fflush(where);
11711 }
11712
11713 /* create_data_socket expects to find some things in the global */
11714 /* variables, so set the globals based on the values in the request. */
11715 /* once the socket has been created, we will set the response values */
11716 /* based on the updated value of those globals. raj 7/94 */
11717 lss_size_req = tcp_rr_request->send_buf_size;
11718 lsr_size_req = tcp_rr_request->recv_buf_size;
11719 loc_nodelay = tcp_rr_request->no_delay;
11720 loc_rcvavoid = tcp_rr_request->so_rcvavoid;
11721 loc_sndavoid = tcp_rr_request->so_sndavoid;
11722
11723 set_hostname_and_port(local_name,
11724 port_buffer,
11725 nf_to_af(tcp_rr_request->ipfamily),
11726 tcp_rr_request->port);
11727
11728 local_res = complete_addrinfo(local_name,
11729 local_name,
11730 port_buffer,
11731 nf_to_af(tcp_rr_request->ipfamily),
11732 SOCK_STREAM,
11733 IPPROTO_TCP,
11734 0);
11735
11736 s_listen = create_data_socket(local_res);
11737
11738 if (s_listen == INVALID_SOCKET) {
11739 netperf_response.content.serv_errno = errno;
11740 send_response();
11741
11742 exit(1);
11743 }
11744
11745 /* Let's get an address assigned to this socket so we can tell the */
11746 /* initiator how to reach the data socket. There may be a desire to */
11747 /* nail this socket to a specific IP address in a multi-homed, */
11748 /* multi-connection situation, but for now, we'll ignore the issue */
11749 /* and concentrate on single connection testing. */
11750
11751 if (bind(s_listen,
11752 (struct sockaddr *)&myaddr_in,
11753 sizeof(myaddr_in)) == SOCKET_ERROR) {
11754 netperf_response.content.serv_errno = errno;
11755 close(s_listen);
11756 send_response();
11757
11758 exit(1);
11759 }
11760
11761 /* Now, let's set-up the socket to listen for connections */
11762 if (listen(s_listen, 5) == SOCKET_ERROR) {
11763 netperf_response.content.serv_errno = errno;
11764 close(s_listen);
11765 send_response();
11766
11767 exit(1);
11768 }
11769
11770
11771 /* now get the port number assigned by the system */
11772 addrlen = sizeof(myaddr_in);
11773 if (getsockname(s_listen,
11774 (struct sockaddr *)&myaddr_in, &addrlen) == SOCKET_ERROR){
11775 netperf_response.content.serv_errno = errno;
11776 close(s_listen);
11777 send_response();
11778
11779 exit(1);
11780 }
11781
11782 /* Now myaddr_in contains the port and the internet address this is */
11783 /* returned to the sender also implicitly telling the sender that the */
11784 /* socket buffer sizing has been done. */
11785
11786 tcp_rr_response->data_port_number = (int) ntohs(myaddr_in.sin_port);
11787 netperf_response.content.serv_errno = 0;
11788
11789 /* But wait, there's more. If the initiator wanted cpu measurements, */
11790 /* then we must call the calibrate routine, which will return the max */
11791 /* rate back to the initiator. If the CPU was not to be measured, or */
11792 /* something went wrong with the calibration, we will return a 0.0 to */
11793 /* the initiator. */
11794
11795 tcp_rr_response->cpu_rate = 0.0; /* assume no cpu */
11796 tcp_rr_response->measure_cpu = 0;
11797
11798 if (tcp_rr_request->measure_cpu) {
11799 tcp_rr_response->measure_cpu = 1;
11800 tcp_rr_response->cpu_rate = calibrate_local_cpu(tcp_rr_request->cpu_rate);
11801 }
11802
11803
11804 /* before we send the response back to the initiator, pull some of */
11805 /* the socket parms from the globals */
11806 tcp_rr_response->send_buf_size = lss_size;
11807 tcp_rr_response->recv_buf_size = lsr_size;
11808 tcp_rr_response->no_delay = loc_nodelay;
11809 tcp_rr_response->so_rcvavoid = loc_rcvavoid;
11810 tcp_rr_response->so_sndavoid = loc_sndavoid;
11811 tcp_rr_response->test_length = tcp_rr_request->test_length;
11812 send_response();
11813
11814 addrlen = sizeof(peeraddr_in);
11815
11816 if ((s_data = accept(s_listen,
11817 (struct sockaddr *)&peeraddr_in,
11818 &addrlen)) == INVALID_SOCKET) {
11819 /* Let's just punt. The remote will be given some information */
11820 close(s_listen);
11821 exit(1);
11822 }
11823
11824 if (debug) {
11825 fprintf(where,"recv_tcp_nbrr: accept completes on the data connection.\n");
11826 fflush(where);
11827 }
11828
11829 #ifdef KLUDGE_SOCKET_OPTIONS
11830 /* this is for those systems which *INCORRECTLY* fail to pass */
11831 /* attributes across an accept() call. Including this goes against */
11832 /* my better judgement :( raj 11/95 */
11833
11834 kludge_socket_options(s_data);
11835
11836 #endif /* KLUDGE_SOCKET_OPTIONS */
11837
11838 /* now that we are connected, mark the socket as non-blocking */
11839 if (!set_nonblock(s_data)) {
11840 close(s_data);
11841 exit(1);
11842 }
11843
11844
11845 /* Now it's time to start receiving data on the connection. We will */
11846 /* first grab the apropriate counters and then start grabbing. */
11847
11848 cpu_start(tcp_rr_request->measure_cpu);
11849
11850 #ifdef WIN32
11851 /* this is used so the timer thread can close the socket out from */
11852 /* under us, which to date is the easiest/cleanest/least */
11853 /* Windows-specific way I can find to force the winsock calls to */
11854 /* return WSAEINTR with the test is over. anything that will run on */
11855 /* 95 and NT and is closer to what netperf expects from Unix signals */
11856 /* and such would be appreciated raj 1/96 */
11857 win_kludge_socket = s_data;
11858 #endif /* WIN32 */
11859
11860 /* The loop will exit when the sender does a shutdown, which will */
11861 /* return a length of zero */
11862
11863 if (tcp_rr_request->test_length > 0) {
11864 times_up = 0;
11865 trans_remaining = 0;
11866 start_timer(tcp_rr_request->test_length + PAD_TIME);
11867 }
11868 else {
11869 times_up = 1;
11870 trans_remaining = tcp_rr_request->test_length * -1;
11871 }
11872
11873 trans_received = 0;
11874
11875 while ((!times_up) || (trans_remaining > 0)) {
11876 temp_message_ptr = recv_ring->buffer_ptr;
11877 request_bytes_remaining = tcp_rr_request->request_size;
11878 while(request_bytes_remaining > 0) {
11879 if((request_bytes_recvd=recv(s_data,
11880 temp_message_ptr,
11881 request_bytes_remaining,
11882 0)) == SOCKET_ERROR) {
11883 if ( SOCKET_EINTR(request_bytes_recvd))
11884 {
11885 /* the timer popped */
11886 timed_out = 1;
11887 break;
11888 }
11889 #ifndef WIN32 // But what does WinNT indicate in this situation...
11890 else if (errno == EAGAIN) {
11891 Set_errno(0);
11892 if (times_up) {
11893 timed_out = 1;
11894 break;
11895 }
11896 continue;
11897 }
11898 #endif
11899 else {
11900 netperf_response.content.serv_errno = errno;
11901 send_response();
11902 exit(1);
11903 }
11904 }
11905 else {
11906 request_bytes_remaining -= request_bytes_recvd;
11907 temp_message_ptr += request_bytes_recvd;
11908 }
11909 }
11910
11911 recv_ring = recv_ring->next;
11912
11913 if (timed_out) {
11914 /* we hit the end of the test based on time - lets */
11915 /* bail out of here now... */
11916 fprintf(where,"yo5\n");
11917 fflush(where);
11918 break;
11919 }
11920
11921 /* Now, send the response to the remote */
11922 if((bytes_sent=send(s_data,
11923 send_ring->buffer_ptr,
11924 tcp_rr_request->response_size,
11925 0)) == SOCKET_ERROR) {
11926 if (SOCKET_EINTR(bytes_sent)) {
11927 /* the test timer has popped */
11928 timed_out = 1;
11929 fprintf(where,"yo6\n");
11930 fflush(where);
11931 break;
11932 }
11933 netperf_response.content.serv_errno = 992;
11934 send_response();
11935 exit(1);
11936 }
11937
11938 send_ring = send_ring->next;
11939
11940 trans_received++;
11941 if (trans_remaining) {
11942 trans_remaining--;
11943 }
11944 }
11945
11946
11947 /* The loop now exits due to timeout or transaction count being */
11948 /* reached */
11949
11950 cpu_stop(tcp_rr_request->measure_cpu,&elapsed_time);
11951
11952 stop_timer();
11953
11954 if (timed_out) {
11955 /* we ended the test by time, which was at least 2 seconds */
11956 /* longer than we wanted to run. so, we want to subtract */
11957 /* PAD_TIME from the elapsed_time. */
11958 elapsed_time -= PAD_TIME;
11959 }
11960
11961 /* send the results to the sender */
11962
11963 if (debug) {
11964 fprintf(where,
11965 "recv_tcp_nbrr: got %d transactions\n",
11966 trans_received);
11967 fflush(where);
11968 }
11969
11970 tcp_rr_results->bytes_received = (trans_received *
11971 (tcp_rr_request->request_size +
11972 tcp_rr_request->response_size));
11973 tcp_rr_results->trans_received = trans_received;
11974 tcp_rr_results->elapsed_time = elapsed_time;
11975 tcp_rr_results->cpu_method = cpu_method;
11976 tcp_rr_results->num_cpus = lib_num_loc_cpus;
11977 if (tcp_rr_request->measure_cpu) {
11978 tcp_rr_results->cpu_util = calc_cpu_util(elapsed_time);
11979 }
11980
11981 if (debug) {
11982 fprintf(where,
11983 "recv_tcp_nbrr: test complete, sending results.\n");
11984 fflush(where);
11985 }
11986
11987 /* we are done with the socket, free it */
11988 close(s_data);
11989
11990 send_response();
11991
11992 }
11993
11994 #endif /* DO_NBRR */
11995
11996
11997 /* this test is intended to test the performance of establishing a */
11998 /* connection, and then closing it again. this test is of somewhat */
11999 /* arcane interest since no packets are exchanged between the */
12000 /* user-space processes, but it will show the raw overhead of */
12001 /* establishing a TCP connection. that service demand could then be */
12002 /* compared with the sum of the service demands of a TCP_CRR and */
12003 /* TCP_RR test - presumeably, they would all relate */
12004
12005 void
send_tcp_cc(char remote_host[])12006 send_tcp_cc(char remote_host[])
12007 {
12008
12009 char *tput_title = "\
12010 Local /Remote\n\
12011 Socket Size Request Resp. Elapsed Trans.\n\
12012 Send Recv Size Size Time Rate \n\
12013 bytes Bytes bytes bytes secs. per sec \n\n";
12014
12015 char *tput_fmt_0 =
12016 "%7.2f\n";
12017
12018 char *tput_fmt_1_line_1 = "\
12019 %-6d %-6d %-6d %-6d %-6.2f %7.2f \n";
12020 char *tput_fmt_1_line_2 = "\
12021 %-6d %-6d\n";
12022
12023 char *cpu_title = "\
12024 Local /Remote\n\
12025 Socket Size Request Resp. Elapsed Trans. CPU CPU S.dem S.dem\n\
12026 Send Recv Size Size Time Rate local remote local remote\n\
12027 bytes bytes bytes bytes secs. per sec %% %% us/Tr us/Tr\n\n";
12028
12029 char *cpu_fmt_0 =
12030 "%6.3f\n";
12031
12032 char *cpu_fmt_1_line_1 = "\
12033 %-6d %-6d %-6d %-6d %-6.2f %-6.2f %-6.2f %-6.2f %-6.3f %-6.3f\n";
12034
12035 char *cpu_fmt_1_line_2 = "\
12036 %-6d %-6d\n";
12037
12038 char *ksink_fmt = "\n\
12039 Alignment Offset\n\
12040 Local Remote Local Remote\n\
12041 Send Recv Send Recv\n\
12042 %5d %5d %5d %5d\n";
12043
12044
12045 int timed_out = 0;
12046 float elapsed_time;
12047
12048 char temp_message_ptr[1];
12049 int nummessages;
12050 SOCKET send_socket;
12051 int trans_remaining;
12052 double bytes_xferd;
12053 int rsp_bytes_left = 1;
12054 int rsp_bytes_recvd;
12055
12056 float local_cpu_utilization;
12057 float local_service_demand;
12058 float remote_cpu_utilization;
12059 float remote_service_demand;
12060 double thruput;
12061
12062 struct addrinfo *local_res;
12063 struct addrinfo *remote_res;
12064
12065 int myport;
12066 int ret;
12067
12068 struct tcp_cc_request_struct *tcp_cc_request;
12069 struct tcp_cc_response_struct *tcp_cc_response;
12070 struct tcp_cc_results_struct *tcp_cc_result;
12071
12072 tcp_cc_request =
12073 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
12074 tcp_cc_response =
12075 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
12076 tcp_cc_result =
12077 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
12078
12079
12080 #ifdef WANT_HISTOGRAM
12081 if (verbosity > 1) {
12082 time_hist = HIST_new();
12083 }
12084 #endif /* WANT_HISTOGRAM */
12085
12086 /* since we are now disconnected from the code that established the */
12087 /* control socket, and since we want to be able to use different */
12088 /* protocols and such, we are passed the name of the remote host and */
12089 /* must turn that into the test specific addressing information. */
12090
12091 complete_addrinfos(&remote_res,
12092 &local_res,
12093 remote_host,
12094 SOCK_STREAM,
12095 IPPROTO_TCP,
12096 0);
12097
12098 if ( print_headers ) {
12099 print_top_test_header("TCP Connect/Close TEST",local_res,remote_res);
12100 }
12101
12102 /* initialize a few counters */
12103
12104 nummessages = 0;
12105 bytes_xferd = 0.0;
12106 times_up = 0;
12107
12108 /* since there are no data buffers in this test, we need no send or */
12109 /* recv rings */
12110
12111 if (debug) {
12112 fprintf(where,"send_tcp_cc: send_socket obtained...\n");
12113 }
12114
12115 /* If the user has requested cpu utilization measurements, we must */
12116 /* calibrate the cpu(s). We will perform this task within the tests */
12117 /* themselves. If the user has specified the cpu rate, then */
12118 /* calibrate_local_cpu will return rather quickly as it will have */
12119 /* nothing to do. If local_cpu_rate is zero, then we will go through */
12120 /* all the "normal" calibration stuff and return the rate back.*/
12121
12122 if (local_cpu_usage) {
12123 local_cpu_rate = calibrate_local_cpu(local_cpu_rate);
12124 }
12125
12126 /* Tell the remote end to do a listen. The server alters the socket */
12127 /* paramters on the other side at this point, hence the reason for */
12128 /* all the values being passed in the setup message. If the user did */
12129 /* not specify any of the parameters, they will be passed as 0, which */
12130 /* will indicate to the remote that no changes beyond the system's */
12131 /* default should be used. Alignment is the exception, it will */
12132 /* default to 8, which will be no alignment alterations. */
12133
12134 netperf_request.content.request_type = DO_TCP_CC;
12135 tcp_cc_request->recv_buf_size = rsr_size_req;
12136 tcp_cc_request->send_buf_size = rss_size_req;
12137 tcp_cc_request->recv_alignment = remote_recv_align;
12138 tcp_cc_request->recv_offset = remote_recv_offset;
12139 tcp_cc_request->send_alignment = remote_send_align;
12140 tcp_cc_request->send_offset = remote_send_offset;
12141 tcp_cc_request->request_size = req_size;
12142 tcp_cc_request->response_size = rsp_size;
12143 tcp_cc_request->no_delay = rem_nodelay;
12144 tcp_cc_request->measure_cpu = remote_cpu_usage;
12145 tcp_cc_request->cpu_rate = remote_cpu_rate;
12146 tcp_cc_request->so_rcvavoid = rem_rcvavoid;
12147 tcp_cc_request->so_sndavoid = rem_sndavoid;
12148 if (test_time) {
12149 tcp_cc_request->test_length = test_time;
12150 }
12151 else {
12152 tcp_cc_request->test_length = test_trans * -1;
12153 }
12154 tcp_cc_request->port = atoi(remote_data_port);
12155 tcp_cc_request->ipfamily = af_to_nf(remote_res->ai_family);
12156
12157 if (debug > 1) {
12158 fprintf(where,"netperf: send_tcp_cc: requesting TCP crr test\n");
12159 }
12160
12161 send_request();
12162
12163 /* The response from the remote will contain all of the relevant */
12164 /* socket parameters for this test type. We will put them back into */
12165 /* the variables here so they can be displayed if desired. The */
12166 /* remote will have calibrated CPU if necessary, and will have done */
12167 /* all the needed set-up we will have calibrated the cpu locally */
12168 /* before sending the request, and will grab the counter value right */
12169 /* after the connect returns. The remote will grab the counter right */
12170 /* after the accept call. This saves the hassle of extra messages */
12171 /* being sent for the TCP tests. */
12172
12173 recv_response();
12174
12175 if (!netperf_response.content.serv_errno) {
12176 rsr_size = tcp_cc_response->recv_buf_size;
12177 rss_size = tcp_cc_response->send_buf_size;
12178 rem_nodelay = tcp_cc_response->no_delay;
12179 remote_cpu_usage= tcp_cc_response->measure_cpu;
12180 remote_cpu_rate = tcp_cc_response->cpu_rate;
12181 /* make sure that port numbers are in network order */
12182 set_port_number(remote_res,(unsigned short)tcp_cc_response->data_port_number);
12183
12184 if (debug) {
12185 fprintf(where,"remote listen done.\n");
12186 fprintf(where,"remote port is %d\n",get_port_number(remote_res));
12187 fflush(where);
12188 }
12189 }
12190 else {
12191 Set_errno(netperf_response.content.serv_errno);
12192 fprintf(where,
12193 "netperf: remote error %d",
12194 netperf_response.content.serv_errno);
12195 perror("");
12196 fflush(where);
12197 exit(1);
12198 }
12199
12200 #ifdef WANT_DEMO
12201 demo_rr_setup(100);
12202 #endif
12203
12204 /* pick a nice random spot between client_port_min and */
12205 /* client_port_max for our initial port number */
12206 srand(getpid());
12207 if (client_port_max - client_port_min) {
12208 myport = client_port_min +
12209 (rand() % (client_port_max - client_port_min));
12210 }
12211 else {
12212 myport = client_port_min;
12213 }
12214 /* there will be a ++ before the first call to bind, so subtract one */
12215 myport--;
12216
12217 /* Set-up the test end conditions. For a request/response test, they */
12218 /* can be either time or transaction based. */
12219
12220 if (test_time) {
12221 /* The user wanted to end the test after a period of time. */
12222 times_up = 0;
12223 trans_remaining = 0;
12224 start_timer(test_time);
12225 }
12226 else {
12227 /* The tester wanted to send a number of bytes. */
12228 trans_remaining = test_bytes;
12229 times_up = 1;
12230 }
12231
12232 /* The cpu_start routine will grab the current time and possibly */
12233 /* value of the idle counter for later use in measuring cpu */
12234 /* utilization and/or service demand and thruput. */
12235
12236 cpu_start(local_cpu_usage);
12237
12238 #ifdef WANT_DEMO
12239 if (demo_mode) {
12240 demo_first_timestamp();
12241 }
12242 #endif
12243
12244 /* We use an "OR" to control test execution. When the test is */
12245 /* controlled by time, the byte count check will always return false. */
12246 /* When the test is controlled by byte count, the time test will */
12247 /* always return false. When the test is finished, the whole */
12248 /* expression will go false and we will stop sending data. I think I */
12249 /* just arbitrarily decrement trans_remaining for the timed test, but */
12250 /* will not do that just yet... One other question is whether or not */
12251 /* the send buffer and the receive buffer should be the same buffer. */
12252
12253 while ((!times_up) || (trans_remaining > 0)) {
12254
12255 #ifdef WANT_HISTOGRAM
12256 if (verbosity > 1) {
12257 /* timestamp just before our call to create the socket, and then */
12258 /* again just after the receive raj 3/95 */
12259 HIST_timestamp(&time_one);
12260 }
12261 #endif /* WANT_HISTOGRAM */
12262
12263 /* set up the data socket */
12264 /* newport: is this label really required any longer? */
12265 /* pick a new port number */
12266 myport++;
12267
12268 /* wrap the port number when we get to client_port_max. NOTE, some */
12269 /* broken TCP's might treat the port number as a signed 16 bit */
12270 /* quantity. we aren't interested in testing such broken */
12271 /* implementations :) so we won't make sure that it is below 32767 */
12272 /* raj 8/94 */
12273 if (myport >= client_port_max) {
12274 myport = client_port_min;
12275 }
12276
12277 /* we do not want to use the port number that the server is */
12278 /* sitting at - this would cause us to fail in a loopback test. we */
12279 /* could just rely on the failure of the bind to get us past this, */
12280 /* but I'm guessing that in this one case at least, it is much */
12281 /* faster, given that we *know* that port number is already in use */
12282 /* (or rather would be in a loopback test) */
12283
12284 if (myport == get_port_number(remote_res)) myport++;
12285
12286 if (debug) {
12287 if ((nummessages % 100) == 0) {
12288 printf("port %d\n",myport);
12289 }
12290 }
12291 set_port_number(local_res, (unsigned short)myport);
12292 send_socket = create_data_socket(local_res);
12293
12294 if (send_socket == INVALID_SOCKET) {
12295 perror("netperf: send_tcp_cc: tcp stream data socket");
12296 exit(1);
12297 }
12298
12299 #ifdef WIN32
12300 /* this is used so the timer thread can close the socket out from */
12301 /* under us, which to date is the easiest/cleanest/least */
12302 /* Windows-specific way I can find to force the winsock calls to */
12303 /* return WSAEINTR with the test is over. anything that will run on */
12304 /* 95 and NT and is closer to what netperf expects from Unix signals */
12305 /* and such would be appreciated raj 1/96 */
12306 win_kludge_socket = send_socket;
12307 #endif /* WIN32 */
12308
12309 /* we used to have a call to bind() here, but that is being
12310 taken care of by create_data_socket(). raj 2005-02-08 */
12311
12312 /* Connect up to the remote port on the data socket */
12313 if ((ret = connect(send_socket,
12314 remote_res->ai_addr,
12315 remote_res->ai_addrlen)) == INVALID_SOCKET){
12316 if (SOCKET_EINTR(ret))
12317 {
12318 /* we hit the end of a */
12319 /* timed test. */
12320 timed_out = 1;
12321 break;
12322 }
12323 perror("netperf: data socket connect failed");
12324 printf("\tattempted to connect on socket %d to port %d",
12325 send_socket,
12326 get_port_number(remote_res));
12327 printf(" from port %u \n",get_port_number(local_res));
12328 exit(1);
12329 }
12330
12331 /* we hang in a recv() to get the remote's close indication */
12332
12333 rsp_bytes_recvd=recv(send_socket,
12334 temp_message_ptr,
12335 rsp_bytes_left,
12336 0);
12337
12338
12339 if (rsp_bytes_recvd == 0) {
12340 /* connection close, call close. we assume that the requisite */
12341 /* number of bytes have been received */
12342
12343 #ifdef WANT_HISTOGRAM
12344 if (verbosity > 1) {
12345 HIST_timestamp(&time_two);
12346 HIST_add(time_hist,delta_micro(&time_one,&time_two));
12347 }
12348 #endif /* WANT_HISTOGRAM */
12349
12350 #ifdef WANT_DEMO
12351 demo_rr_interval(1);
12352 #endif
12353
12354 nummessages++;
12355 if (trans_remaining) {
12356 trans_remaining--;
12357 }
12358
12359 if (debug > 3) {
12360 fprintf(where,
12361 "Transaction %d completed on local port %u\n",
12362 nummessages,
12363 get_port_number(local_res));
12364 fflush(where);
12365 }
12366
12367 close(send_socket);
12368
12369 }
12370 else {
12371 /* it was less than zero - an error occured */
12372 if (SOCKET_EINTR(rsp_bytes_recvd))
12373 {
12374 /* We hit the end of a timed test. */
12375 timed_out = 1;
12376 break;
12377 }
12378 perror("send_tcp_cc: data recv error");
12379 exit(1);
12380 }
12381
12382 }
12383
12384
12385 /* this call will always give us the elapsed time for the test, and */
12386 /* will also store-away the necessaries for cpu utilization */
12387
12388 cpu_stop(local_cpu_usage,&elapsed_time); /* was cpu being measured? */
12389 /* how long did we really run? */
12390
12391 /* Get the statistics from the remote end. The remote will have */
12392 /* calculated service demand and all those interesting things. If it */
12393 /* wasn't supposed to care, it will return obvious values. */
12394
12395 recv_response();
12396 if (!netperf_response.content.serv_errno) {
12397 if (debug)
12398 fprintf(where,"remote results obtained\n");
12399 }
12400 else {
12401 Set_errno(netperf_response.content.serv_errno);
12402 fprintf(where,
12403 "netperf: remote error %d",
12404 netperf_response.content.serv_errno);
12405 perror("");
12406 fflush(where);
12407
12408 exit(1);
12409 }
12410
12411 /* We now calculate what our thruput was for the test. In the future, */
12412 /* we may want to include a calculation of the thruput measured by */
12413 /* the remote, but it should be the case that for a TCP stream test, */
12414 /* that the two numbers should be *very* close... We calculate */
12415 /* bytes_sent regardless of the way the test length was controlled. */
12416 /* If it was time, we needed to, and if it was by bytes, the user may */
12417 /* have specified a number of bytes that wasn't a multiple of the */
12418 /* send_size, so we really didn't send what he asked for ;-) We use */
12419 /* Kbytes/s as the units of thruput for a TCP stream test, where K = */
12420 /* 1024. A future enhancement *might* be to choose from a couple of */
12421 /* unit selections. */
12422
12423 bytes_xferd = (req_size * nummessages) + (rsp_size * nummessages);
12424 thruput = calc_thruput(bytes_xferd);
12425
12426 if (local_cpu_usage || remote_cpu_usage) {
12427 /* We must now do a little math for service demand and cpu */
12428 /* utilization for the system(s) */
12429 /* Of course, some of the information might be bogus because */
12430 /* there was no idle counter in the kernel(s). We need to make */
12431 /* a note of this for the user's benefit...*/
12432 if (local_cpu_usage) {
12433 if (local_cpu_rate == 0.0) {
12434 fprintf(where,"WARNING WARNING WARNING WARNING WARNING WARNING WARNING!\n");
12435 fprintf(where,"Local CPU usage numbers based on process information only!\n");
12436 fflush(where);
12437 }
12438 local_cpu_utilization = calc_cpu_util(0.0);
12439 /* since calc_service demand is doing ms/Kunit we will */
12440 /* multiply the number of transaction by 1024 to get */
12441 /* "good" numbers */
12442 local_service_demand = calc_service_demand((double) nummessages*1024,
12443 0.0,
12444 0.0,
12445 0);
12446 }
12447 else {
12448 local_cpu_utilization = (float) -1.0;
12449 local_service_demand = (float) -1.0;
12450 }
12451
12452 if (remote_cpu_usage) {
12453 if (remote_cpu_rate == 0.0) {
12454 fprintf(where,"DANGER DANGER DANGER DANGER DANGER DANGER DANGER!\n");
12455 fprintf(where,"Remote CPU usage numbers based on process information only!\n");
12456 fflush(where);
12457 }
12458 remote_cpu_utilization = tcp_cc_result->cpu_util;
12459 /* since calc_service demand is doing ms/Kunit we will */
12460 /* multiply the number of transaction by 1024 to get */
12461 /* "good" numbers */
12462 remote_service_demand = calc_service_demand((double) nummessages*1024,
12463 0.0,
12464 remote_cpu_utilization,
12465 tcp_cc_result->num_cpus);
12466 }
12467 else {
12468 remote_cpu_utilization = (float) -1.0;
12469 remote_service_demand = (float) -1.0;
12470 }
12471
12472 /* We are now ready to print all the information. If the user */
12473 /* has specified zero-level verbosity, we will just print the */
12474 /* local service demand, or the remote service demand. If the */
12475 /* user has requested verbosity level 1, he will get the basic */
12476 /* "streamperf" numbers. If the user has specified a verbosity */
12477 /* of greater than 1, we will display a veritable plethora of */
12478 /* background information from outside of this block as it it */
12479 /* not cpu_measurement specific... */
12480
12481 switch (verbosity) {
12482 case 0:
12483 if (local_cpu_usage) {
12484 fprintf(where,
12485 cpu_fmt_0,
12486 local_service_demand);
12487 }
12488 else {
12489 fprintf(where,
12490 cpu_fmt_0,
12491 remote_service_demand);
12492 }
12493 break;
12494 case 1:
12495 case 2:
12496
12497 if (print_headers) {
12498 fprintf(where,
12499 cpu_title,
12500 local_cpu_method,
12501 remote_cpu_method);
12502 }
12503
12504 fprintf(where,
12505 cpu_fmt_1_line_1, /* the format string */
12506 lss_size, /* local sendbuf size */
12507 lsr_size,
12508 req_size, /* how large were the requests */
12509 rsp_size, /* guess */
12510 elapsed_time, /* how long was the test */
12511 nummessages/elapsed_time,
12512 local_cpu_utilization, /* local cpu */
12513 remote_cpu_utilization, /* remote cpu */
12514 local_service_demand, /* local service demand */
12515 remote_service_demand); /* remote service demand */
12516 fprintf(where,
12517 cpu_fmt_1_line_2,
12518 rss_size,
12519 rsr_size);
12520 break;
12521 }
12522 }
12523 else {
12524 /* The tester did not wish to measure service demand. */
12525 switch (verbosity) {
12526 case 0:
12527 fprintf(where,
12528 tput_fmt_0,
12529 nummessages/elapsed_time);
12530 break;
12531 case 1:
12532 case 2:
12533 if (print_headers) {
12534 fprintf(where,tput_title,format_units());
12535 }
12536
12537 fprintf(where,
12538 tput_fmt_1_line_1, /* the format string */
12539 lss_size,
12540 lsr_size,
12541 req_size, /* how large were the requests */
12542 rsp_size, /* how large were the responses */
12543 elapsed_time, /* how long did it take */
12544 nummessages/elapsed_time);
12545 fprintf(where,
12546 tput_fmt_1_line_2,
12547 rss_size, /* remote recvbuf size */
12548 rsr_size);
12549
12550 break;
12551 }
12552 }
12553
12554 /* it would be a good thing to include information about some of the */
12555 /* other parameters that may have been set for this test, but at the */
12556 /* moment, I do not wish to figure-out all the formatting, so I will */
12557 /* just put this comment here to help remind me that it is something */
12558 /* that should be done at a later time. */
12559
12560 if (verbosity > 1) {
12561 /* The user wanted to know it all, so we will give it to him. */
12562 /* This information will include as much as we can find about */
12563 /* TCP statistics, the alignments of the sends and receives */
12564 /* and all that sort of rot... */
12565
12566 fprintf(where,
12567 ksink_fmt,
12568 local_send_align,
12569 remote_recv_offset,
12570 local_send_offset,
12571 remote_recv_offset);
12572
12573 #ifdef WANT_HISTOGRAM
12574 fprintf(where,"\nHistogram of request/response times\n");
12575 fflush(where);
12576 HIST_report(time_hist);
12577 #endif /* WANT_HISTOGRAM */
12578
12579 }
12580
12581 }
12582
12583
12584 void
recv_tcp_cc()12585 recv_tcp_cc()
12586 {
12587
12588 char *message;
12589
12590 struct addrinfo *local_res;
12591 char local_name[BUFSIZ];
12592 char port_buffer[PORTBUFSIZE];
12593
12594 struct sockaddr_storage myaddr_in, peeraddr_in;
12595 SOCKET s_listen,s_data;
12596 netperf_socklen_t addrlen;
12597 char *recv_message_ptr;
12598 char *send_message_ptr;
12599 int trans_received;
12600 int trans_remaining;
12601 int timed_out = 0;
12602 float elapsed_time;
12603
12604 struct tcp_cc_request_struct *tcp_cc_request;
12605 struct tcp_cc_response_struct *tcp_cc_response;
12606 struct tcp_cc_results_struct *tcp_cc_results;
12607
12608 tcp_cc_request =
12609 (struct tcp_cc_request_struct *)netperf_request.content.test_specific_data;
12610 tcp_cc_response =
12611 (struct tcp_cc_response_struct *)netperf_response.content.test_specific_data;
12612 tcp_cc_results =
12613 (struct tcp_cc_results_struct *)netperf_response.content.test_specific_data;
12614
12615 if (debug) {
12616 fprintf(where,"netserver: recv_tcp_cc: entered...\n");
12617 fflush(where);
12618 }
12619
12620 /* We want to set-up the listen socket with all the desired */
12621 /* parameters and then let the initiator know that all is ready. If */
12622 /* socket size defaults are to be used, then the initiator will have */
12623 /* sent us 0's. If the socket sizes cannot be changed, then we will */
12624 /* send-back what they are. If that information cannot be determined, */
12625 /* then we send-back -1's for the sizes. If things go wrong for any */
12626 /* reason, we will drop back ten yards and punt. */
12627
12628 /* If anything goes wrong, we want the remote to know about it. It */
12629 /* would be best if the error that the remote reports to the user is */
12630 /* the actual error we encountered, rather than some bogus unexpected */
12631 /* response type message. */
12632
12633 if (debug) {
12634 fprintf(where,"recv_tcp_cc: setting the response type...\n");
12635 fflush(where);
12636 }
12637
12638 netperf_response.content.response_type = TCP_CC_RESPONSE;
12639
12640 if (debug) {
12641 fprintf(where,"recv_tcp_cc: the response type is set...\n");
12642 fflush(where);
12643 }
12644
12645 /* set-up the data buffer with the requested alignment and offset */
12646 message = (char *)malloc(DATABUFFERLEN);
12647 if (message == NULL) {
12648 printf("malloc(%d) failed!\n", DATABUFFERLEN);
12649 exit(1);
12650 }
12651
12652 /* We now alter the message_ptr variables to be at the desired */
12653 /* alignments with the desired offsets. */
12654
12655 if (debug) {
12656 fprintf(where,
12657 "recv_tcp_cc: requested recv alignment of %d offset %d\n",
12658 tcp_cc_request->recv_alignment,
12659 tcp_cc_request->recv_offset);
12660 fprintf(where,
12661 "recv_tcp_cc: requested send alignment of %d offset %d\n",
12662 tcp_cc_request->send_alignment,
12663 tcp_cc_request->send_offset);
12664 fflush(where);
12665 }
12666
12667 recv_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->recv_alignment, tcp_cc_request->recv_offset);
12668
12669 send_message_ptr = ALIGN_BUFFER(message, tcp_cc_request->send_alignment, tcp_cc_request->send_offset);
12670
12671 if (debug) {
12672 fprintf(where,"recv_tcp_cc: receive alignment and offset set...\n");
12673 fflush(where);
12674 }
12675
12676 /* Grab a socket to listen on, and then listen on it. */
12677
12678 if (debug) {
12679 fprintf(where,"recv_tcp_cc: grabbing a socket...\n");
12680 fflush(where);
12681 }
12682
12683 /* create_data_socket expects to find some things in the global */
12684 /* variables, so set the globals based on the values in the request. */
12685 /* once the socket has been created, we will set the response values */
12686 /* based on the updated value of those globals. raj 7/94 */
12687 lss_size_req = tcp_cc_request->send_buf_size;
12688 lsr_size_req = tcp_cc_request->recv_buf_size;
12689 loc_nodelay = tcp_cc_request->no_delay;
12690 loc_rcvavoid = tcp_cc_request->so_rcvavoid;
12691 loc_sndavoid = tcp_cc_request->so_sndavoid;
12692
12693 set_hostname_and_port(local_name,
12694 port_buffer,
12695 nf_to_af(tcp_cc_request->ipfamily),
12696 tcp_cc_request->port);
12697
12698 local_res = complete_addrinfo(local_name,
12699 local_name,
12700 port_buffer,
12701 nf_to_af(tcp_cc_request->ipfamily),
12702 SOCK_STREAM,
12703 IPPROTO_TCP,
12704 0);
12705
12706 s_listen = create_data_socket(local_res);
12707
12708 if (s_listen == INVALID_SOCKET) {
12709 netperf_response.content.serv_errno = errno;
12710 send_response();
12711 if (debug) {
12712 fprintf(where,"could not create data socket\n");
12713 fflush(where);
12714 }
12715 exit(1);
12716 }
12717
12718 #ifdef WIN32
12719 /* The test timer can fire during operations on the listening socket,
12720 so to make the start_timer below work we have to move
12721 it to close s_listen while we are blocked on accept. */
12722 win_kludge_socket2 = s_listen;
12723 #endif
12724
12725
12726 /* Now, let's set-up the socket to listen for connections */
12727 if (listen(s_listen, 5) == SOCKET_ERROR) {
12728 netperf_response.content.serv_errno = errno;
12729 close(s_listen);
12730 send_response();
12731 if (debug) {
12732 fprintf(where,"could not listen\n");
12733 fflush(where);
12734 }
12735 exit(1);
12736 }
12737
12738 /* now get the port number assigned by the system */
12739 addrlen = sizeof(myaddr_in);
12740 if (getsockname(s_listen,
12741 (struct sockaddr *)&myaddr_in,
12742 &addrlen) == SOCKET_ERROR){
12743 netperf_response.content.serv_errno = errno;
12744 close(s_listen);
12745 send_response();
12746 if (debug) {
12747 fprintf(where,"could not geetsockname\n");
12748 fflush(where);
12749 }
12750 exit(1);
12751 }
12752
12753 /* Now myaddr_in contains the port and the internet address this is */
12754 /* returned to the sender also implicitly telling the sender that the */
12755 /* socket buffer sizing has been done. */
12756
12757 tcp_cc_response->data_port_number =
12758 (int) ntohs(((struct sockaddr_in *)&myaddr_in)->sin_port);
12759 if (debug) {
12760 fprintf(where,"telling the remote to call me at %d\n",
12761 tcp_cc_response->data_port_number);
12762 fflush(where);
12763 }
12764 netperf_response.content.serv_errno = 0;
12765
12766 /* But wait, there's more. If the initiator wanted cpu measurements, */
12767 /* then we must call the calibrate routine, which will return the max */
12768 /* rate back to the initiator. If the CPU was not to be measured, or */
12769 /* something went wrong with the calibration, we will return a 0.0 to */
12770 /* the initiator. */
12771
12772 tcp_cc_response->cpu_rate = (float)0.0; /* assume no cpu */
12773 if (tcp_cc_request->measure_cpu) {
12774 tcp_cc_response->measure_cpu = 1;
12775 tcp_cc_response->cpu_rate =
12776 calibrate_local_cpu(tcp_cc_request->cpu_rate);
12777 }
12778
12779
12780
12781 /* before we send the response back to the initiator, pull some of */
12782 /* the socket parms from the globals */
12783 tcp_cc_response->send_buf_size = lss_size;
12784 tcp_cc_response->recv_buf_size = lsr_size;
12785 tcp_cc_response->no_delay = loc_nodelay;
12786 tcp_cc_response->so_rcvavoid = loc_rcvavoid;
12787 tcp_cc_response->so_sndavoid = loc_sndavoid;
12788
12789 send_response();
12790
12791 addrlen = sizeof(peeraddr_in);
12792
12793 /* Now it's time to start receiving data on the connection. We will */
12794 /* first grab the apropriate counters and then start grabbing. */
12795
12796 cpu_start(tcp_cc_request->measure_cpu);
12797
12798 /* The loop will exit when the sender does a shutdown, which will */
12799 /* return a length of zero */
12800
12801 if (tcp_cc_request->test_length > 0) {
12802 times_up = 0;
12803 trans_remaining = 0;
12804 start_timer(tcp_cc_request->test_length + PAD_TIME);
12805 }
12806 else {
12807 times_up = 1;
12808 trans_remaining = tcp_cc_request->test_length * -1;
12809 }
12810
12811 trans_received = 0;
12812
12813 while ((!times_up) || (trans_remaining > 0)) {
12814 #ifdef WIN32
12815 /* The test timer will probably fire during this accept,
12816 so to make the start_timer above work we have to move
12817 it to close s_listen while we are blocked on accept. */
12818 win_kludge_socket = s_listen;
12819 #endif
12820 /* accept a connection from the remote */
12821 if ((s_data=accept(s_listen,
12822 (struct sockaddr *)&peeraddr_in,
12823 &addrlen)) == INVALID_SOCKET) {
12824 if (errno == EINTR) {
12825 /* the timer popped */
12826 timed_out = 1;
12827 break;
12828 }
12829 fprintf(where,"recv_tcp_cc: accept: errno = %d\n",errno);
12830 fflush(where);
12831 close(s_listen);
12832
12833 exit(1);
12834 }
12835
12836 #ifdef KLUDGE_SOCKET_OPTIONS
12837 /* this is for those systems which *INCORRECTLY* fail to pass */
12838 /* attributes across an accept() call. Including this goes against */
12839 /* my better judgement :( raj 11/95 */
12840
12841 kludge_socket_options(s_data);
12842
12843 #endif /* KLUDGE_SOCKET_OPTIONS */
12844
12845 #ifdef WIN32
12846 /* this is used so the timer thread can close the socket out from */
12847 /* under us, which to date is the easiest/cleanest/least */
12848 /* Windows-specific way I can find to force the winsock calls to */
12849 /* return WSAEINTR with the test is over. anything that will run on */
12850 /* 95 and NT and is closer to what netperf expects from Unix signals */
12851 /* and such would be appreciated raj 1/96 */
12852 win_kludge_socket = s_data;
12853 #endif /* WIN32 */
12854
12855 if (debug) {
12856 fprintf(where,"recv_tcp_cc: accepted data connection.\n");
12857 fflush(where);
12858 }
12859
12860
12861 /* close the connection. the server will likely do a graceful */
12862 /* close of the connection, insuring that all data has arrived at */
12863 /* the client. for this it will call shutdown(), and then recv() and */
12864 /* then close(). I'm reasonably confident that this is the */
12865 /* appropriate sequence of calls - I would like to hear of */
12866 /* examples in web servers to the contrary. raj 10/95*/
12867 close(s_data);
12868
12869 trans_received++;
12870 if (trans_remaining) {
12871 trans_remaining--;
12872 }
12873
12874 if (debug) {
12875 fprintf(where,
12876 "recv_tcp_cc: Transaction %d complete\n",
12877 trans_received);
12878 fflush(where);
12879 }
12880
12881 }
12882
12883
12884 /* The loop now exits due to timeout or transaction count being */
12885 /* reached */
12886
12887 cpu_stop(tcp_cc_request->measure_cpu,&elapsed_time);
12888
12889 if (timed_out) {
12890 /* we ended the test by time, which was at least 2 seconds */
12891 /* longer than we wanted to run. so, we want to subtract */
12892 /* PAD_TIME from the elapsed_time. */
12893 elapsed_time -= PAD_TIME;
12894 }
12895 /* send the results to the sender */
12896
12897 if (debug) {
12898 fprintf(where,
12899 "recv_tcp_cc: got %d transactions\n",
12900 trans_received);
12901 fflush(where);
12902 }
12903
12904 tcp_cc_results->bytes_received = (trans_received *
12905 (tcp_cc_request->request_size +
12906 tcp_cc_request->response_size));
12907 tcp_cc_results->trans_received = trans_received;
12908 tcp_cc_results->elapsed_time = elapsed_time;
12909 tcp_cc_results->num_cpus = lib_num_loc_cpus;
12910 if (tcp_cc_request->measure_cpu) {
12911 tcp_cc_results->cpu_util = calc_cpu_util(elapsed_time);
12912 }
12913
12914 if (debug) {
12915 fprintf(where,
12916 "recv_tcp_cc: test complete, sending results.\n");
12917 fflush(where);
12918 }
12919
12920 send_response();
12921
12922 }
12923
12924 void
print_sockets_usage()12925 print_sockets_usage()
12926 {
12927
12928 fwrite(sockets_usage, sizeof(char), strlen(sockets_usage), stdout);
12929 exit(1);
12930
12931 }
12932
12933 void
scan_sockets_args(int argc,char * argv[])12934 scan_sockets_args(int argc, char *argv[])
12935
12936 {
12937
12938 #define SOCKETS_ARGS "b:CDnNhH:L:m:M:p:P:r:R:s:S:T:Vw:W:z46"
12939
12940 extern char *optarg; /* pointer to option string */
12941
12942 int c;
12943
12944 char
12945 arg1[BUFSIZ], /* argument holders */
12946 arg2[BUFSIZ];
12947
12948 if (debug) {
12949 int i;
12950 printf("%s called with the following argument vector\n",
12951 #if _MSC_VER <= 1200
12952 "scan_sockets_args");
12953 #else
12954 __func__);
12955 #endif
12956 for (i = 0; i< argc; i++) {
12957 printf("%s ",argv[i]);
12958 }
12959 printf("\n");
12960 }
12961
12962 strncpy(local_data_port,"0",sizeof(local_data_port));
12963 strncpy(remote_data_port,"0",sizeof(remote_data_port));
12964
12965 /* by default, only a UDP_STREAM test disallows routing, to cover
12966 the backsides of incompetent testers who have bogus setups */
12967 if (strcasecmp(test_name,"UDP_STREAM") == 0) {
12968 routing_allowed = 0;
12969 }
12970
12971 /* Go through all the command line arguments and break them */
12972 /* out. For those options that take two parms, specifying only */
12973 /* the first will set both to that value. Specifying only the */
12974 /* second will leave the first untouched. To change only the */
12975 /* first, use the form "first," (see the routine break_args.. */
12976
12977 while ((c= getopt(argc, argv, SOCKETS_ARGS)) != EOF) {
12978 switch (c) {
12979 case '?':
12980 case '4':
12981 remote_data_family = AF_INET;
12982 local_data_family = AF_INET;
12983 break;
12984 case '6':
12985 #if defined(AF_INET6)
12986 remote_data_family = AF_INET6;
12987 local_data_family = AF_INET6;
12988 #else
12989 fprintf(stderr,
12990 "This netperf was not compiled on an IPv6 capable host!\n");
12991 fflush(stderr);
12992 exit(-1);
12993 #endif
12994 break;
12995 case 'h':
12996 print_sockets_usage();
12997 exit(1);
12998 case 'b':
12999 #ifdef WANT_FIRST_BURST
13000 first_burst_size = atoi(optarg);
13001 #else /* WANT_FIRST_BURST */
13002 printf("Initial request burst functionality not compiled-in!\n");
13003 #endif /* WANT_FIRST_BURST */
13004 break;
13005 case 'C':
13006 #ifdef TCP_CORK
13007 /* set TCP_CORK */
13008 loc_tcpcork = 1;
13009 rem_tcpcork = 1; /* however, at first, we ony have cork affect loc */
13010 #else
13011 printf("WARNING: TCP_CORK not available on this platform!\n");
13012 #endif /* TCP_CORK */
13013 break;
13014 case 'D':
13015 /* set the TCP nodelay flag */
13016 loc_nodelay = 1;
13017 rem_nodelay = 1;
13018 break;
13019 case 'H':
13020 break_args_explicit(optarg,arg1,arg2);
13021 if (arg1[0]) {
13022 /* make sure we leave room for the NULL termination boys and
13023 girls. raj 2005-02-82 */
13024 remote_data_address = malloc(strlen(arg1)+1);
13025 strncpy(remote_data_address,arg1,strlen(arg1));
13026 }
13027 if (arg2[0])
13028 remote_data_family = parse_address_family(arg2);
13029 break;
13030 case 'L':
13031 break_args_explicit(optarg,arg1,arg2);
13032 if (arg1[0]) {
13033 /* make sure we leave room for the NULL termination boys and
13034 girls. raj 2005-02-82 */
13035 local_data_address = malloc(strlen(arg1)+1);
13036 strncpy(local_data_address,arg1,strlen(arg1));
13037 }
13038 if (arg2[0])
13039 local_data_family = parse_address_family(arg2);
13040 break;
13041 case 's':
13042 /* set local socket sizes */
13043 break_args(optarg,arg1,arg2);
13044 if (arg1[0])
13045 lss_size_req = convert(arg1);
13046 if (arg2[0])
13047 lsr_size_req = convert(arg2);
13048 break;
13049 case 'S':
13050 /* set remote socket sizes */
13051 break_args(optarg,arg1,arg2);
13052 if (arg1[0])
13053 rss_size_req = convert(arg1);
13054 if (arg2[0])
13055 rsr_size_req = convert(arg2);
13056 break;
13057 case 'r':
13058 /* set the request/response sizes */
13059 break_args(optarg,arg1,arg2);
13060 if (arg1[0])
13061 req_size = convert(arg1);
13062 if (arg2[0])
13063 rsp_size = convert(arg2);
13064 break;
13065 case 'R':
13066 /* enable/disable routing on the data connection*/
13067 routing_allowed = atoi(optarg);
13068 break;
13069 case 'm':
13070 /* set the send size */
13071 send_size = convert(optarg);
13072 break;
13073 case 'M':
13074 /* set the recv size */
13075 recv_size = convert(optarg);
13076 break;
13077 case 'n':
13078 /* set the local socket type*/
13079 local_connected = 1;
13080 break;
13081 case 'N':
13082 /* set the remote socket type*/
13083 remote_connected = 1;
13084 break;
13085 case 'p':
13086 /* set the min and max port numbers for the TCP_CRR and TCP_TRR */
13087 /* tests. */
13088 break_args(optarg,arg1,arg2);
13089 if (arg1[0])
13090 client_port_min = atoi(arg1);
13091 if (arg2[0])
13092 client_port_max = atoi(arg2);
13093 break;
13094 case 'P':
13095 /* set the local and remote data port numbers for the tests to
13096 allow them to run through those blankety blank end-to-end
13097 breaking firewalls. raj 2004-06-15 */
13098 break_args(optarg,arg1,arg2);
13099 if (arg1[0])
13100 strncpy(local_data_port,arg1,sizeof(local_data_port));
13101 if (arg2[0])
13102 strncpy(remote_data_port,arg2,sizeof(remote_data_port));
13103 break;
13104 case 't':
13105 /* set the test name */
13106 strcpy(test_name,optarg);
13107 break;
13108 case 'W':
13109 /* set the "width" of the user space data */
13110 /* buffer. This will be the number of */
13111 /* send_size buffers malloc'd in the */
13112 /* *_STREAM test. It may be enhanced to set */
13113 /* both send and receive "widths" but for now */
13114 /* it is just the sending *_STREAM. */
13115 send_width = convert(optarg);
13116 break;
13117 case 'V' :
13118 /* we want to do copy avoidance and will set */
13119 /* it for everything, everywhere, if we really */
13120 /* can. of course, we don't know anything */
13121 /* about the remote... */
13122 #ifdef SO_SND_COPYAVOID
13123 loc_sndavoid = 1;
13124 #else
13125 loc_sndavoid = 0;
13126 printf("Local send copy avoidance not available.\n");
13127 #endif
13128 #ifdef SO_RCV_COPYAVOID
13129 loc_rcvavoid = 1;
13130 #else
13131 loc_rcvavoid = 0;
13132 printf("Local recv copy avoidance not available.\n");
13133 #endif
13134 rem_sndavoid = 1;
13135 rem_rcvavoid = 1;
13136 break;
13137 };
13138 }
13139
13140 #if defined(WANT_FIRST_BURST)
13141 #if defined(WANT_HISTOGRAM)
13142 /* if WANT_FIRST_BURST and WANT_HISTOGRAM are defined and the user
13143 indeed wants a non-zero first burst size, and we would emit a
13144 histogram, then we should emit a warning that the two are not
13145 compatible. raj 2006-01-31 */
13146 if ((first_burst_size > 0) && (verbosity >= 2)) {
13147 fprintf(stderr,
13148 "WARNING! Histograms and first bursts are incompatible!\n");
13149 fflush(stderr);
13150 }
13151 #endif
13152 #endif
13153
13154 /* we do not want to make remote_data_address non-NULL because if
13155 the user has not specified a remote adata address, we want to
13156 take it from the hostname in the -H global option. raj
13157 2005-02-08 */
13158
13159 /* so, if there is to be no control connection, we want to have some
13160 different settings for a few things */
13161
13162 if (no_control) {
13163
13164 if (strcmp(remote_data_port,"0") == 0) {
13165 /* we need to select either the discard port, echo port or
13166 chargen port dedepending on the test name. raj 2007-02-08 */
13167 if (strstr(test_name,"STREAM") ||
13168 strstr(test_name,"SENDFILE")) {
13169 strncpy(remote_data_port,"discard",sizeof(remote_data_port));
13170 }
13171 else if (strstr(test_name,"RR")) {
13172 strncpy(remote_data_port,"echo",sizeof(remote_data_port));
13173 }
13174 else if (strstr(test_name,"MAERTS")) {
13175 strncpy(remote_data_port,"chargen",sizeof(remote_data_port));
13176 }
13177 else {
13178 printf("No default port known for the %s test, please set one yourself\n",test_name);
13179 exit(-1);
13180 }
13181 }
13182 remote_data_port[sizeof(remote_data_port) - 1] = '\0';
13183
13184 /* I go back and forth on whether these should become -1 or if
13185 they should become 0 for a no_control test. what do you think?
13186 raj 2006-02-08 */
13187
13188 rem_rcvavoid = -1;
13189 rem_sndavoid = -1;
13190 rss_size_req = -1;
13191 rsr_size_req = -1;
13192 rem_nodelay = -1;
13193
13194 if (strstr(test_name,"STREAM") ||
13195 strstr(test_name,"SENDFILE")) {
13196 recv_size = -1;
13197 }
13198 else if (strstr(test_name,"MAERTS")) {
13199 send_size = -1;
13200 }
13201 }
13202 }
13203