2 //=============================================================================
6 * Measures UDP round-trip performance.
8 * @author Fred Kuhns and David L. Levine
10 //=============================================================================
13 #include "ace/OS_main.h"
14 #include "ace/Reactor.h"
15 #include "ace/SOCK_Dgram.h"
16 #include "ace/INET_Addr.h"
18 #include "ace/Get_Opt.h"
19 #include "ace/High_Res_Timer.h"
20 #include "ace/Log_Msg.h"
21 #include "ace/OS_NS_stdio.h"
22 #include "ace/OS_NS_ctype.h"
23 #include "ace/OS_NS_arpa_inet.h"
24 #include "ace/OS_NS_string.h"
25 #include "ace/os_include/os_netdb.h"
26 #include "ace/OS_NS_unistd.h"
28 // FUZZ: disable check_for_math_include
31 // Global variables (evil).
32 static const u_short DEFPORT
= 5050;
33 static const int MAXPKTSZ
= 65536;
34 static const int DEFPKTSZ
= 64;
35 static const int DEFITERATIONS
= 1000;
36 static const int DEFINTERVAL
= 1000; // 1000 usecs.
37 static const int DEFWINDOWSZ
= 10; // 10 microsecond.
38 static char SendBuf
[MAXPKTSZ
];
39 static char RxBuf
[MAXPKTSZ
];
40 static ACE_TCHAR
**cmd
;
41 static ACE_TCHAR datafile
[MAXHOSTNAMELEN
];
43 static ACE_UINT32 nsamples
= DEFITERATIONS
;
44 static int usdelay
= DEFINTERVAL
;
45 static int bufsz
= DEFPKTSZ
;
46 static int window
= DEFWINDOWSZ
;
47 static int VERBOSE
= 0;
48 static int logfile
= 0;
49 static int server
= 0;
50 static int client
= 0;
51 static u_int use_reactor
= 0;
52 ACE_hrtime_t max_allow
= 0;
53 ACE_hrtime_t total_ltime
;
62 " [-f datafile] (creates datafile.samp and datafile.dist)\n"
71 " [-x max_sample_allowed]\n"
72 " [-a to use the ACE reactor]\n"
77 static ACE_hrtime_t
*Samples
;
79 static ACE_TCHAR sumfile
[30];
80 static ACE_TCHAR distfile
[30];
81 static ACE_TCHAR sampfile
[30];
83 class Client
: public ACE_Event_Handler
86 Client (const ACE_INET_Addr
&addr
,
87 const ACE_INET_Addr
&remote_addr
);
89 virtual ~Client (void);
91 // = Override <ACE_Event_Handler> methods.
92 virtual ACE_HANDLE
get_handle (void) const;
93 virtual int handle_input (ACE_HANDLE
);
94 virtual int handle_close (ACE_HANDLE handle
,
95 ACE_Reactor_Mask close_mask
);
97 //FUZZ: disable check_for_lack_ACE_OS
98 /// Send the <buf> to the server.
99 int send (const char *buf
, size_t len
);
100 //FUZZ: enable check_for_lack_ACE_OS
102 /// Wait for the response.
103 int get_response (char *buf
, size_t len
);
105 /// Send messages to server and record statistics.
108 //FUZZ: disable check_for_lack_ACE_OS
109 /// Send shutdown message to server.
111 //FUZZ: enable check_for_lack_ACE_OS
114 /// To send messages and receive responses.
115 ACE_SOCK_Dgram endpoint_
;
117 /// The address to send messages to.
118 ACE_INET_Addr remote_addr_
;
120 ACE_UNIMPLEMENTED_FUNC (Client (void))
121 ACE_UNIMPLEMENTED_FUNC (Client (const Client
&))
122 ACE_UNIMPLEMENTED_FUNC (Client
&operator= (const Client
&))
125 Client::Client (const ACE_INET_Addr
&addr
,
126 const ACE_INET_Addr
&remote_addr
)
128 remote_addr_ (remote_addr
)
132 if (ACE_Reactor::instance ()->register_handler
133 (this, ACE_Event_Handler::READ_MASK
) == -1)
134 ACE_ERROR ((LM_ERROR
,
135 "ACE_Reactor::register_handler: Client\n"));
139 Client::~Client (void)
144 Client::get_handle (void) const
146 return endpoint_
.get_handle ();
150 Client::handle_input (ACE_HANDLE
)
153 ACE_INET_Addr from_addr
;
155 ssize_t n
= endpoint_
.recv (buf
, sizeof buf
, from_addr
);
158 ACE_ERROR ((LM_ERROR
,
162 ACE_DEBUG ((LM_DEBUG
,
163 "(%P|%t) buf of size %d = %*s\n",
172 Client::handle_close (ACE_HANDLE
,
175 this->endpoint_
.close ();
180 Client::send (const char *buf
, size_t len
)
182 return this->endpoint_
.send (buf
, len
, remote_addr_
);
186 Client::get_response (char *buf
, size_t len
)
189 return this->endpoint_
.recv (buf
, len
, addr
);
201 char *sbuf
= SendBuf
;
204 ACE_High_Res_Timer timer
;
208 double std_dev
= 0.0;
209 double std_err
= 0.0;
210 double sample_mean
= 0.0;
212 int tracking_last_over
= 0;
213 ACE_High_Res_Timer since_over
;
214 ACE_hrtime_t psum
= 0;
215 ACE_hrtime_t sum
= 0;
216 ACE_hrtime_t max
= 0;
217 ACE_hrtime_t min
= (ACE_hrtime_t
) (u_int
) -1;
221 pid_t
*pid
= (pid_t
*) sbuf
;
222 int *seq
= (int *) (sbuf
+ sizeof (int));
224 ACE_OS::memset (sbuf
, 0, bufsz
);
225 ACE_OS::memset (rbuf
, 0, bufsz
);
227 *pid
= ACE_OS::getpid ();
230 ACE_DEBUG ((LM_DEBUG
,
231 "PID = %d, Starting SEQ = %d\n",
235 // Allocate memory to hold samples.
236 Samples
= (ACE_hrtime_t
*) ACE_OS::calloc (nsamples
,
237 sizeof (ACE_hrtime_t
));
239 for (i
= -1, *seq
= 0, j
= 0;
240 i
< (ACE_INT32
) nsamples
;
241 (*seq
)++, i
++, j
++, timer
.reset ())
244 if (this->send (sbuf
, bufsz
) <= 0)
245 ACE_ERROR_RETURN ((LM_ERROR
, "(%P) %p\n", "send"), -1);
247 if ((n
= get_response (rbuf
, bufsz
)) <= 0)
248 ACE_ERROR_RETURN ((LM_ERROR
, "(%P) %p\n", "get_response"), -1);
253 ACE_ERROR_RETURN ((LM_ERROR
,
254 "\nTrouble receiving from socket!\n\n"),
257 timer
.elapsed_time (sample
); // in nanoseconds.
261 ACE_DEBUG ((LM_DEBUG
,
262 "Ignoring first sample of %u usecs\n",
263 (ACE_UINT32
) (sample
)));
266 else if (max_allow
> 0 && sample
> max_allow
)
268 ACE_DEBUG ((LM_DEBUG
, "Sample # %i = "
269 "%u msec is over the limit (%u)!\n",
271 (ACE_UINT32
) (sample
/ (ACE_UINT32
) 1000000),
272 (ACE_UINT32
) (max_allow
/ (ACE_UINT32
) 1000000)));
274 if (tracking_last_over
)
277 ACE_Time_Value over_time
;
278 since_over
.elapsed_time (over_time
);
279 ACE_DEBUG ((LM_DEBUG
,
280 "\tTime since last over = %u msec!\n",
285 tracking_last_over
= 1;
294 if (min
== (ACE_hrtime_t
) (u_int
) -1)
315 ACE_DEBUG ((LM_DEBUG
,
316 "(%i) Partial (running) mean %u usecs\n",
318 (ACE_UINT32
) (psum
/ (ACE_UINT32
) (1000 * 500))));
325 sample_mean
= ((double) ACE_U64_TO_U32 (sum
)) / (double) nsamples
;
329 ACE_OS::sprintf (sumfile
, ACE_TEXT("%s.sum"), datafile
);
330 ACE_OS::sprintf (distfile
, ACE_TEXT("%s.dist"), datafile
);
331 ACE_OS::sprintf (sampfile
, ACE_TEXT("%s.samp"), datafile
);
333 distfp
= ACE_OS::fopen(distfile
, ACE_TEXT("w"));
337 ACE_DEBUG ((LM_DEBUG
,
338 "Unable to open dist file!\n\n"));
341 if (logfile
&& (sampfp
= ACE_OS::fopen (sampfile
, ACE_TEXT("w"))) == 0)
343 ACE_OS::fclose (distfp
);
344 ACE_DEBUG ((LM_DEBUG
,
345 "Unable to open sample file!\n\n"));
348 if (logfile
&& (sumfp
= ACE_OS::fopen (sumfile
, ACE_TEXT("w"))) == 0)
350 ACE_OS::fclose (distfp
);
351 ACE_OS::fclose (sampfp
);
352 ACE_DEBUG ((LM_DEBUG
,
353 "Unable to open sample file!\n\n"));
358 window
= window
* 1000; // convert to nsec.
359 ndist
= (int)((max
-min
) / window
) + 1;
360 Dist
= (u_int
*) ACE_OS::calloc (ndist
,
363 for (i
= 0; i
< (ACE_INT32
) nsamples
; i
++)
365 std_dev
+= ((double) ACE_U64_TO_U32 (Samples
[i
]) - sample_mean
) *
366 ((double) ACE_U64_TO_U32 (Samples
[i
]) - sample_mean
);
367 d
= (int)((Samples
[i
] - min
)/window
);
369 if (d
< 0 || d
> ndist
)
371 ACE_DEBUG ((LM_DEBUG
,
372 "\nError indexing into dist array %d (%d)\n\n",
379 ACE_OS::fprintf (sampfp
,
381 ACE_U64_TO_U32 (Samples
[i
]));
387 tmp
= min
+ (window
/ 2);
389 for (i
= 0; i
< ndist
; i
++)
391 ACE_OS::fprintf (distfp
,
393 (ACE_UINT32
) (tmp
/ (ACE_UINT32
) 1000),
399 std_dev
= (double) sqrt (std_dev
/ (double) (nsamples
- 1.0));
400 std_err
= (double) std_dev
/ sqrt ((double) nsamples
);
402 ACE_DEBUG ((LM_DEBUG
,
403 "\nResults for %i samples (usec):\n"
404 "\tSample Mean = %f,\n"
405 "\tSample Max = %u, Max index = %d,\n"
406 "\tSample Min = %u, Min index = %d,\n"
407 "\tStandard Deviation = %f,\n"
408 "\tStandard Error = %f\n",
410 sample_mean
/ 1000.0,
411 (u_int
) (max
/ (ACE_UINT32
) 1000),
413 (u_int
) (min
/ (ACE_UINT32
) 1000),
420 ACE_OS::fprintf (sumfp
,
421 "Command executed:\n");
423 ACE_OS::fprintf (sumfp
,
425 ACE_TEXT_ALWAYS_CHAR (*cmd
));
426 ACE_OS::fprintf (sumfp
,
429 ACE_OS::fprintf (sumfp
,
430 "\nResults for %i samples (usec):"
431 "\tSample Mean = %f,\n"
432 "\tSample Max = %u, Max index = %d,\n"
433 "\tSample Min = %u, Min index = %d,\n"
434 "\tStandard Deviation = %f,\n"
435 "\tStandard Error = %f\n",
437 sample_mean
/ 1000.0,
438 (ACE_UINT32
) (max
/ (ACE_UINT32
) 1000),
440 (ACE_UINT32
) (min
/ (ACE_UINT32
) 1000),
450 Client::shutdown (void)
452 const char buf
= 'S';
453 const int n
= endpoint_
.send (&buf
, 1u, remote_addr_
);
457 if (ACE_Reactor::instance ()->remove_handler
458 (this, ACE_Event_Handler::READ_MASK
) == -1)
459 ACE_ERROR_RETURN ((LM_ERROR
,
460 "ACE_Reactor::remove_handler: Client\n"),
467 class Server
: public ACE_Event_Handler
470 Server (const ACE_INET_Addr
&addr
);
472 virtual ~Server (void);
474 // = Override <ACE_Event_Handler> methods.
475 virtual ACE_HANDLE
get_handle (void) const;
476 virtual int handle_input (ACE_HANDLE
);
477 virtual int handle_close (ACE_HANDLE handle
,
478 ACE_Reactor_Mask close_mask
);
481 /// Receives datagrams.
482 ACE_SOCK_Dgram endpoint_
;
484 ACE_UNIMPLEMENTED_FUNC (Server (void))
485 ACE_UNIMPLEMENTED_FUNC (Server (const Server
&))
486 ACE_UNIMPLEMENTED_FUNC (Server
&operator= (const Server
&))
489 Server::Server (const ACE_INET_Addr
&addr
)
494 if (ACE_Reactor::instance ()->register_handler
496 ACE_Event_Handler::READ_MASK
) == -1)
497 ACE_ERROR ((LM_ERROR
,
498 "ACE_Reactor::register_handler: Server\n"));
502 Server::~Server (void)
507 Server::get_handle (void) const
509 return endpoint_
.get_handle ();
513 Server::handle_input (ACE_HANDLE
)
516 ACE_INET_Addr from_addr
;
518 ssize_t n
= endpoint_
.recv (buf
, sizeof buf
, from_addr
);
521 ACE_DEBUG ((LM_ERROR
,
523 "handle_input: recv"));
525 // Send the message back as the response.
526 if (endpoint_
.send (buf
, n
, from_addr
) == n
)
528 if (n
== 1 && buf
[0] == 'S')
532 if (ACE_Reactor::instance ()->remove_handler
533 (this, ACE_Event_Handler::READ_MASK
) == -1)
534 ACE_ERROR_RETURN ((LM_ERROR
,
535 "ACE_Reactor::remove_handler: server\n"),
538 ACE_Reactor::end_event_loop ();
542 // Indicate done by returning 1.
551 ACE_DEBUG ((LM_ERROR
,
553 "handle_input: send"));
559 Server::handle_close (ACE_HANDLE
,
568 ACE_TMAIN (int argc
, ACE_TCHAR
*argv
[])
570 int c
, dstport
= DEFPORT
;
575 //FUZZ: disable check_for_lack_ACE_OS
576 ACE_Get_Opt
getopt (argc
, argv
, ACE_TEXT("x:w:f:vs:I:p:rtn:b:a"));
578 while ((c
= getopt ()) != -1)
580 //FUZZ: enable check_for_lack_ACE_OS
584 max_allow
= ACE_OS::atoi (getopt
.opt_arg ());
587 window
= ACE_OS::atoi (getopt
.opt_arg ());
589 ACE_ERROR_RETURN ((LM_ERROR
,
590 "Invalid window!\n\n"),
594 ACE_OS::strcpy (datafile
, getopt
.opt_arg ());
601 bufsz
= ACE_OS::atoi (getopt
.opt_arg ());
604 ACE_ERROR_RETURN ((LM_ERROR
,
605 "\nBuffer size must be greater than 0!\n\n"),
609 nsamples
= ACE_OS::atoi (getopt
.opt_arg ());
611 ACE_ERROR_RETURN ((LM_ERROR
,
612 "\nIterations must be greater than 0!\n\n"),
619 so_bufsz
= ACE_OS::atoi (getopt
.opt_arg ());
622 ACE_ERROR_RETURN ((LM_ERROR
,
623 "\nInvalid socket buffer size!\n\n"),
627 usdelay
= ACE_OS::atoi (getopt
.opt_arg ());
630 ACE_ERROR_RETURN ((LM_ERROR
,
631 "%s: bad usdelay: %s\n",
637 dstport
= ACE_OS::atoi (getopt
.opt_arg ());
639 ACE_ERROR_RETURN ((LM_ERROR
,
640 "\nInvalid port number!\n\n"),
657 if ((getopt
.opt_ind () >= argc
&& client
!= 0) || argc
== 1)
663 ACE_INET_Addr
addr (server
? dstport
: dstport
+ 1);
667 Server
server (addr
);
671 ACE_Reactor::run_event_loop ();
675 // Handle input in the current thread.
676 while (server
.handle_input (0) != 1)
684 if ((u_int
) bufsz
< sizeof (ACE_hrtime_t
))
685 ACE_ERROR_RETURN ((LM_ERROR
,
686 "\nbufsz must be >= %d\n",
687 sizeof (ACE_hrtime_t
)),
689 ACE_INET_Addr remote_addr
;
691 if (ACE_OS::ace_isdigit(argv
[getopt
.opt_ind ()][0]))
693 if (remote_addr
.set (dstport
,
694 (ACE_UINT32
) ACE_OS::inet_addr
695 (ACE_TEXT_ALWAYS_CHAR(argv
[getopt
.opt_ind ()]))) == -1)
696 ACE_ERROR_RETURN ((LM_ERROR
,
697 "invalid IP address: %s\n",
698 argv
[getopt
.opt_ind ()]),
703 if (remote_addr
.set (dstport
, argv
[getopt
.opt_ind ()]) == -1)
704 ACE_ERROR_RETURN ((LM_ERROR
,
705 "invalid IP address: %s\n",
706 argv
[getopt
.opt_ind ()]),
711 Client
client (addr
, remote_addr
);
713 ACE_DEBUG ((LM_DEBUG
,
714 "\nSending %d byte packets to %s:%d "
715 "with so_bufsz = %d\n\n",
717 addr
.get_host_name (),