2 Data source for network testing.
4 Copyright (c) 2011-2012, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/DebugLib.h>
20 #include <Library/PcdLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/UefiLib.h>
24 #include <netinet/in.h>
26 #include <Protocol/ServiceBinding.h>
27 #include <Protocol/Tcp4.h>
29 #include <sys/EfiSysCall.h>
31 #include <sys/socket.h>
37 #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples
38 #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges
39 #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates
40 #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average
41 #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples
43 #define TPL_DATASOURCE TPL_CALLBACK ///< Synchronization TPL
45 #define PACKET_SIZE 1448 ///< Size of data packets
46 #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes
57 BOOLEAN bTcp4
; ///< TRUE if TCP4 is being used
58 BOOLEAN bTcp4Connected
; ///< TRUE if connected to remote system
59 BOOLEAN bTcp4Connecting
; ///< TRUE while connection in progress
60 UINTN Tcp4Index
; ///< Index into handle array
61 EFI_HANDLE Tcp4Controller
; ///< Network controller handle
62 EFI_HANDLE Tcp4Handle
; ///< TCP4 port handle
63 EFI_TCP4_PROTOCOL
* pTcp4Protocol
; ///< TCP4 protocol pointer
64 EFI_SERVICE_BINDING_PROTOCOL
* pTcp4Service
; ///< TCP4 Service binding
65 EFI_TCP4_CONFIG_DATA Tcp4ConfigData
;///< TCP4 configuration data
66 EFI_TCP4_OPTION Tcp4Option
; ///< TCP4 port options
67 EFI_TCP4_CLOSE_TOKEN Tcp4CloseToken
;///< Close control
68 EFI_TCP4_CONNECTION_TOKEN Tcp4ConnectToken
; ///< Connection control
69 EFI_TCP4_LISTEN_TOKEN Tcp4ListenToken
; ///< Listen control
70 EFI_TCP4_IO_TOKEN Tcp4TxToken
; ///< Normal data token
75 volatile BOOLEAN bTick
;
76 BOOLEAN bTimerRunning
;
80 // Remote IP Address Data
82 struct sockaddr_in6 RemoteHostAddress
;
88 UINT64 TotalBytesSent
;
91 UINT64 BytesSent
[ DATA_SAMPLES
];
92 UINT8 Buffer
[ DATA_BUFFER_SIZE
];
96 // Forward routine declarations
98 EFI_STATUS
TimerStart ( UINTN Milliseconds
);
102 Check for control C entered at console
104 @retval EFI_SUCCESS Control C not entered
105 @retval EFI_ABORTED Control C entered
114 // Assume no user intervention
116 Status
= EFI_SUCCESS
;
119 // Display user stop request
121 if ( EFI_ERROR ( Status
)) {
123 "User stop request!\r\n" ));
127 // Return the check status
136 @param [in] pDigit The address of the next digit
137 @param [out] pValue The address to receive the value
139 @return Returns the address of the separator
154 while (( '0' <= *pDigit
) && ( '9' >= *pDigit
)) {
156 // Make room for the new least significant digit
161 // Convert the digit from ASCII to binary
163 Value
+= *pDigit
- '0';
166 // Set the next digit
177 // Return the next separator
186 @retval EFI_SUCCESS The IP address is valid
187 @retval Other Failure to convert the IP address
193 struct sockaddr_in
* pRemoteAddress4
;
194 struct sockaddr_in6
* pRemoteAddress6
;
195 UINT32 RemoteAddress
;
209 Status
= EFI_INVALID_PARAMETER
;
212 // Get the port number
214 ZeroMem ( &RemoteHostAddress
, sizeof ( RemoteHostAddress
));
215 RemoteHostAddress
.sin6_port
= htons ( PcdGet16 ( DataSource_Port
));
216 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
217 pRemoteAddress6
= &RemoteHostAddress
;
220 // Convert the IP address from a string to a numeric value
222 if (( 4 == sscanf ( pRemoteHost
,
231 && ( 255 >= Value4
)) {
233 // Build the IPv4 address
235 pRemoteAddress4
->sin_len
= sizeof ( *pRemoteAddress4
);
236 pRemoteAddress4
->sin_family
= AF_INET
;
237 RemoteAddress
= Value1
241 pRemoteAddress4
->sin_addr
.s_addr
= RemoteAddress
;
242 Status
= EFI_SUCCESS
;
245 // Display the IP address
248 "%d.%d.%d.%d: Remote host IP address\r\n",
254 else if (( 8 == sscanf ( pRemoteHost
,
255 "%x:%x:%x:%x:%x:%x:%x:%x",
264 && ( 0xffff >= Value1
)
265 && ( 0xffff >= Value2
)
266 && ( 0xffff >= Value3
)
267 && ( 0xffff >= Value4
)
268 && ( 0xffff >= Value5
)
269 && ( 0xffff >= Value6
)
270 && ( 0xffff >= Value7
)
271 && ( 0xffff >= Value8
)) {
273 // Build the IPv6 address
275 pRemoteAddress6
->sin6_len
= sizeof ( *pRemoteAddress6
);
276 pRemoteAddress6
->sin6_family
= AF_INET6
;
277 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ] = (UINT8
)( Value1
>> 8 );
278 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ] = (UINT8
)Value1
;
279 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ] = (UINT8
)( Value2
>> 8 );
280 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ] = (UINT8
)Value2
;
281 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ] = (UINT8
)( Value3
>> 8 );
282 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ] = (UINT8
)Value3
;
283 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ] = (UINT8
)( Value4
>> 8 );
284 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ] = (UINT8
)Value4
;
285 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ] = (UINT8
)( Value5
>> 8 );
286 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ] = (UINT8
)Value5
;
287 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ] = (UINT8
)( Value6
>> 8 );
288 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ] = (UINT8
)Value6
;
289 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ] = (UINT8
)( Value7
>> 8 );
290 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ] = (UINT8
)Value7
;
291 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ] = (UINT8
)( Value8
>> 8 );
292 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ] = (UINT8
)Value8
;
293 Status
= EFI_SUCCESS
;
296 // Display the IP address
299 "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]: Remote host IP address\r\n",
310 Print ( L
"ERROR - Invalid IP address!\r\n" );
314 // Return the operation status
323 @retval EFI_SUCCESS The application is running normally
324 @retval Other The user stopped the application
334 // Determine if the socket is open
336 Status
= EFI_DEVICE_ERROR
;
337 if ( -1 != Socket
) {
339 // Attempt to close the socket
341 CloseStatus
= close ( Socket
);
342 if ( 0 == CloseStatus
) {
344 "0x%08x: Socket closed\r\n",
347 Status
= EFI_SUCCESS
;
350 DEBUG (( DEBUG_ERROR
,
351 "ERROR: Failed to close socket, errno: %d\r\n",
357 // Return the operation status
366 @retval EFI_SUCCESS The application is running normally
367 @retval Other The user stopped the application
374 struct sockaddr_in
* pRemoteAddress4
;
375 struct sockaddr_in6
* pRemoteAddress6
;
379 // Display the connecting message
381 pRemoteAddress4
= (struct sockaddr_in
*)&RemoteHostAddress
;
382 pRemoteAddress6
= &RemoteHostAddress
;
383 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
384 Print ( L
"Connecting to remote system %d.%d.%d.%d:%d\r\n",
385 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
386 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
387 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
388 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
389 ntohs ( pRemoteAddress4
->sin_port
));
392 Print ( L
"Connecting to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
393 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
394 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
395 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
396 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
397 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
398 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
399 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
400 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
401 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
402 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
403 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
404 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
405 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
406 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
407 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
408 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
409 ntohs ( pRemoteAddress6
->sin6_port
));
413 // Connect to the remote system
415 Status
= EFI_SUCCESS
;
418 // Check for user stop request
421 Status
= ControlCCheck ( );
422 if ( EFI_ERROR ( Status
)) {
427 if ( EFI_ERROR ( Status
)) {
432 // Connect to the remote system
434 ConnectStatus
= connect ( Socket
,
435 (struct sockaddr
*)pRemoteAddress6
,
436 pRemoteAddress6
->sin6_len
);
437 if ( -1 != ConnectStatus
) {
438 if ( AF_INET
== pRemoteAddress6
->sin6_family
) {
439 Print ( L
"Connected to remote system %d.%d.%d.%d:%d\r\n",
440 pRemoteAddress4
->sin_addr
.s_addr
& 0xff,
441 ( pRemoteAddress4
->sin_addr
.s_addr
>> 8 ) & 0xff,
442 ( pRemoteAddress4
->sin_addr
.s_addr
>> 16 ) & 0xff,
443 ( pRemoteAddress4
->sin_addr
.s_addr
>> 24 ) & 0xff,
444 ntohs ( pRemoteAddress4
->sin_port
));
447 Print ( L
"Connected to remote system [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
448 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 0 ],
449 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 1 ],
450 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 2 ],
451 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 3 ],
452 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 4 ],
453 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 5 ],
454 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 6 ],
455 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 7 ],
456 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 8 ],
457 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 9 ],
458 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 10 ],
459 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 11 ],
460 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 12 ],
461 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 13 ],
462 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 14 ],
463 pRemoteAddress6
->sin6_addr
.__u6_addr
.__u6_addr8
[ 15 ],
464 ntohs ( pRemoteAddress6
->sin6_port
));
466 Print ( L
"ConnectStatus: %d, Status: %r\r\n", ConnectStatus
, Status
);
470 // Close the socket and try again
472 if ( EAGAIN
!= errno
) {
473 Status
= EFI_NOT_STARTED
;
477 } while ( -1 == ConnectStatus
);
480 // Return the operation status
482 Print ( L
"SocketConnect returning Status: %r\r\n", Status
);
490 @param [in] Family Network family, AF_INET or AF_INET6
492 @retval EFI_SUCCESS The application is running normally
493 @retval Other The user stopped the application
503 // Loop creating the socket
506 "Creating the socket\r\n" ));
509 // Check for user stop request
511 Status
= ControlCCheck ( );
512 if ( EFI_ERROR ( Status
)) {
517 // Attempt to create the socket
519 Socket
= socket ( Family
,
522 if ( -1 != Socket
) {
524 "0x%08x: Socket created\r\n",
528 } while ( -1 == Socket
);
531 // Return the operation status
538 Send data over the socket
540 @retval EFI_SUCCESS The application is running normally
541 @retval Other The user stopped the application
554 TimerStart ( 1 * 1000 );
557 // Loop until the connection breaks or the user stops
561 // Check for user stop request
563 Status
= ControlCCheck ( );
564 if ( EFI_ERROR ( Status
)) {
571 BytesSent
= write ( Socket
, &Buffer
[0], sizeof ( Buffer
));
572 if ( -1 == BytesSent
) {
574 "ERROR: send failed, errno: %d\r\n",
576 Print ( L
"ERROR: send failed, errno: %d\r\n", errno
);
581 Status
= EFI_SUCCESS
;
586 Status
= EFI_NOT_STARTED
;
591 // Synchronize with the TimerCallback routine
593 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
596 // Account for the data sent
598 TotalBytesSent
+= BytesSent
;
601 // Release the TimerCallback routine synchronization
603 gBS
->RestoreTPL ( TplPrevious
);
604 } while ( !EFI_ERROR ( Status
));
607 // Return the operation status
614 Open the network connection and send the data.
616 @retval EFI_SUCCESS Continue looping
617 @retval other Stopped by user's Control-C input
627 // Use do/while and break instead of goto
631 // Wait for the network layer to initialize
633 Status
= SocketNew ( RemoteHostAddress
.sin6_family
);
634 if ( EFI_ERROR ( Status
)) {
639 // Wait for the remote network application to start
641 Status
= SocketConnect ( );
642 Print ( L
"Status: %r\r\n", Status
);
643 if ( EFI_NOT_STARTED
== Status
) {
644 Status
= SocketClose ( );
647 else if ( EFI_SUCCESS
!= Status
) {
655 // Send data until the connection breaks
657 Status
= SocketSend ( );
658 if ( EFI_ERROR ( Status
)) {
664 // Return the operation status
666 Print ( L
"Returning Status: %r\r\n", Status
);
672 Close the TCP connection
674 @retval EFI_SUCCESS The application is running normally
675 @retval Other The user stopped the application
688 if ( bTcp4Connected
) {
689 Tcp4CloseToken
.AbortOnClose
= TRUE
;
690 Status
= pTcp4Protocol
->Close ( pTcp4Protocol
,
692 if ( EFI_ERROR ( Status
)) {
693 DEBUG (( DEBUG_ERROR
,
694 "ERROR - Failed to start the TCP port close, Status: %r\r\n",
698 Status
= gBS
->WaitForEvent ( 1,
699 &Tcp4CloseToken
.CompletionToken
.Event
,
701 if ( EFI_ERROR ( Status
)) {
702 DEBUG (( DEBUG_ERROR
,
703 "ERROR - Failed to wait for close event, Status: %r\r\n",
707 Status
= Tcp4CloseToken
.CompletionToken
.Status
;
708 if ( EFI_ERROR ( Status
)) {
709 DEBUG (( DEBUG_ERROR
,
710 "ERROR - Failed to close the TCP port, Status: %r\r\n",
715 "0x%08x: TCP port closed\r\n",
717 bTcp4Connected
= FALSE
;
720 // Display the port closed message
722 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
723 Print ( L
"Closed connection to %d.%d.%d.%d:%d\r\n",
728 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
735 // Release the events
737 if ( NULL
!= Tcp4TxToken
.CompletionToken
.Event
) {
738 Status
= gBS
->CloseEvent ( Tcp4TxToken
.CompletionToken
.Event
);
739 if ( !EFI_ERROR ( Status
)) {
741 "0x%08x: TX event closed\r\n",
742 Tcp4TxToken
.CompletionToken
.Event
));
743 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
746 DEBUG (( DEBUG_ERROR
,
747 "ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
752 if ( NULL
!= Tcp4ListenToken
.CompletionToken
.Event
) {
753 Status
= gBS
->CloseEvent ( Tcp4ListenToken
.CompletionToken
.Event
);
754 if ( !EFI_ERROR ( Status
)) {
756 "0x%08x: Listen event closed\r\n",
757 Tcp4ListenToken
.CompletionToken
.Event
));
758 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
761 DEBUG (( DEBUG_ERROR
,
762 "ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
767 if ( NULL
!= Tcp4ConnectToken
.CompletionToken
.Event
) {
768 Status
= gBS
->CloseEvent ( Tcp4ConnectToken
.CompletionToken
.Event
);
769 if ( !EFI_ERROR ( Status
)) {
771 "0x%08x: Connect event closed\r\n",
772 Tcp4ConnectToken
.CompletionToken
.Event
));
773 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
776 DEBUG (( DEBUG_ERROR
,
777 "ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
782 if ( NULL
!= Tcp4CloseToken
.CompletionToken
.Event
) {
783 Status
= gBS
->CloseEvent ( Tcp4CloseToken
.CompletionToken
.Event
);
784 if ( !EFI_ERROR ( Status
)) {
786 "0x%08x: Close event closed\r\n",
787 Tcp4CloseToken
.CompletionToken
.Event
));
788 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
791 DEBUG (( DEBUG_ERROR
,
792 "ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
798 // Close the TCP protocol
800 if ( NULL
!= pTcp4Protocol
) {
801 Status
= gBS
->CloseProtocol ( Tcp4Handle
,
802 &gEfiTcp4ProtocolGuid
,
805 if ( EFI_ERROR ( Status
)) {
806 DEBUG (( DEBUG_ERROR
,
807 "ERROR - Failed to close the TCP protocol, Status: %r\r\n",
812 "0x%08x: TCP4 protocol closed\r\n",
814 pTcp4Protocol
= NULL
;
819 // Done with the TCP service
821 if ( NULL
!= Tcp4Handle
) {
822 Status
= pTcp4Service
->DestroyChild ( pTcp4Service
,
824 if ( EFI_ERROR ( Status
)) {
825 DEBUG (( DEBUG_ERROR
,
826 "ERROR - Failed to release TCP service handle, Status: %r\r\n",
831 "Ox%08x: TCP service closed\r\n",
838 // Close the service protocol
840 if ( NULL
!= pTcp4Service
) {
841 Status
= gBS
->CloseProtocol ( Tcp4Controller
,
842 &gEfiTcp4ServiceBindingProtocolGuid
,
845 if ( !EFI_ERROR ( Status
)) {
847 "0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
852 DEBUG (( DEBUG_ERROR
,
853 "ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
857 Tcp4Controller
= NULL
;
858 bTcp4Connecting
= TRUE
;
861 // Mark the connection as closed
863 Status
= EFI_SUCCESS
;
866 // Return the operation status
875 @retval EFI_SUCCESS Protocol found
876 @retval other Protocl not found
883 EFI_HANDLE
* pHandles
;
888 // Use do/while and break instead of goto
892 // Attempt to locate the next TCP adapter in the system
894 Status
= gBS
->LocateHandleBuffer ( ByProtocol
,
895 &gEfiTcp4ServiceBindingProtocolGuid
,
899 if ( EFI_ERROR ( Status
)) {
901 "WARNING - No network controllers or TCP4 available, Status: %r\r\n",
907 // Wrap the index if necessary
909 if ( HandleCount
<= Tcp4Index
) {
913 // Wait for the next timer tick
921 // Display the connecting message
923 if ( bTcp4Connecting
) {
924 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
925 Print ( L
"Connecting to %d.%d.%d.%d:%d\r\n",
930 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
931 bTcp4Connecting
= FALSE
;
935 // Open the network controller's service protocol
937 Tcp4Controller
= pHandles
[ Tcp4Index
++ ];
938 Status
= gBS
->OpenProtocol (
940 &gEfiTcp4ServiceBindingProtocolGuid
,
941 (VOID
**) &pTcp4Service
,
944 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
945 if ( EFI_ERROR ( Status
)) {
946 DEBUG (( DEBUG_ERROR
,
947 "ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
949 Tcp4Controller
= NULL
;
953 "0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
957 // Connect to the TCP service
959 Status
= pTcp4Service
->CreateChild ( pTcp4Service
,
961 if ( EFI_ERROR ( Status
)) {
962 DEBUG (( DEBUG_ERROR
,
963 "ERROR - Failed to open TCP service, Status: %r\r\n",
969 "Ox%08x: TCP service opened\r\n",
973 // Locate the TCP protcol
975 Status
= gBS
->OpenProtocol ( Tcp4Handle
,
976 &gEfiTcp4ProtocolGuid
,
977 (VOID
**)&pTcp4Protocol
,
980 EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
);
981 if ( EFI_ERROR ( Status
)) {
982 DEBUG (( DEBUG_ERROR
,
983 "ERROR - Failed to open the TCP protocol, Status: %r\r\n",
985 pTcp4Protocol
= NULL
;
989 "0x%08x: TCP4 protocol opened\r\n",
994 // Release the handle buffer
996 gBS
->FreePool ( pHandles
);
999 // Return the operation status
1006 Send data over the TCP4 connection
1008 @retval EFI_SUCCESS The application is running normally
1009 @retval Other The user stopped the application
1016 EFI_TCP4_TRANSMIT_DATA Packet
;
1018 EFI_TPL TplPrevious
;
1021 // Restart the timer
1023 TimerStart ( 1 * 1000 );
1026 // Initialize the packet
1028 Packet
.DataLength
= sizeof ( Buffer
);
1029 Packet
.FragmentCount
= 1;
1030 Packet
.Push
= FALSE
;
1031 Packet
.Urgent
= FALSE
;
1032 Packet
.FragmentTable
[0].FragmentBuffer
= &Buffer
[0];
1033 Packet
.FragmentTable
[0].FragmentLength
= sizeof ( Buffer
);
1034 Tcp4TxToken
.Packet
.TxData
= &Packet
;
1037 // Loop until the connection breaks or the user stops
1041 // Check for user stop request
1043 Status
= ControlCCheck ( );
1044 if ( EFI_ERROR ( Status
)) {
1051 Status
= pTcp4Protocol
->Transmit ( pTcp4Protocol
,
1053 if ( EFI_ERROR ( Status
)) {
1054 DEBUG (( DEBUG_ERROR
,
1055 "ERROR - Failed to start the transmit, Status: %r\r\n",
1061 Status
= EFI_SUCCESS
;
1066 // Wait for the transmit to complete
1068 Status
= gBS
->WaitForEvent ( 1,
1069 &Tcp4TxToken
.CompletionToken
.Event
,
1071 if ( EFI_ERROR ( Status
)) {
1072 DEBUG (( DEBUG_ERROR
,
1073 "ERROR - Failed to wait for transmit completion, Status: %r\r\n",
1079 Status
= EFI_SUCCESS
;
1084 // Get the transmit status
1086 Status
= Tcp4TxToken
.CompletionToken
.Status
;
1087 if ( EFI_ERROR ( Status
)) {
1088 DEBUG (( DEBUG_WARN
,
1089 "WARNING - Failed the transmission, Status: %r\r\n",
1095 Status
= EFI_SUCCESS
;
1100 Status
= EFI_NOT_STARTED
;
1105 // Synchronize with the TimerCallback routine
1107 TplPrevious
= gBS
->RaiseTPL ( TPL_DATASOURCE
);
1110 // Account for the data sent
1112 TotalBytesSent
+= Packet
.DataLength
;
1115 // Release the TimerCallback routine synchronization
1117 gBS
->RestoreTPL ( TplPrevious
);
1118 } while ( !EFI_ERROR ( Status
));
1121 // Return the operation status
1128 Open the network connection and send the data.
1130 @retval EFI_SUCCESS Continue looping
1131 @retval other Stopped by user's Control-C input
1143 // Use do/while and break instead of goto
1147 // Locate the TCP protocol
1149 Status
= Tcp4Locate ( );
1150 if ( EFI_ERROR ( Status
)) {
1155 // Create the necessary events
1157 Status
= gBS
->CreateEvent ( 0,
1161 &Tcp4CloseToken
.CompletionToken
.Event
);
1162 if ( EFI_ERROR ( Status
)) {
1163 DEBUG (( DEBUG_ERROR
,
1164 "ERROR - Failed to create the close event, Status: %r\r\n",
1166 Tcp4CloseToken
.CompletionToken
.Event
= NULL
;
1169 DEBUG (( DEBUG_INFO
,
1170 "0x%08x: Close event open\r\n",
1171 Tcp4CloseToken
.CompletionToken
.Event
));
1173 Status
= gBS
->CreateEvent ( 0,
1177 &Tcp4ConnectToken
.CompletionToken
.Event
);
1178 if ( EFI_ERROR ( Status
)) {
1179 DEBUG (( DEBUG_ERROR
,
1180 "ERROR - Failed to create the connect event, Status: %r\r\n",
1182 Tcp4ConnectToken
.CompletionToken
.Event
= NULL
;
1185 DEBUG (( DEBUG_INFO
,
1186 "0x%08x: Connect event open\r\n",
1187 Tcp4ConnectToken
.CompletionToken
.Event
));
1189 Status
= gBS
->CreateEvent ( 0,
1193 &Tcp4ListenToken
.CompletionToken
.Event
);
1194 if ( EFI_ERROR ( Status
)) {
1195 DEBUG (( DEBUG_ERROR
,
1196 "ERROR - Failed to create the listen event, Status: %r\r\n",
1198 Tcp4ListenToken
.CompletionToken
.Event
= NULL
;
1201 DEBUG (( DEBUG_INFO
,
1202 "0x%08x: Listen event open\r\n",
1203 Tcp4ListenToken
.CompletionToken
.Event
));
1205 Status
= gBS
->CreateEvent ( 0,
1209 &Tcp4TxToken
.CompletionToken
.Event
);
1210 if ( EFI_ERROR ( Status
)) {
1211 DEBUG (( DEBUG_ERROR
,
1212 "ERROR - Failed to create the TX event, Status: %r\r\n",
1214 Tcp4TxToken
.CompletionToken
.Event
= NULL
;
1217 DEBUG (( DEBUG_INFO
,
1218 "0x%08x: TX event open\r\n",
1219 Tcp4TxToken
.CompletionToken
.Event
));
1222 // Configure the local TCP port
1224 Tcp4ConfigData
.TimeToLive
= 255;
1225 Tcp4ConfigData
.TypeOfService
= 0;
1226 Tcp4ConfigData
.ControlOption
= NULL
;
1227 Tcp4ConfigData
.AccessPoint
.ActiveFlag
= TRUE
;
1228 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[0] = 0;
1229 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[1] = 0;
1230 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[2] = 0;
1231 Tcp4ConfigData
.AccessPoint
.StationAddress
.Addr
[3] = 0;
1232 Tcp4ConfigData
.AccessPoint
.StationPort
= 0;
1233 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[0] = (UINT8
) ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1234 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[1] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 8 );
1235 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[2] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 16 );
1236 Tcp4ConfigData
.AccessPoint
.RemoteAddress
.Addr
[3] = (UINT8
)( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
>> 24 );
1237 Tcp4ConfigData
.AccessPoint
.RemotePort
= ntohs (((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
);
1238 Tcp4ConfigData
.AccessPoint
.UseDefaultAddress
= TRUE
;
1239 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[0] = 0;
1240 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[1] = 0;
1241 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[2] = 0;
1242 Tcp4ConfigData
.AccessPoint
.SubnetMask
.Addr
[3] = 0;
1243 Status
= pTcp4Protocol
->Configure ( pTcp4Protocol
,
1245 if ( EFI_ERROR ( Status
)) {
1246 DEBUG (( DEBUG_ERROR
,
1247 "ERROR - Failed to configure TCP port, Status: %r\r\n",
1251 DEBUG (( DEBUG_INFO
,
1252 "0x%08x: TCP4 port configured\r\n",
1256 // Connect to the remote TCP port
1258 Status
= pTcp4Protocol
->Connect ( pTcp4Protocol
,
1259 &Tcp4ConnectToken
);
1260 if ( EFI_ERROR ( Status
)) {
1261 DEBUG (( DEBUG_ERROR
,
1262 "ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
1266 Status
= gBS
->WaitForEvent ( 1,
1267 &Tcp4ConnectToken
.CompletionToken
.Event
,
1269 if ( EFI_ERROR ( Status
)) {
1270 DEBUG (( DEBUG_ERROR
,
1271 "ERROR - Failed to wait for the connection, Status: %r\r\n",
1275 Status
= Tcp4ConnectToken
.CompletionToken
.Status
;
1276 if ( EFI_ERROR ( Status
)) {
1277 DEBUG (( DEBUG_WARN
,
1278 "WARNING - Failed to connect to the remote system, Status: %r\r\n",
1282 DEBUG (( DEBUG_INFO
,
1283 "0x%08x: TCP4 port connected\r\n",
1285 bTcp4Connected
= TRUE
;
1288 // Display the connection
1290 pIpAddress
= (UINT8
*)&((struct sockaddr_in
*)&RemoteHostAddress
)->sin_addr
.s_addr
;
1291 Print ( L
"Connected to %d.%d.%d.%d:%d\r\n",
1296 ntohs ( ((struct sockaddr_in
*)&RemoteHostAddress
)->sin_port
));
1299 if ( EFI_ERROR ( Status
)) {
1303 Status
= EFI_SUCCESS
;
1307 // Semd data until the connection breaks
1309 Status
= Tcp4Send ( );
1313 // Return the operation status
1320 Handle the timer callback
1322 @param [in] Event Event that caused this callback
1323 @param [in] pContext Context for this routine
1333 UINT64 BitsPerSecond
;
1338 // Notify the other code of the timer tick
1343 // Update the average bytes per second
1345 if ( 0 != TotalBytesSent
) {
1346 BytesSent
[ In
] = TotalBytesSent
;
1349 if ( DATA_SAMPLES
<= In
) {
1354 // Separate the samples
1356 if ( DATA_SAMPLES
== Samples
) {
1357 Print ( L
"---------- Stable average ----------\r\n" );
1362 // Compute the data rate
1365 for ( Index
= 0; DATA_SAMPLES
> Index
; Index
++ ) {
1366 TotalBytes
+= BytesSent
[ Index
];
1368 Average
= (UINT32
)RShiftU64 ( TotalBytes
, DATA_SAMPLE_SHIFT
);
1369 BitsPerSecond
= Average
* 8;
1372 // Display the data rate
1374 if (( RANGE_SWITCH
>> 10 ) > Average
) {
1375 Print ( L
"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n",
1380 BitsPerSecond
/= 1000;
1381 if ( RANGE_SWITCH
> Average
) {
1382 Print ( L
"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n",
1384 (( Average
& 0x3ff ) * 1000 ) >> 10,
1388 BitsPerSecond
/= 1000;
1390 if ( RANGE_SWITCH
> Average
) {
1391 Print ( L
"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n",
1393 (( Average
& 0x3ff ) * 1000 ) >> 10,
1397 BitsPerSecond
/= 1000;
1399 if ( RANGE_SWITCH
> Average
) {
1400 Print ( L
"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n",
1402 (( Average
& 0x3ff ) * 1000 ) >> 10,
1406 BitsPerSecond
/= 1000;
1408 if ( RANGE_SWITCH
> Average
) {
1409 Print ( L
"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n",
1411 (( Average
& 0x3ff ) * 1000 ) >> 10,
1415 BitsPerSecond
/= 1000;
1417 Print ( L
"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n",
1419 (( Average
& 0x3ff ) * 1000 ) >> 10,
1433 @retval EFI_SUCCESS The timer was successfully created
1434 @retval Other Timer initialization failed
1445 Status
= gBS
->CreateEvent ( EVT_TIMER
| EVT_NOTIFY_SIGNAL
,
1450 if ( EFI_ERROR ( Status
)) {
1451 DEBUG (( DEBUG_ERROR
,
1452 "ERROR - Failed to allocate the timer event, Status: %r\r\n",
1456 DEBUG (( DEBUG_INFO
,
1457 "0x%08x: Timer created\r\n",
1462 // Return the operation status
1471 @retval EFI_SUCCESS The timer was stopped successfully
1472 @retval Other The timer failed to stop
1483 Status
= EFI_SUCCESS
;
1486 // Determine if the timer is running
1488 if ( bTimerRunning
) {
1492 Status
= gBS
->SetTimer ( pTimer
,
1495 if ( EFI_ERROR ( Status
)) {
1496 DEBUG (( DEBUG_ERROR
,
1497 "ERROR - Failed to stop the timer, Status: %r\r\n",
1502 // Timer timer is now stopped
1504 bTimerRunning
= FALSE
;
1505 DEBUG (( DEBUG_INFO
,
1506 "0x%08x: Timer stopped\r\n",
1512 // Return the operation status
1521 @param [in] Milliseconds The number of milliseconds between timer callbacks
1523 @retval EFI_SUCCESS The timer was successfully created
1524 @retval Other Timer initialization failed
1535 // Stop the timer if necessary
1537 Status
= EFI_SUCCESS
;
1538 if ( bTimerRunning
) {
1539 Status
= TimerStop ( );
1541 if ( !EFI_ERROR ( Status
)) {
1543 // Compute the new delay
1545 TimeDelay
= Milliseconds
;
1546 TimeDelay
*= 1000 * 10;
1551 Status
= gBS
->SetTimer ( pTimer
,
1554 if ( EFI_ERROR ( Status
)) {
1555 DEBUG (( DEBUG_ERROR
,
1556 "ERROR - Failed to start the timer, Status: %r\r\n",
1561 // The timer is now running
1563 bTimerRunning
= TRUE
;
1564 DEBUG (( DEBUG_INFO
,
1565 "0x%08x: Timer running\r\n",
1571 // Return the operation status
1580 @retval EFI_SUCCESS The timer was destroyed successfully
1581 @retval Other Failed to destroy the timer
1592 Status
= EFI_SUCCESS
;
1595 // Determine if the timer is running
1597 if ( bTimerRunning
) {
1601 Status
= TimerStop ( );
1603 if (( !EFI_ERROR ( Status
)) && ( NULL
!= pTimer
)) {
1605 // Done with this timer
1607 Status
= gBS
->CloseEvent ( pTimer
);
1608 if ( EFI_ERROR ( Status
)) {
1609 DEBUG (( DEBUG_ERROR
,
1610 "ERROR - Failed to free the timer event, Status: %r\r\n",
1614 DEBUG (( DEBUG_INFO
,
1615 "0x%08x: Timer Destroyed\r\n",
1622 // Return the operation status
1629 Send data to the DataSink program to test a network's bandwidth.
1631 @param [in] Argc The number of arguments
1632 @param [in] Argv The argument value array
1634 @retval 0 The application exited normally.
1635 @retval Other An error occurred.
1643 EFI_STATUS (* pClose
) ();
1644 EFI_STATUS (* pOpen
) ();
1647 DEBUG (( DEBUG_INFO
,
1648 "DataSource starting\r\n" ));
1651 // Validate the command line
1654 Print ( L
"%s <remote IP address> [Use TCP]\r\n", Argv
[0] );
1659 // Determine if TCP should be used
1661 bTcp4
= (BOOLEAN
)( 2 < Argc
);
1664 // Determine the support routines
1669 bTcp4Connecting
= TRUE
;
1673 pClose
= SocketClose
;
1677 // Use for/break instead of goto
1681 // No bytes sent so far
1685 memset ( &BytesSent
, 0, sizeof ( BytesSent
));
1688 // Get the IP address
1690 pRemoteHost
= Argv
[1];
1691 Status
= IpAddress ( );
1692 if ( EFI_ERROR ( Status
)) {
1700 Status
= TimerCreate ( );
1701 if ( EFI_ERROR ( Status
)) {
1706 // Loop forever abusing the specified system
1710 // Start a timer to perform connection polling and display updates
1712 Status
= TimerStart ( 2 * 1000 );
1713 if ( EFI_ERROR ( Status
)) {
1718 // Open the network connection and send the data
1721 if ( EFI_ERROR ( Status
)) {
1726 // Done with the network connection
1728 Status
= pClose ( );
1729 } while ( !EFI_ERROR ( Status
));
1732 // Close the network connection if necessary
1743 // Stop the timer if necessary
1749 // Return the operation status
1751 DEBUG (( DEBUG_INFO
,
1752 "DataSource exiting, Status: %r\r\n",