/** @file
Data source for network testing.
Copyright (c) 2011, Intel Corporation
All rights reserved. This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <errno.h>
#include <Uefi.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Protocol/ServiceBinding.h>
#include <sys/EfiSysCall.h>
//
// Socket Data
//
//
// TCP V4 Data
//
//
// Timer Data
//
//
// Remote IP Address Data
//
//
// Traffic Data
//
//
// Forward routine declarations
//
/**
Check for control C entered at console
@retval EFI_SUCCESS Control C not entered
@retval EFI_ABORTED Control C entered
**/
)
{
//
// Assume no user intervention
//
//
// Display user stop request
//
DEBUG (( DEBUG_INFO,
"User stop request!\r\n" ));
}
//
// Return the check status
//
return Status;
}
/**
Get a digit
@param [in] pDigit The address of the next digit
@param [out] pValue The address to receive the value
@return Returns the address of the separator
**/
CHAR8 *
GetDigit (
)
{
//
// Walk the digits
//
Value = 0;
//
// Make room for the new least significant digit
//
Value *= 10;
//
// Convert the digit from ASCII to binary
//
//
// Set the next digit
//
pDigit += 1;
}
//
// Return the value
//
//
// Return the next separator
//
return pDigit;
}
/**
Get the IP address
@retval EFI_SUCCESS The IP address is valid
@retval Other Failure to convert the IP address
**/
)
{
//
// Assume failure
//
//
// Convert the IP address from a string to a numeric value
//
| ( Value2 << 8 )
| ( Value3 << 16 )
| ( Value4 << 24 );
DEBUG (( DEBUG_INFO,
"%d.%d.%d.%d: Remote host IP address\r\n",
Value4 ));
}
}
}
}
}
//
// Return the operation status
//
return Status;
}
/**
Close the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
int CloseStatus;
//
// Determine if the socket is open
//
if ( -1 != Socket ) {
//
// Attempt to close the socket
//
if ( 0 == CloseStatus ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket closed\r\n",
Socket ));
Socket = -1;
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR: Failed to close socket, errno: %d\r\n",
errno ));
}
}
//
// Return the operation status
//
return Status;
}
/**
Connect the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
int ConnectStatus;
//
// Display the connecting message
//
Print ( L"Connecting to remote system %d.%d.%d.%d:%d\r\n",
RemoteAddress & 0xff,
//
// Connect to the remote system
//
do {
//
// Check for user stop request
//
while ( !bTick ) {
Status = ControlCCheck ( );
break;
}
}
break;
}
//
// Connect to the remote system
//
(struct sockaddr *) &RemoteHostAddress,
if ( -1 != ConnectStatus ) {
Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n",
RemoteAddress & 0xff,
}
else {
//
// Close the socket and try again
//
break;
}
}
} while ( -1 == ConnectStatus );
//
// Return the operation status
//
return Status;
}
/**
Create the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
//
// Loop creating the socket
//
DEBUG (( DEBUG_INFO,
"Creating the socket\r\n" ));
do {
//
// Check for user stop request
//
Status = ControlCCheck ( );
break;
}
//
// Attempt to create the socket
//
IPPROTO_TCP );
if ( -1 != Socket ) {
DEBUG (( DEBUG_INFO,
"0x%08x: Socket created\r\n",
Socket ));
break;
}
} while ( -1 == Socket );
//
// Return the operation status
//
return Status;
}
/**
Send data over the socket
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
//
// Restart the timer
//
//
// Loop until the connection breaks or the user stops
//
do {
//
// Check for user stop request
//
Status = ControlCCheck ( );
break;
}
//
// Send some bytes
//
if ( -1 == BytesSent ) {
DEBUG (( DEBUG_INFO,
"ERROR: send failed, errno: %d\r\n",
errno ));
//
// Try again
//
//
// Exit now
//
break;
}
//
// Synchronize with the TimerCallback routine
//
//
// Account for the data sent
//
//
// Release the TimerCallback routine synchronization
//
//
// Return the operation status
//
return Status;
}
/**
Open the network connection and send the data.
@retval EFI_SUCCESS Continue looping
@retval other Stopped by user's Control-C input
**/
)
{
//
//
do {
//
// Wait for the network layer to initialize
//
break;
}
//
// Wait for the remote network application to start
//
Status = SocketConnect ( );
if ( EFI_NOT_STARTED == Status ) {
Status = SocketClose ( );
continue;
}
else if ( EFI_SUCCESS != Status ) {
//
// Control-C
//
break;
}
//
// Send data until the connection breaks
//
Status = SocketSend ( );
break;
}
} while ( FALSE );
//
// Return the operation status
//
return Status;
}
/**
Close the TCP connection
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
)
{
//
// Close the port
//
if ( bTcp4Connected ) {
&Tcp4CloseToken );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to start the TCP port close, Status: %r\r\n",
Status ));
}
else {
&Index );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to wait for close event, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the TCP port, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_INFO,
"0x%08x: TCP port closed\r\n",
pTcp4Protocol ));
//
// Display the port closed message
//
Print ( L"Closed connection to %d.%d.%d.%d:%d\r\n",
pIpAddress[0],
pIpAddress[1],
pIpAddress[2],
pIpAddress[3],
}
}
}
}
//
// Release the events
//
DEBUG (( DEBUG_INFO,
"0x%08x: TX event closed\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the Tcp4TxToken event, Status: %r\r\n",
Status ));
}
}
DEBUG (( DEBUG_INFO,
"0x%08x: Listen event closed\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the Tcp4ListenToken event, Status: %r\r\n",
Status ));
}
}
DEBUG (( DEBUG_INFO,
"0x%08x: Connect event closed\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the Tcp4ConnectToken event, Status: %r\r\n",
Status ));
}
}
DEBUG (( DEBUG_INFO,
"0x%08x: Close event closed\r\n",
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the Tcp4CloseToken event, Status: %r\r\n",
Status ));
}
}
//
// Close the TCP protocol
//
if ( NULL != pTcp4Protocol ) {
NULL );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the TCP protocol, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_INFO,
"0x%08x: TCP4 protocol closed\r\n",
pTcp4Protocol ));
}
}
//
// Done with the TCP service
//
if ( NULL != Tcp4Handle ) {
Tcp4Handle );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to release TCP service handle, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_INFO,
"Ox%08x: TCP service closed\r\n",
Tcp4Handle ));
Tcp4Handle = NULL;
}
}
//
// Close the service protocol
//
if ( NULL != pTcp4Service ) {
NULL );
DEBUG (( DEBUG_INFO,
"0x%08x: Controller closed gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
Tcp4Controller ));
pTcp4Service = NULL;
}
else {
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to close the gEfiTcp4ServiceBindingProtocolGuid protocol, Status: %r\r\n",
Status ));
}
}
//
// Mark the connection as closed
//
//
// Return the operation status
//
return Status;
}
/**
Locate TCP protocol
@retval EFI_SUCCESS Protocol found
@retval other Protocl not found
**/
)
{
//
//
do {
//
// Attempt to locate the next TCP adapter in the system
//
NULL,
&pHandles );
DEBUG (( DEBUG_WARN,
"WARNING - No network controllers or TCP4 available, Status: %r\r\n",
Status ));
break;
}
//
// Wrap the index if necessary
//
if ( HandleCount <= Tcp4Index ) {
Tcp4Index = 0;
//
// Wait for the next timer tick
//
do {
} while ( !bTick );
}
//
// Display the connecting message
//
if ( bTcp4Connecting ) {
Print ( L"Connecting to %d.%d.%d.%d:%d\r\n",
pIpAddress[0],
pIpAddress[1],
pIpAddress[2],
pIpAddress[3],
}
//
// Open the network controller's service protocol
//
(VOID **) &pTcp4Service,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to open gEfiTcp4ServiceBindingProtocolGuid on controller 0x%08x\r\n",
Tcp4Controller ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: Controller opened gEfiTcp4ServiceBindingProtocolGuid protocol\r\n",
Tcp4Controller ));
//
// Connect to the TCP service
//
&Tcp4Handle );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to open TCP service, Status: %r\r\n",
Status ));
Tcp4Handle = NULL;
break;
}
DEBUG (( DEBUG_INFO,
"Ox%08x: TCP service opened\r\n",
Tcp4Handle ));
//
// Locate the TCP protcol
//
(VOID **)&pTcp4Protocol,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to open the TCP protocol, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: TCP4 protocol opened\r\n",
pTcp4Protocol ));
}while ( FALSE );
//
// Release the handle buffer
//
//
// Return the operation status
//
return Status;
}
/**
Send data over the TCP4 connection
@retval EFI_SUCCESS The application is running normally
@retval Other The user stopped the application
**/
Tcp4Send (
)
{
//
// Restart the timer
//
//
// Initialize the packet
//
//
// Loop until the connection breaks or the user stops
//
do {
//
// Check for user stop request
//
Status = ControlCCheck ( );
break;
}
//
// Send some bytes
//
&Tcp4TxToken );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to start the transmit, Status: %r\r\n",
Status ));
//
// Try again
//
break;
}
//
// Wait for the transmit to complete
//
&Index );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to wait for transmit completion, Status: %r\r\n",
Status ));
//
// Try again
//
break;
}
//
// Get the transmit status
//
DEBUG (( DEBUG_WARN,
"WARNING - Failed the transmission, Status: %r\r\n",
Status ));
//
// Try again
//
//
// Exit now
//
break;
}
//
// Synchronize with the TimerCallback routine
//
//
// Account for the data sent
//
//
// Release the TimerCallback routine synchronization
//
//
// Return the operation status
//
return Status;
}
/**
Open the network connection and send the data.
@retval EFI_SUCCESS Continue looping
@retval other Stopped by user's Control-C input
**/
Tcp4Open (
)
{
//
//
do {
//
// Locate the TCP protocol
//
Status = Tcp4Locate ( );
break;
}
//
// Create the necessary events
//
NULL,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to create the close event, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: Close event open\r\n",
NULL,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to create the connect event, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: Connect event open\r\n",
NULL,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to create the listen event, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: Listen event open\r\n",
NULL,
NULL,
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to create the TX event, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: TX event open\r\n",
//
// Configure the local TCP port
//
Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[1] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 8 );
Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[2] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 16 );
Tcp4ConfigData.AccessPoint.RemoteAddress.Addr[3] = (UINT8)( RemoteHostAddress.sin_addr.s_addr >> 24 );
&Tcp4ConfigData );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to configure TCP port, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: TCP4 port configured\r\n",
pTcp4Protocol ));
//
// Connect to the remote TCP port
//
&Tcp4ConnectToken );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to start the connection to the remote system, Status: %r\r\n",
Status ));
break;
}
&Index );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to wait for the connection, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_WARN,
"WARNING - Failed to connect to the remote system, Status: %r\r\n",
Status ));
break;
}
DEBUG (( DEBUG_INFO,
"0x%08x: TCP4 port connected\r\n",
pTcp4Protocol ));
//
// Display the connection
//
Print ( L"Connected to %d.%d.%d.%d:%d\r\n",
pIpAddress[0],
pIpAddress[1],
pIpAddress[2],
pIpAddress[3],
} while ( 0 );
//
// Try again
//
}
else {
//
// Semd data until the connection breaks
//
}
//
// Return the operation status
//
return Status;
}
/**
Handle the timer callback
@param [in] Event Event that caused this callback
@param [in] pContext Context for this routine
**/
)
{
//
// Notify the other code of the timer tick
//
//
// Update the average bytes per second
//
if ( 0 != BytesSent ) {
//
// Separate the samples
//
Print ( L"---------- Stable average ----------\r\n" );
}
Samples += 1;
//
// Display the data rate
//
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
}
else {
Average >>= 10;
if ( Average < RANGE_SWITCH ) {
Average );
}
else {
Average >>= 10;
}
}
}
}
}
}
}
/**
Create the timer
@retval EFI_SUCCESS The timer was successfully created
@retval Other Timer initialization failed
**/
)
{
//
// Create the timer
//
NULL,
&pTimer );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to allocate the timer event, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_INFO,
"0x%08x: Timer created\r\n",
pTimer ));
}
//
// Return the operation status
//
return Status;
}
/**
Stop the timer
@retval EFI_SUCCESS The timer was stopped successfully
@retval Other The timer failed to stop
**/
)
{
//
// Assume success
//
//
// Determine if the timer is running
//
if ( bTimerRunning ) {
//
// Stop the timer
//
0 );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to stop the timer, Status: %r\r\n",
Status ));
}
else {
//
// Timer timer is now stopped
//
DEBUG (( DEBUG_INFO,
"0x%08x: Timer stopped\r\n",
pTimer ));
}
}
//
// Return the operation status
//
return Status;
}
/**
Start the timer
@param [in] Milliseconds The number of milliseconds between timer callbacks
@retval EFI_SUCCESS The timer was successfully created
@retval Other Timer initialization failed
**/
)
{
//
// Stop the timer if necessary
//
if ( bTimerRunning ) {
}
//
// Compute the new delay
//
//
// Start the timer
//
TimeDelay );
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to start the timer, Status: %r\r\n",
Status ));
}
else {
//
// The timer is now running
//
DEBUG (( DEBUG_INFO,
"0x%08x: Timer running\r\n",
pTimer ));
}
}
//
// Return the operation status
//
return Status;
}
/**
Destroy the timer
@retval EFI_SUCCESS The timer was destroyed successfully
@retval Other Failed to destroy the timer
**/
)
{
//
// Assume success
//
//
// Determine if the timer is running
//
if ( bTimerRunning ) {
//
// Stop the timer
//
}
//
// Done with this timer
//
DEBUG (( DEBUG_ERROR,
"ERROR - Failed to free the timer event, Status: %r\r\n",
Status ));
}
else {
DEBUG (( DEBUG_INFO,
"0x%08x: Timer Destroyed\r\n",
pTimer ));
}
}
//
// Return the operation status
//
return Status;
}
/**
Send data to the DataSink program to test a network's bandwidth.
@param [in] Argc The number of arguments
@param [in] Argv The argument value array
@retval 0 The application exited normally.
@retval Other An error occurred.
**/
int
main (
)
{
EFI_STATUS (* pClose) ();
EFI_STATUS (* pOpen) ();
DEBUG (( DEBUG_INFO,
"DataSource starting\r\n" ));
//
// Validate the command line
//
if ( 2 > Argc ) {
return -1;
}
//
// Determine if TCP should be used
//
//
// Determine the support routines
//
if ( bTcp4 ) {
}
else {
pOpen = SocketOpen;
}
//
//
for ( ; ; ) {
//
// No bytes sent so far
//
TotalBytesSent = 0;
AverageBytes = 0;
PreviousBytes = 0;
Samples = 0;
//
// Get the port number
//
//
// Get the IP address
//
break;
}
//
// Create the timer
//
Status = TimerCreate ( );
break;
}
//
// Loop forever abusing the specified system
//
do {
//
// Start a timer to perform connection polling and display updates
//
break;
}
//
// Open the network connection and send the data
//
break;
}
//
// Done with the network connection
//
//
// Close the network connection if necessary
//
pClose ( );
//
// All done
//
break;
}
//
// Stop the timer if necessary
//
TimerStop ( );
TimerDestroy ( );
//
// Return the operation status
//
DEBUG (( DEBUG_INFO,
"DataSource exiting, Status: %r\r\n",
Status ));
return Status;
}