2 Data source for network testing.
4 Copyright (c) 2011-2012, Intel Corporation. All rights reserved.
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/DebugLib.h>
14 #include <Library/PcdLib.h>
15 #include <Library/UefiBootServicesTableLib.h>
16 #include <Library/UefiLib.h>
18 #include <netinet/in.h>
20 #include <sys/EfiSysCall.h>
22 #include <sys/socket.h>
25 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
26 #define MAX_CONNECTIONS ( 1 + 16 ) ///< Maximum number of client connections
27 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
28 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
29 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
30 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
32 #define TPL_DATASINK TPL_CALLBACK ///< Synchronization TPL
34 #define PACKET_SIZE 1448 ///< Size of data packets
35 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
37 typedef struct _DT_PORT
{
39 struct sockaddr_in6 IpAddress
;
42 UINT64 BytesReceived
[ DATA_SAMPLES
];
45 volatile BOOLEAN bTick
;
46 BOOLEAN bTimerRunning
;
47 struct sockaddr_in6 LocalAddress
;
50 UINT8 Buffer
[ DATA_BUFFER_SIZE
];
51 struct pollfd PollFd
[ MAX_CONNECTIONS
];
52 DT_PORT Port
[ MAX_CONNECTIONS
];
57 // Forward routine declarations
59 EFI_STATUS
TimerStart ( UINTN Milliseconds
);
63 Check for control C entered at console
65 @retval EFI_SUCCESS Control C not entered
66 @retval EFI_ABORTED Control C entered
75 // Assume no user intervention
80 // Display user stop request
82 if ( EFI_ERROR ( Status
)) {
84 "User stop request!\r\n" ));
88 // Return the check status
95 Accept a socket connection
97 @retval EFI_SUCCESS The application is running normally
98 @retval EFI_NOT_STARTED Error with the listen socket
99 @retval Other The user stopped the application
112 Status
= EFI_DEVICE_ERROR
;
115 // Bind to the local address
117 SocketStatus
= bind ( ListenSocket
,
118 (struct sockaddr
*) &LocalAddress
,
119 LocalAddress
.sin6_len
);
120 if ( 0 == SocketStatus
) {
122 // Start listening on the local socket
124 SocketStatus
= listen ( ListenSocket
, 5 );
125 if ( 0 == SocketStatus
) {
127 // Local socket in the listen state
129 Status
= EFI_SUCCESS
;
135 PollFd
[ Index
].fd
= ListenSocket
;
136 PollFd
[ Index
].events
= POLLRDNORM
| POLLHUP
;
137 PollFd
[ Index
].revents
= 0;
138 ZeroMem ( &Port
[ Index
], sizeof ( Port
[ Index
]));
143 // Return the operation status
152 @retval EFI_SUCCESS The application is running normally
153 @retval Other The user stopped the application
163 // Determine if the socket is open
165 Status
= EFI_DEVICE_ERROR
;
166 if ( -1 != ListenSocket
) {
168 // Attempt to close the socket
170 CloseStatus
= close ( ListenSocket
);
171 if ( 0 == CloseStatus
) {
173 "0x%08x: Socket closed\r\n",
176 Status
= EFI_SUCCESS
;
179 DEBUG (( DEBUG_ERROR
,
180 "ERROR: Failed to close socket, errno: %d\r\n",
186 // Return the operation status
195 @param [in] Family Network family, AF_INET or AF_INET6
197 @retval EFI_SUCCESS The application is running normally
198 @retval Other The user stopped the application
208 // Get the port number
210 ZeroMem ( &LocalAddress
, sizeof ( LocalAddress
));
211 LocalAddress
.sin6_len
= sizeof ( LocalAddress
);
212 LocalAddress
.sin6_family
= Family
;
213 LocalAddress
.sin6_port
= htons ( PcdGet16 ( DataSource_Port
));
216 // Loop creating the socket
219 "Creating the socket\r\n" ));
222 // Check for user stop request
224 Status
= ControlCCheck ( );
225 if ( !EFI_ERROR ( Status
)) {
227 // Attempt to create the socket
229 ListenSocket
= socket ( LocalAddress
.sin6_family
,
232 if ( -1 != ListenSocket
) {
234 "0x%08x: Socket created\r\n",
238 Status
= EFI_NOT_STARTED
;
243 // Return the operation status
250 Poll the socket for more work
252 @retval EFI_SUCCESS The application is running normally
253 @retval EFI_NOT_STARTED Listen socket error
254 @retval Other The user stopped the application
260 BOOLEAN bRemoveSocket
;
261 BOOLEAN bListenError
;
262 size_t BytesReceived
;
268 socklen_t LengthInBytes
;
269 struct sockaddr_in
* pPortIpAddress4
;
270 struct sockaddr_in6
* pPortIpAddress6
;
271 struct sockaddr_in
* pRemoteAddress4
;
272 struct sockaddr_in6
* pRemoteAddress6
;
273 struct sockaddr_in6 RemoteAddress
;
279 // Check for control-C
281 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteAddress
;
282 pRemoteAddress6
= (struct sockaddr_in6
*)&RemoteAddress
;
283 bListenError
= FALSE
;
284 Status
= ControlCCheck ( );
285 if ( !EFI_ERROR ( Status
)) {
289 FdCount
= poll ( &PollFd
[0],
292 if ( -1 == FdCount
) {
296 DEBUG (( DEBUG_ERROR
,
297 "ERROR - Poll error, errno: %d\r\n",
299 Status
= EFI_DEVICE_ERROR
;
303 // Process the poll output
307 bRemoveSocket
= FALSE
;
310 // Account for this descriptor
312 pPortIpAddress4
= (struct sockaddr_in
*)&Port
[ Index
].IpAddress
;
313 pPortIpAddress6
= (struct sockaddr_in6
*)&Port
[ Index
].IpAddress
;
314 if ( 0 != PollFd
[ Index
].revents
) {
319 // Check for a broken connection
321 if ( 0 != ( PollFd
[ Index
].revents
& POLLHUP
)) {
322 bRemoveSocket
= TRUE
;
323 if ( ListenSocket
== PollFd
[ Index
].fd
) {
325 DEBUG (( DEBUG_ERROR
,
326 "ERROR - Network closed on listen socket, errno: %d\r\n",
330 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
331 DEBUG (( DEBUG_ERROR
,
332 "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n",
333 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
334 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
335 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
336 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
337 ntohs ( pPortIpAddress4
->sin_port
),
341 DEBUG (( DEBUG_ERROR
,
342 "ERROR - Network closed on socket [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
343 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
344 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
345 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
346 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
347 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
348 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
349 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
350 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
351 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
352 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
353 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
354 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
355 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
356 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
357 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
358 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
359 ntohs ( pPortIpAddress6
->sin6_port
),
366 CloseStatus
= close ( PollFd
[ Index
].fd
);
367 if ( 0 == CloseStatus
) {
368 bRemoveSocket
= TRUE
;
369 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
371 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
373 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
374 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
375 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
376 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
377 ntohs ( pPortIpAddress4
->sin_port
)));
381 "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
383 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
384 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
385 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
386 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
387 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
388 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
389 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
390 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
391 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
392 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
393 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
394 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
395 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
396 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
397 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
398 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
399 ntohs ( pPortIpAddress6
->sin6_port
)));
403 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
404 DEBUG (( DEBUG_ERROR
,
405 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
407 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
408 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
409 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
410 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
411 ntohs ( pPortIpAddress4
->sin_port
),
415 DEBUG (( DEBUG_ERROR
,
416 "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
418 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
419 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
420 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
421 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
422 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
423 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
424 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
425 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
426 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
427 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
428 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
429 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
430 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
431 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
432 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
433 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
434 ntohs ( pPortIpAddress6
->sin6_port
),
442 // Check for a connection or read data
444 if ( 0 != ( PollFd
[ Index
].revents
& POLLRDNORM
)) {
446 // Check for a connection
448 if ( ListenSocket
== PollFd
[ Index
].fd
) {
450 // Another client connection was received
452 LengthInBytes
= sizeof ( RemoteAddress
);
453 Socket
= accept ( ListenSocket
,
454 (struct sockaddr
*) &RemoteAddress
,
456 if ( -1 == Socket
) {
458 // Listen socket error
461 bRemoveSocket
= TRUE
;
462 DEBUG (( DEBUG_ERROR
,
463 "ERROR - Listen socket failure, errno: %d\r\n",
468 // Determine if there is room for this connection
470 if (( MAX_CONNECTIONS
<= MaxPort
)
471 || ((( MAX_CONNECTIONS
- 1 ) == MaxPort
) && ( -1 == ListenSocket
))) {
473 // Display the connection
475 if ( AF_INET
== pRemoteAddress4
->sin_family
) {
476 Print ( L
"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n",
477 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
478 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
479 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
480 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
481 ntohs ( pRemoteAddress4
->sin_port
));
484 Print ( L
"Rejecting connection to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
485 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
486 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
487 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
488 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
489 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
490 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
491 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
492 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
493 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
494 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
495 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
496 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
497 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
498 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
499 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
500 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
501 ntohs ( pRemoteAddress6
->sin6_port
));
505 // No room for this connection
506 // Close the connection
508 CloseStatus
= close ( Socket
);
509 if ( 0 == CloseStatus
) {
510 bRemoveSocket
= TRUE
;
511 if ( AF_INET
== pRemoteAddress4
->sin_family
) {
513 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
515 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
516 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
517 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
518 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
519 ntohs ( pRemoteAddress4
->sin_port
)));
523 "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
525 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
526 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
527 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
528 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
529 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
530 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
531 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
532 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
533 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
534 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
535 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
536 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
537 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
538 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
539 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
540 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
541 ntohs ( pRemoteAddress6
->sin6_port
)));
545 DEBUG (( DEBUG_ERROR
,
546 "ERROR - Failed to close socket 0x%08x, errno: %d\r\n",
552 // Keep the application running
553 // No issue with the listen socket
555 Status
= EFI_SUCCESS
;
559 // Display the connection
561 if ( AF_INET
== pRemoteAddress4
->sin_family
) {
562 Print ( L
"Connected to remote system %d.%d.%d.%d:%d\r\n",
563 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
564 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
565 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
566 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
567 ntohs ( pRemoteAddress4
->sin_port
));
570 Print ( L
"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
571 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
572 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
573 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
574 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
575 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
576 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
577 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
578 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
579 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
580 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
581 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
582 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
583 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
584 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
585 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
586 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
587 ntohs ( pRemoteAddress6
->sin6_port
));
591 // Allocate the client connection
594 ZeroMem ( &Port
[ Index
], sizeof ( Port
[ Index
]));
595 CopyMem ( pPortIpAddress6
, pRemoteAddress6
, sizeof ( *pRemoteAddress6
));
596 PollFd
[ Index
].fd
= Socket
;
597 PollFd
[ Index
].events
= POLLRDNORM
| POLLHUP
;
598 PollFd
[ Index
].revents
= 0;
606 BytesReceived
= read ( PollFd
[ Index
].fd
,
609 if ( 0 < BytesReceived
) {
611 // Display the amount of data received
613 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
615 "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n",
618 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
619 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
620 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
621 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
622 ntohs ( pPortIpAddress4
->sin_port
)));
626 "0x%08x: Socket received 0x%08x bytes from [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
629 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
630 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
631 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
632 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
633 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
634 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
635 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
636 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
637 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
638 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
639 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
640 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
641 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
642 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
643 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
644 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
645 ntohs ( pPortIpAddress6
->sin6_port
)));
649 // Synchronize with the TimerCallback routine
651 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASINK
);
654 // Account for the data received
656 Port
[ Index
].BytesTotal
+= BytesReceived
;
659 // Release the synchronization with the TimerCallback routine
661 gBS
->RestoreTPL ( TplPrevious
);
663 else if ( -1 == BytesReceived
) {
667 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
669 "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n",
670 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
671 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
672 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
673 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
674 ntohs ( pPortIpAddress4
->sin_port
),
679 "ERROR - Receive failure for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
680 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
681 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
682 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
683 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
684 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
685 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
686 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
687 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
688 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
689 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
690 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
691 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
692 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
693 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
694 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
695 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
696 ntohs ( pPortIpAddress6
->sin6_port
),
699 CloseStatus
= close ( PollFd
[ Index
].fd
);
700 if ( 0 == CloseStatus
) {
701 bRemoveSocket
= TRUE
;
702 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
704 "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n",
706 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
707 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
708 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
709 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
710 ntohs ( pPortIpAddress4
->sin_port
)));
714 "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
716 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
717 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
718 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
719 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
720 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
721 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
722 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
723 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
724 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
725 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
726 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
727 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
728 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
729 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
730 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
731 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
732 ntohs ( pPortIpAddress6
->sin6_port
)));
736 if ( AF_INET
== pPortIpAddress4
->sin_family
) {
737 DEBUG (( DEBUG_ERROR
,
738 "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n",
740 pPortIpAddress4
->sin_addr
.s_addr
& 0xff,
741 ( pPortIpAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
742 ( pPortIpAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
743 ( pPortIpAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
744 ntohs ( pPortIpAddress4
->sin_port
),
748 DEBUG (( DEBUG_ERROR
,
749 "ERROR - Failed to close socket 0x%08x for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d, errno: %d\r\n",
751 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
752 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
753 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
754 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
755 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
756 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
757 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
758 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
759 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
760 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
761 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
762 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
763 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
764 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
765 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
766 pPortIpAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
767 ntohs ( pPortIpAddress6
->sin6_port
),
774 // Keep the application running
775 // No issue with the listen socket
777 Status
= EFI_SUCCESS
;
782 // Remove the socket if necessary
784 if ( bRemoveSocket
) {
786 "0x%08x: Socket removed from polling\r\n",
787 PollFd
[ Index
].fd
));
789 for ( Entry
= Index
+ 1; MaxPort
>= Entry
; Entry
++ ) {
790 EntryPrevious
= Entry
;
791 CopyMem ( &Port
[ EntryPrevious
],
793 sizeof ( Port
[ Entry
]));
794 PollFd
[ EntryPrevious
].events
= PollFd
[ Entry
].events
;
795 PollFd
[ EntryPrevious
].fd
= PollFd
[ Entry
].fd
;
796 PollFd
[ EntryPrevious
].revents
= PollFd
[ Entry
].revents
;
798 PollFd
[ MaxPort
].fd
= -1;
803 // Account for this socket
811 // Return the listen failure if necessary
813 if (( !EFI_ERROR ( Status
)) && bListenError
) {
814 Status
= EFI_NOT_STARTED
;
818 // Return the poll status
825 Handle the timer callback
827 @param [in] Event Event that caused this callback
828 @param [in] pContext Context for this routine
838 UINT64 BitsPerSecond
;
839 UINT64 BytesReceived
;
845 // Notify the other code of the timer tick
850 // Walk the list of ports
852 for ( Index
= 0; MaxPort
> Index
; Index
++ ) {
854 // Determine if any data was received
856 BytesReceived
= Port
[ Index
].BytesTotal
;
857 if (( ListenSocket
!= PollFd
[ Index
].fd
)
858 && ( 0 != BytesReceived
)) {
860 // Update the received data samples
862 Port
[ Index
].BytesTotal
= 0;
863 Port
[ Index
].BytesReceived
[ Port
[ Index
].In
] = BytesReceived
;
864 Port
[ Index
].In
+= 1;
865 if ( DATA_SAMPLES
<= Port
[ Index
].In
) {
866 Port
[ Index
].In
= 0;
870 // Separate the samples
872 if ( DATA_SAMPLES
== Port
[ Index
].Samples
) {
873 Print ( L
"---------- Stable average ----------\r\n" );
875 Port
[ Index
].Samples
+= 1;
878 // Compute the data rate
881 for ( Count
= 0; DATA_SAMPLES
> Count
; Count
++ )
883 TotalBytes
+= Port
[ Index
].BytesReceived
[ Count
];
885 Average
= (UINT32
)RShiftU64 ( TotalBytes
, DATA_SAMPLE_SHIFT
);
886 BitsPerSecond
= Average
* 8;
889 // Display the data rate
891 if (( RANGE_SWITCH
>> 10 ) > Average
) {
892 Print ( L
"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
897 BitsPerSecond
/= 1000;
898 if ( RANGE_SWITCH
> Average
) {
899 Print ( L
"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
901 (( Average
& 0x3ff ) * 1000 ) >> 10,
905 BitsPerSecond
/= 1000;
907 if ( RANGE_SWITCH
> Average
) {
908 Print ( L
"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
910 (( Average
& 0x3ff ) * 1000 ) >> 10,
914 BitsPerSecond
/= 1000;
916 if ( RANGE_SWITCH
> Average
) {
917 Print ( L
"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
919 (( Average
& 0x3ff ) * 1000 ) >> 10,
923 BitsPerSecond
/= 1000;
925 if ( RANGE_SWITCH
> Average
) {
926 Print ( L
"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
928 (( Average
& 0x3ff ) * 1000 ) >> 10,
932 BitsPerSecond
/= 1000;
934 Print ( L
"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
936 (( Average
& 0x3ff ) * 1000 ) >> 10,
951 @retval EFI_SUCCESS The timer was successfully created
952 @retval Other Timer initialization failed
963 Status
= gBS
->CreateEvent ( EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
968 if ( EFI_ERROR ( Status
)) {
969 DEBUG (( DEBUG_ERROR
,
970 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
975 "0x%08x: Timer created\r\n",
980 // Return the operation status
989 @retval EFI_SUCCESS The timer was stopped successfully
990 @retval Other The timer failed to stop
1001 Status
= EFI_SUCCESS
;
1004 // Determine if the timer is running
1006 if ( bTimerRunning
) {
1010 Status
= gBS
->SetTimer ( pTimer
,
1013 if ( EFI_ERROR ( Status
)) {
1014 DEBUG (( DEBUG_ERROR
,
1015 "ERROR - Failed to stop the timer, Status: %r\r\n",
1020 // Timer timer is now stopped
1022 bTimerRunning
= FALSE
;
1023 DEBUG (( DEBUG_INFO
,
1024 "0x%08x: Timer stopped\r\n",
1030 // Return the operation status
1039 @param [in] Milliseconds The number of milliseconds between timer callbacks
1041 @retval EFI_SUCCESS The timer was successfully created
1042 @retval Other Timer initialization failed
1053 // Stop the timer if necessary
1055 Status
= EFI_SUCCESS
;
1056 if ( bTimerRunning
) {
1057 Status
= TimerStop ( );
1059 if ( !EFI_ERROR ( Status
)) {
1061 // Compute the new delay
1063 TimeDelay
= Milliseconds
;
1064 TimeDelay
*= 1000 * 10;
1069 Status
= gBS
->SetTimer ( pTimer
,
1072 if ( EFI_ERROR ( Status
)) {
1073 DEBUG (( DEBUG_ERROR
,
1074 "ERROR - Failed to start the timer, Status: %r\r\n",
1079 // The timer is now running
1081 bTimerRunning
= TRUE
;
1082 DEBUG (( DEBUG_INFO
,
1083 "0x%08x: Timer running\r\n",
1089 // Return the operation status
1098 @retval EFI_SUCCESS The timer was destroyed successfully
1099 @retval Other Failed to destroy the timer
1110 Status
= EFI_SUCCESS
;
1113 // Determine if the timer is running
1115 if ( bTimerRunning
) {
1119 Status
= TimerStop ( );
1121 if (( !EFI_ERROR ( Status
)) && ( NULL
!= pTimer
)) {
1123 // Done with this timer
1125 Status
= gBS
->CloseEvent ( pTimer
);
1126 if ( EFI_ERROR ( Status
)) {
1127 DEBUG (( DEBUG_ERROR
,
1128 "ERROR - Failed to free the timer event, Status: %r\r\n",
1132 DEBUG (( DEBUG_INFO
,
1133 "0x%08x: Timer Destroyed\r\n",
1140 // Return the operation status
1147 Receive data from the DataSource program to test a network's bandwidth.
1149 @param [in] Argc The number of arguments
1150 @param [in] Argv The argument value array
1152 @retval 0 The application exited normally.
1153 @retval Other An error occurred.
1164 DEBUG (( DEBUG_INFO
,
1165 "DataSink starting\r\n" ));
1168 // Determine the family to use
1170 Family
= ( 1 < Argc
) ? AF_INET6
: AF_INET
;
1173 // Use for/break instead of goto
1180 Status
= TimerCreate ( );
1181 if ( EFI_ERROR ( Status
)) {
1186 // Start a timer to perform network polling and display updates
1188 Status
= TimerStart ( 1 * 1000 );
1189 if ( EFI_ERROR ( Status
)) {
1194 // Loop forever waiting for abuse
1200 // Complete any client operations
1202 Status
= SocketPoll ( );
1203 if ( EFI_ERROR ( Status
)) {
1214 if ( EFI_ERROR ( Status
)) {
1222 // Wait for the network layer to initialize
1224 Status
= SocketNew ( Family
);
1225 if ( EFI_ERROR ( Status
)) {
1230 // Wait for the remote network application to start
1232 Status
= SocketAccept ( );
1233 if ( EFI_NOT_STARTED
== Status
) {
1234 Status
= SocketClose ( );
1237 else if ( EFI_SUCCESS
!= Status
) {
1245 // Receive data until the connection breaks
1248 Status
= SocketPoll ( );
1249 } while ( !EFI_ERROR ( Status
));
1252 // Done with the socket
1254 Status
= SocketClose ( );
1255 } while ( !EFI_ERROR ( Status
));
1258 // Close the socket if necessary
1269 // Stop the timer if necessary
1275 // Return the operation status
1277 DEBUG (( DEBUG_INFO
,
1278 "DataSink exiting, Status: %r\r\n",