/** @file Data source for network testing. Copyright (c) 2011-2012, Intel Corporation. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include #include #include #include #include #include #include #include #define DATA_SAMPLE_SHIFT 5 ///< Shift for number of samples #define MAX_CONNECTIONS ( 1 + 16 ) ///< Maximum number of client connections #define RANGE_SWITCH ( 1024 * 1024 ) ///< Switch display ranges #define DATA_RATE_UPDATE_SHIFT 2 ///< 2n seconds between updates #define AVERAGE_SHIFT_COUNT ( 6 - DATA_RATE_UPDATE_SHIFT ) ///< 2n samples in average #define DATA_SAMPLES ( 1 << DATA_SAMPLE_SHIFT ) ///< Number of samples #define TPL_DATASINK TPL_CALLBACK ///< Synchronization TPL #define PACKET_SIZE 1448 ///< Size of data packets #define DATA_BUFFER_SIZE (( 65536 / PACKET_SIZE ) * PACKET_SIZE ) ///< Buffer size in bytes typedef struct _DT_PORT { UINT64 BytesTotal; struct sockaddr_in6 IpAddress; UINT32 In; UINT32 Samples; UINT64 BytesReceived[ DATA_SAMPLES ]; } DT_PORT; volatile BOOLEAN bTick; BOOLEAN bTimerRunning; struct sockaddr_in6 LocalAddress; EFI_EVENT pTimer; int ListenSocket; UINT8 Buffer[ DATA_BUFFER_SIZE ]; struct pollfd PollFd[ MAX_CONNECTIONS ]; DT_PORT Port[ MAX_CONNECTIONS ]; nfds_t MaxPort; // // Forward routine declarations // EFI_STATUS TimerStart ( UINTN Milliseconds ); /** Check for control C entered at console @retval EFI_SUCCESS Control C not entered @retval EFI_ABORTED Control C entered **/ EFI_STATUS ControlCCheck ( ) { EFI_STATUS Status; // // Assume no user intervention // Status = EFI_SUCCESS; // // Display user stop request // if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_INFO, "User stop request!\r\n" )); } // // Return the check status // return Status; } /** Accept a socket connection @retval EFI_SUCCESS The application is running normally @retval EFI_NOT_STARTED Error with the listen socket @retval Other The user stopped the application **/ EFI_STATUS SocketAccept ( ) { INT32 SocketStatus; EFI_STATUS Status; INTN Index; // // Assume failure // Status = EFI_DEVICE_ERROR; // // Bind to the local address // SocketStatus = bind ( ListenSocket, (struct sockaddr *) &LocalAddress, LocalAddress.sin6_len ); if ( 0 == SocketStatus ) { // // Start listening on the local socket // SocketStatus = listen ( ListenSocket, 5 ); if ( 0 == SocketStatus ) { // // Local socket in the listen state // Status = EFI_SUCCESS; // // Allocate a port // Index = MaxPort++; PollFd[ Index ].fd = ListenSocket; PollFd[ Index ].events = POLLRDNORM | POLLHUP; PollFd[ Index ].revents = 0; ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ])); } } // // Return the operation status // return Status; } /** Close the socket @retval EFI_SUCCESS The application is running normally @retval Other The user stopped the application **/ EFI_STATUS SocketClose ( ) { INT32 CloseStatus; EFI_STATUS Status; // // Determine if the socket is open // Status = EFI_DEVICE_ERROR; if ( -1 != ListenSocket ) { // // Attempt to close the socket // CloseStatus = close ( ListenSocket ); if ( 0 == CloseStatus ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed\r\n", ListenSocket )); ListenSocket = -1; Status = EFI_SUCCESS; } else { DEBUG (( DEBUG_ERROR, "ERROR: Failed to close socket, errno: %d\r\n", errno )); } } // // Return the operation status // return Status; } /** Create the socket @param [in] Family Network family, AF_INET or AF_INET6 @retval EFI_SUCCESS The application is running normally @retval Other The user stopped the application **/ EFI_STATUS SocketNew ( sa_family_t Family ) { EFI_STATUS Status; // // Get the port number // ZeroMem ( &LocalAddress, sizeof ( LocalAddress )); LocalAddress.sin6_len = sizeof ( LocalAddress ); LocalAddress.sin6_family = Family; LocalAddress.sin6_port = htons ( PcdGet16 ( DataSource_Port )); // // Loop creating the socket // DEBUG (( DEBUG_INFO, "Creating the socket\r\n" )); // // Check for user stop request // Status = ControlCCheck ( ); if ( !EFI_ERROR ( Status )) { // // Attempt to create the socket // ListenSocket = socket ( LocalAddress.sin6_family, SOCK_STREAM, IPPROTO_TCP ); if ( -1 != ListenSocket ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket created\r\n", ListenSocket )); } else { Status = EFI_NOT_STARTED; } } // // Return the operation status // return Status; } /** Poll the socket for more work @retval EFI_SUCCESS The application is running normally @retval EFI_NOT_STARTED Listen socket error @retval Other The user stopped the application **/ EFI_STATUS SocketPoll ( ) { BOOLEAN bRemoveSocket; BOOLEAN bListenError; size_t BytesReceived; int CloseStatus; nfds_t Entry; INTN EntryPrevious; int FdCount; nfds_t Index; socklen_t LengthInBytes; struct sockaddr_in * pPortIpAddress4; struct sockaddr_in6 * pPortIpAddress6; struct sockaddr_in * pRemoteAddress4; struct sockaddr_in6 * pRemoteAddress6; struct sockaddr_in6 RemoteAddress; int Socket; EFI_STATUS Status; EFI_TPL TplPrevious; // // Check for control-C // pRemoteAddress4 = (struct sockaddr_in *)&RemoteAddress; pRemoteAddress6 = (struct sockaddr_in6 *)&RemoteAddress; bListenError = FALSE; Status = ControlCCheck ( ); if ( !EFI_ERROR ( Status )) { // // Poll the sockets // FdCount = poll ( &PollFd[0], MaxPort, 0 ); if ( -1 == FdCount ) { // // Poll error // DEBUG (( DEBUG_ERROR, "ERROR - Poll error, errno: %d\r\n", errno )); Status = EFI_DEVICE_ERROR; } else { // // Process the poll output // Index = 0; while ( FdCount ) { bRemoveSocket = FALSE; // // Account for this descriptor // pPortIpAddress4 = (struct sockaddr_in *)&Port[ Index ].IpAddress; pPortIpAddress6 = (struct sockaddr_in6 *)&Port[ Index ].IpAddress; if ( 0 != PollFd[ Index ].revents ) { FdCount -= 1; } // // Check for a broken connection // if ( 0 != ( PollFd[ Index ].revents & POLLHUP )) { bRemoveSocket = TRUE; if ( ListenSocket == PollFd[ Index ].fd ) { bListenError = TRUE; DEBUG (( DEBUG_ERROR, "ERROR - Network closed on listen socket, errno: %d\r\n", errno )); } else { if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_ERROR, "ERROR - Network closed on socket %d.%d.%d.%d:%d, errno: %d\r\n", pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ), errno )); } else { DEBUG (( DEBUG_ERROR, "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", pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ), errno )); } // // Close the socket // CloseStatus = close ( PollFd[ Index ].fd ); if ( 0 == CloseStatus ) { bRemoveSocket = TRUE; if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n", PollFd[ Index ].fd, pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ))); } else { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", PollFd[ Index ].fd, pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ))); } } else { if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n", PollFd[ Index ].fd, pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ), errno )); } else { DEBUG (( DEBUG_ERROR, "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", PollFd[ Index ].fd, pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ), errno )); } } } } // // Check for a connection or read data // if ( 0 != ( PollFd[ Index ].revents & POLLRDNORM )) { // // Check for a connection // if ( ListenSocket == PollFd[ Index ].fd ) { // // Another client connection was received // LengthInBytes = sizeof ( RemoteAddress ); Socket = accept ( ListenSocket, (struct sockaddr *) &RemoteAddress, &LengthInBytes ); if ( -1 == Socket ) { // // Listen socket error // bListenError = TRUE; bRemoveSocket = TRUE; DEBUG (( DEBUG_ERROR, "ERROR - Listen socket failure, errno: %d\r\n", errno )); } else { // // Determine if there is room for this connection // if (( MAX_CONNECTIONS <= MaxPort ) || ((( MAX_CONNECTIONS - 1 ) == MaxPort ) && ( -1 == ListenSocket ))) { // // Display the connection // if ( AF_INET == pRemoteAddress4->sin_family ) { Print ( L"Rejecting connection to remote system %d.%d.%d.%d:%d\r\n", pRemoteAddress4->sin_addr.s_addr & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pRemoteAddress4->sin_port )); } else { 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", pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pRemoteAddress6->sin6_port )); } // // No room for this connection // Close the connection // CloseStatus = close ( Socket ); if ( 0 == CloseStatus ) { bRemoveSocket = TRUE; if ( AF_INET == pRemoteAddress4->sin_family ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n", PollFd[ Index ].fd, pRemoteAddress4->sin_addr.s_addr & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pRemoteAddress4->sin_port ))); } else { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", PollFd[ Index ].fd, pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pRemoteAddress6->sin6_port ))); } } else { DEBUG (( DEBUG_ERROR, "ERROR - Failed to close socket 0x%08x, errno: %d\r\n", PollFd[ Index ].fd, errno )); } // // Keep the application running // No issue with the listen socket // Status = EFI_SUCCESS; } else { // // Display the connection // if ( AF_INET == pRemoteAddress4->sin_family ) { Print ( L"Connected to remote system %d.%d.%d.%d:%d\r\n", pRemoteAddress4->sin_addr.s_addr & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pRemoteAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pRemoteAddress4->sin_port )); } else { 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", pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pRemoteAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pRemoteAddress6->sin6_port )); } // // Allocate the client connection // Index = MaxPort++; ZeroMem ( &Port[ Index ], sizeof ( Port[ Index ])); CopyMem ( pPortIpAddress6, pRemoteAddress6, sizeof ( *pRemoteAddress6 )); PollFd[ Index ].fd = Socket; PollFd[ Index ].events = POLLRDNORM | POLLHUP; PollFd[ Index ].revents = 0; } } } else { // // Data received // BytesReceived = read ( PollFd[ Index ].fd, &Buffer, sizeof ( Buffer )); if ( 0 < BytesReceived ) { // // Display the amount of data received // if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket received 0x%08x bytes from %d.%d.%d.%d:%d\r\n", PollFd[ Index ].fd, BytesReceived, pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ))); } else { DEBUG (( DEBUG_INFO, "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", PollFd[ Index ].fd, BytesReceived, pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ))); } // // Synchronize with the TimerCallback routine // TplPrevious = gBS->RaiseTPL ( TPL_DATASINK ); // // Account for the data received // Port[ Index ].BytesTotal += BytesReceived; // // Release the synchronization with the TimerCallback routine // gBS->RestoreTPL ( TplPrevious ); } else if ( -1 == BytesReceived ) { // // Close the socket // if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_INFO, "ERROR - Receive failure for %d.%d.%d.%d:%d, errno: %d\r\n", pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ), errno )); } else { DEBUG (( DEBUG_INFO, "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", pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ), errno )); } CloseStatus = close ( PollFd[ Index ].fd ); if ( 0 == CloseStatus ) { bRemoveSocket = TRUE; if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for %d.%d.%d.%d:%d\r\n", PollFd[ Index ].fd, pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ))); } else { DEBUG (( DEBUG_INFO, "0x%08x: Socket closed for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n", PollFd[ Index ].fd, pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ))); } } else { if ( AF_INET == pPortIpAddress4->sin_family ) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to close socket 0x%08x for %d.%d.%d.%d:%d, errno: %d\r\n", PollFd[ Index ].fd, pPortIpAddress4->sin_addr.s_addr & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 8 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 16 ) & 0xff, ( pPortIpAddress4->sin_addr.s_addr >> 24 ) & 0xff, ntohs ( pPortIpAddress4->sin_port ), errno )); } else { DEBUG (( DEBUG_ERROR, "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", PollFd[ Index ].fd, pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 0 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 1 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 2 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 3 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 4 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 5 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 6 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 7 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 8 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 9 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 10 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 11 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 12 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 13 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 14 ], pPortIpAddress6->sin6_addr.__u6_addr.__u6_addr8[ 15 ], ntohs ( pPortIpAddress6->sin6_port ), errno )); } } } // // Keep the application running // No issue with the listen socket // Status = EFI_SUCCESS; } } // // Remove the socket if necessary // if ( bRemoveSocket ) { DEBUG (( DEBUG_INFO, "0x%08x: Socket removed from polling\r\n", PollFd[ Index ].fd )); MaxPort -= 1; for ( Entry = Index + 1; MaxPort >= Entry; Entry++ ) { EntryPrevious = Entry; CopyMem ( &Port[ EntryPrevious ], &Port[ Entry ], sizeof ( Port[ Entry ])); PollFd[ EntryPrevious ].events = PollFd[ Entry ].events; PollFd[ EntryPrevious ].fd = PollFd[ Entry ].fd; PollFd[ EntryPrevious ].revents = PollFd[ Entry ].revents; } PollFd[ MaxPort ].fd = -1; Index -= 1; } // // Account for this socket // Index += 1; } } } // // Return the listen failure if necessary // if (( !EFI_ERROR ( Status )) && bListenError ) { Status = EFI_NOT_STARTED; } // // Return the poll status // return Status; } /** Handle the timer callback @param [in] Event Event that caused this callback @param [in] pContext Context for this routine **/ VOID EFIAPI TimerCallback ( IN EFI_EVENT Event, IN VOID * pContext ) { UINT32 Average; UINT64 BitsPerSecond; UINT64 BytesReceived; UINT32 Count; nfds_t Index; UINT64 TotalBytes; // // Notify the other code of the timer tick // bTick = TRUE; // // Walk the list of ports // for ( Index = 0; MaxPort > Index; Index++ ) { // // Determine if any data was received // BytesReceived = Port[ Index ].BytesTotal; if (( ListenSocket != PollFd[ Index ].fd ) && ( 0 != BytesReceived )) { // // Update the received data samples // Port[ Index ].BytesTotal = 0; Port[ Index ].BytesReceived [ Port[ Index ].In ] = BytesReceived; Port[ Index ].In += 1; if ( DATA_SAMPLES <= Port[ Index ].In ) { Port[ Index ].In = 0; } // // Separate the samples // if ( DATA_SAMPLES == Port[ Index ].Samples ) { Print ( L"---------- Stable average ----------\r\n" ); } Port[ Index ].Samples += 1; // // Compute the data rate // TotalBytes = 0; for ( Count = 0; DATA_SAMPLES > Count; Count++ ) { TotalBytes += Port[ Index ].BytesReceived[ Count ]; } Average = (UINT32)RShiftU64 ( TotalBytes, DATA_SAMPLE_SHIFT ); BitsPerSecond = Average * 8; // // Display the data rate // if (( RANGE_SWITCH >> 10 ) > Average ) { Print ( L"Ave: %d Bytes/Sec, %Ld Bits/sec\r\n", Average, BitsPerSecond ); } else { BitsPerSecond /= 1000; if ( RANGE_SWITCH > Average ) { Print ( L"Ave: %d.%03d KiBytes/Sec, %Ld KBits/sec\r\n", Average >> 10, (( Average & 0x3ff ) * 1000 ) >> 10, BitsPerSecond ); } else { BitsPerSecond /= 1000; Average >>= 10; if ( RANGE_SWITCH > Average ) { Print ( L"Ave: %d.%03d MiBytes/Sec, %Ld MBits/sec\r\n", Average >> 10, (( Average & 0x3ff ) * 1000 ) >> 10, BitsPerSecond ); } else { BitsPerSecond /= 1000; Average >>= 10; if ( RANGE_SWITCH > Average ) { Print ( L"Ave: %d.%03d GiBytes/Sec, %Ld GBits/sec\r\n", Average >> 10, (( Average & 0x3ff ) * 1000 ) >> 10, BitsPerSecond ); } else { BitsPerSecond /= 1000; Average >>= 10; if ( RANGE_SWITCH > Average ) { Print ( L"Ave: %d.%03d TiBytes/Sec, %Ld TBits/sec\r\n", Average >> 10, (( Average & 0x3ff ) * 1000 ) >> 10, BitsPerSecond ); } else { BitsPerSecond /= 1000; Average >>= 10; Print ( L"Ave: %d.%03d PiBytes/Sec, %Ld PBits/sec\r\n", Average >> 10, (( Average & 0x3ff ) * 1000 ) >> 10, BitsPerSecond ); } } } } } } } } /** Create the timer @retval EFI_SUCCESS The timer was successfully created @retval Other Timer initialization failed **/ EFI_STATUS TimerCreate ( ) { EFI_STATUS Status; // // Create the timer // Status = gBS->CreateEvent ( EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_DATASINK, TimerCallback, NULL, &pTimer ); if ( EFI_ERROR ( Status )) { 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 **/ EFI_STATUS TimerStop ( ) { EFI_STATUS Status; // // Assume success // Status = EFI_SUCCESS; // // Determine if the timer is running // if ( bTimerRunning ) { // // Stop the timer // Status = gBS->SetTimer ( pTimer, TimerCancel, 0 ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to stop the timer, Status: %r\r\n", Status )); } else { // // Timer timer is now stopped // bTimerRunning = FALSE; 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 **/ EFI_STATUS TimerStart ( UINTN Milliseconds ) { EFI_STATUS Status; UINT64 TimeDelay; // // Stop the timer if necessary // Status = EFI_SUCCESS; if ( bTimerRunning ) { Status = TimerStop ( ); } if ( !EFI_ERROR ( Status )) { // // Compute the new delay // TimeDelay = Milliseconds; TimeDelay *= 1000 * 10; // // Start the timer // Status = gBS->SetTimer ( pTimer, TimerPeriodic, TimeDelay ); if ( EFI_ERROR ( Status )) { DEBUG (( DEBUG_ERROR, "ERROR - Failed to start the timer, Status: %r\r\n", Status )); } else { // // The timer is now running // bTimerRunning = TRUE; 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 **/ EFI_STATUS TimerDestroy ( ) { EFI_STATUS Status; // // Assume success // Status = EFI_SUCCESS; // // Determine if the timer is running // if ( bTimerRunning ) { // // Stop the timer // Status = TimerStop ( ); } if (( !EFI_ERROR ( Status )) && ( NULL != pTimer )) { // // Done with this timer // Status = gBS->CloseEvent ( pTimer ); if ( EFI_ERROR ( Status )) { 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 )); pTimer = NULL; } } // // Return the operation status // return Status; } /** Receive data from the DataSource 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 ( IN int Argc, IN char **Argv ) { sa_family_t Family; EFI_STATUS Status; DEBUG (( DEBUG_INFO, "DataSink starting\r\n" )); // // Determine the family to use // Family = ( 1 < Argc ) ? AF_INET6 : AF_INET; // // Use for/break instead of goto // for ( ; ; ) { // // Create the timer // bTick = TRUE; Status = TimerCreate ( ); if ( EFI_ERROR ( Status )) { break; } // // Start a timer to perform network polling and display updates // Status = TimerStart ( 1 * 1000 ); if ( EFI_ERROR ( Status )) { break; } // // Loop forever waiting for abuse // do { ListenSocket = -1; do { // // Complete any client operations // Status = SocketPoll ( ); if ( EFI_ERROR ( Status )) { // // Control-C // break; } // // Wait for a while // } while ( !bTick ); if ( EFI_ERROR ( Status )) { // // Control-C // break; } // // Wait for the network layer to initialize // Status = SocketNew ( Family ); if ( EFI_ERROR ( Status )) { continue; } // // Wait for the remote network application to start // Status = SocketAccept ( ); if ( EFI_NOT_STARTED == Status ) { Status = SocketClose ( ); continue; } else if ( EFI_SUCCESS != Status ) { // // Control-C // break; } // // Receive data until the connection breaks // do { Status = SocketPoll ( ); } while ( !EFI_ERROR ( Status )); // // Done with the socket // Status = SocketClose ( ); } while ( !EFI_ERROR ( Status )); // // Close the socket if necessary // SocketClose ( ); // // All done // break; } // // Stop the timer if necessary // TimerStop ( ); TimerDestroy ( ); // // Return the operation status // DEBUG (( DEBUG_INFO, "DataSink exiting, Status: %r\r\n", Status )); return Status; }