summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-22 20:22:27 +0000
committerlpleahy <lpleahy@6f19259b-4bc3-4df7-8a09-765794883524>2011-09-22 20:22:27 +0000
commit57ad09b9ccd387f3b9468247c3a8f0c536a21579 (patch)
tree862a13dc168604c654a5d5394d88804b04a53ade
parent855f5eb0eb0d2a68d2d86f4c39955b5ab513f0a1 (diff)
downloadedk2-57ad09b9ccd387f3b9468247c3a8f0c536a21579.zip
edk2-57ad09b9ccd387f3b9468247c3a8f0c536a21579.tar.gz
edk2-57ad09b9ccd387f3b9468247c3a8f0c536a21579.tar.bz2
Update the receive engine to use multiple buffers instead of a single buffer.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/branches/EADK@12403 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--StdLib/EfiSocketLib/Ip4.c366
-rw-r--r--StdLib/EfiSocketLib/Socket.c502
-rw-r--r--StdLib/EfiSocketLib/Socket.h120
-rw-r--r--StdLib/EfiSocketLib/Tcp4.c278
-rw-r--r--StdLib/EfiSocketLib/Udp4.c361
-rw-r--r--StdLib/Include/Efi/EfiSocketLib.h1
6 files changed, 553 insertions, 1075 deletions
diff --git a/StdLib/EfiSocketLib/Ip4.c b/StdLib/EfiSocketLib/Ip4.c
index 38cea89..ad68820 100644
--- a/StdLib/EfiSocketLib/Ip4.c
+++ b/StdLib/EfiSocketLib/Ip4.c
@@ -16,29 +16,6 @@
/**
- Process the receive completion
-
- This routine keeps the IPv4 driver's buffer and queues it in
- in FIFO order to the data queue. The IP4 driver's buffer will
- be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
- See the \ref Tcp4ReceiveEngine section.
-
- This routine is called by the IPv4 driver when data is
- received.
-
- @param [in] Event The receive completion event
-
- @param [in] pPort The address of an ::ESL_PORT structure
-
-**/
-VOID
-EslIp4RxComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- );
-
-
-/**
Get the local socket address
This routine returns the IPv4 address associated with the local
@@ -84,7 +61,7 @@ EslIp4LocalAddressGet (
This support routine is called by ::EslSocketPortAllocate.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] pSockAddr Address of a sockaddr structure that contains the
connection point on the local machine. An IPv4 address
of INADDR_ANY specifies that the connection is made to
@@ -341,7 +318,7 @@ EslIp4OptionSet (
to connect the socket with the underlying network adapter
running the IPv4 protocol.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] DebugFlags Flags for debug messages
@retval EFI_SUCCESS - Socket successfully created
@@ -354,128 +331,46 @@ EslIp4PortAllocate (
)
{
EFI_IP4_CONFIG_DATA * pConfig;
- ESL_IP4_CONTEXT * pIp4;
ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Use for/break instead of goto
- for ( ; ; ) {
- //
- // Allocate the receive event
- //
- pSocket = pPort->pSocket;
- pIp4 = &pPort->Context.Ip4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslIp4RxComplete,
- pPort,
- &pIp4->RxToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the receive event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_RX | DEBUG_POOL,
- "0x%08x: Created receive event\r\n",
- pIp4->RxToken.Event ));
-
- //
- // Initialize the port
- //
- pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );
- pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );
- pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );
-
- //
- // Save the transmit address
- //
- pPort->pfnTxStart = (PFN_NET_TX_START)pPort->pProtocol.IPv4->Transmit;
-
- //
- // Set the configuration flags
- //
- pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
- pConfig->AcceptIcmpErrors = FALSE;
- pConfig->AcceptBroadcast = FALSE;
- pConfig->AcceptPromiscuous = FALSE;
- pConfig->TypeOfService = 0;
- pConfig->TimeToLive = 255;
- pConfig->DoNotFragment = FALSE;
- pConfig->RawData = FALSE;
- pConfig->ReceiveTimeout = 0;
- pConfig->TransmitTimeout = 0;
-
- //
- // Set the default protocol
- //
- pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;
- pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );
- break;
- }
+ // Initialize the port
+ //
+ pSocket = pPort->pSocket;
+ pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );
+ pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );
+ pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );
//
- // Return the operation status
+ // Save the cancel, receive and transmit addresses
//
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Close an IP4 port.
-
- This routine releases the resources allocated by
- ::EslIp4PortAllocate.
-
- This routine is called by ::EslSocketPortClose.
- See the \ref PortCloseStateMachine section.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed
- @retval other Port close error
-
-**/
-EFI_STATUS
-EslIp4PortClose (
- IN ESL_PORT * pPort
- )
-{
- UINTN DebugFlags;
- ESL_IP4_CONTEXT * pIp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;
+ pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;
+ pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;
//
- // Assume success
+ // Set the configuration flags
//
- Status = EFI_SUCCESS;
- DebugFlags = pPort->DebugFlags;
- pIp4 = &pPort->Context.Ip4;
+ pConfig = &pPort->Context.Ip4.ModeData.ConfigData;
+ pConfig->AcceptIcmpErrors = FALSE;
+ pConfig->AcceptBroadcast = FALSE;
+ pConfig->AcceptPromiscuous = FALSE;
+ pConfig->TypeOfService = 0;
+ pConfig->TimeToLive = 255;
+ pConfig->DoNotFragment = FALSE;
+ pConfig->RawData = FALSE;
+ pConfig->ReceiveTimeout = 0;
+ pConfig->TransmitTimeout = 0;
//
- // Done with the receive event
+ // Set the default protocol
//
- if ( NULL != pIp4->RxToken.Event ) {
- Status = gBS->CloseEvent ( pIp4->RxToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed receive event\r\n",
- pIp4->RxToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the receive event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
+ pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;
+ pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );
+ Status = EFI_SUCCESS;
//
// Return the operation status
@@ -514,67 +409,15 @@ EslIp4PortClosePacketFree (
*pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;
//
- // Return the buffer to the IP4 driver
- //
- gBS->SignalEvent ( pPacket->Op.Ip4Rx.pRxData->RecycleSignal );
- DBG_EXIT ( );
-}
-
-
-/**
- Perform the network specific close operation on the port.
-
- This routine performs a cancel operations on the IPv4 port to
- shutdown the receive operations on the port.
-
- This routine is called by the ::EslSocketPortCloseTxDone
- routine after the port completes all of the transmission.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
-
-**/
-EFI_STATUS
-EslIp4PortCloseRxStop (
- IN ESL_PORT * pPort
- )
-{
- ESL_IP4_CONTEXT * pIp4;
- EFI_IP4_PROTOCOL * pIp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Reset the port, cancel the outstanding receive
+ // Disconnect the buffer from the packet
//
- pIp4 = &pPort->Context.Ip4;
- pIp4Protocol = pPort->pProtocol.IPv4;
- Status = pIp4Protocol->Cancel ( pIp4Protocol,
- &pPort->Context.Ip4.RxToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Packet receive aborted on port: 0x%08x\r\n",
- pPort->pReceivePending,
- pPort ));
- }
- else {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Packet receive pending on Port 0x%08x\r\n",
- pPort->pReceivePending,
- pPort ));
- Status = EFI_SUCCESS;
- }
+ pPacket->Op.Ip4Rx.pRxData = NULL;
//
- // Return the operation status
+ // Return the buffer to the IP4 driver
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ gBS->SignalEvent ( pRxData->RecycleSignal );
+ DBG_EXIT ( );
}
@@ -784,97 +627,31 @@ EslIp4RemoteAddressSet (
/**
- Cancel the receive operations
-
- This routine cancels the pending receive operations.
- See the \ref Ip4ReceiveEngine section.
-
- This routine is called by ::EslSocketShutdown when the socket
- layer is being shutdown.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure
-
- @retval EFI_SUCCESS - The cancel was successful
-
- **/
-EFI_STATUS
-EslIp4RxCancel (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_IP4_CONTEXT * pIp4;
- EFI_IP4_PROTOCOL * pIp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume failure
- //
- Status = EFI_NOT_FOUND;
-
- //
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if a receive is pending
- //
- pIp4 = &pPort->Context.Ip4;
- pPacket = pPort->pReceivePending;
- if ( NULL != pPacket ) {
- //
- // Attempt to cancel the receive operation
- //
- pIp4Protocol = pPort->pProtocol.IPv4;
- Status = pIp4Protocol->Cancel ( pIp4Protocol,
- &pIp4->RxToken );
- if ( EFI_NOT_FOUND == Status ) {
- //
- // The receive is complete
- //
- Status = EFI_SUCCESS;
- }
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
Process the receive completion
This routine keeps the IPv4 driver's buffer and queues it in
in FIFO order to the data queue. The IP4 driver's buffer will
be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.
- See the \ref Tcp4ReceiveEngine section.
+ See the \ref ReceiveEngine section.
This routine is called by the IPv4 driver when data is
received.
@param [in] Event The receive completion event
- @param [in] pPort The address of an ::ESL_PORT structure
+ @param [in] pIo The address of an ::ESL_IO_MGMT structure
**/
VOID
EslIp4RxComplete (
IN EFI_EVENT Event,
- IN ESL_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
size_t LengthInBytes;
+ ESL_PORT * pPort;
ESL_PACKET * pPacket;
EFI_IP4_RECEIVE_DATA * pRxData;
- ESL_IP4_CONTEXT * pIp4;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -882,85 +659,37 @@ EslIp4RxComplete (
//
// Get the operation status.
//
- pIp4 = &pPort->Context.Ip4;
- Status = pIp4->RxToken.Status;
+ pPort = pIo->pPort;
+ Status = pIo->Token.Ip4Rx.Status;
//
// Get the packet length
//
- pRxData = pIp4->RxToken.Packet.RxData;
+ pRxData = pIo->Token.Ip4Rx.Packet.RxData;
LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;
//
// Save the data in the packet
//
- pPacket = pPort->pReceivePending;
+ pPacket = pIo->pPacket;
pPacket->Op.Ip4Rx.pRxData = pRxData;
//
// Complete this request
//
- EslSocketRxComplete ( pPort, Status, LengthInBytes, FALSE );
+ EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
DBG_EXIT ( );
}
/**
- Start a receive operation
-
- This routine posts a receive buffer to the IPv4 driver.
- See the \ref ReceiveEngine section.
-
- This support routine is called by EslSocketRxStart.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pPacket Address of an ::ESL_PACKET structure.
-
- @retval EFI_SUCCESS Receive operation started successfully
-
- **/
-EFI_STATUS
-EslIp4RxStart (
- IN ESL_PORT * pPort,
- IN ESL_PACKET * pPacket
- )
-{
- ESL_IP4_CONTEXT * pIp4;
- EFI_IP4_PROTOCOL * pIp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Initialize the buffer for receive
- //
- pPacket->Op.Ip4Rx.pRxData = NULL;
- pIp4 = &pPort->Context.Ip4;
- pIp4->RxToken.Packet.RxData = NULL;
-
- //
- // Start the receive on the packet
- //
- pIp4Protocol = pPort->pProtocol.IPv4;
- Status = pIp4Protocol->Receive ( pIp4Protocol,
- &pIp4->RxToken );
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
Determine if the socket is configured.
This routine uses the flag ESL_SOCKET::bConfigured to determine
if the network layer's configuration routine has been called.
This routine calls the ::EslSocketBind and configuration routines
if they were not already called. After the port is configured,
- the \ref Ip4ReceiveEngine is started.
+ the \ref ReceiveEngine is started.
This routine is called by EslSocketIsConfigured to verify
that the socket is configured.
@@ -1260,6 +989,7 @@ EslIp4TxBuffer (
sizeof ( pPacket->Op.Ip4Tx )
- sizeof ( pPacket->Op.Ip4Tx.Buffer )
+ BufferLength,
+ 0,
DEBUG_TX );
if ( !EFI_ERROR ( Status )) {
//
@@ -1483,6 +1213,8 @@ CONST ESL_PROTOCOL_API cEslIp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
+ sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),
+ OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),
FALSE,
NULL, // Accept
NULL, // ConnectPoll
@@ -1494,15 +1226,15 @@ CONST ESL_PROTOCOL_API cEslIp4Api = {
EslIp4OptionGet,
EslIp4OptionSet,
EslIp4PortAllocate,
- EslIp4PortClose,
+ NULL, // PortClose
+ NULL, // PortCloseOp
EslIp4PortClosePacketFree,
- EslIp4PortCloseRxStop,
TRUE,
EslIp4Receive,
EslIp4RemoteAddressGet,
EslIp4RemoteAddressSet,
- EslIp4RxCancel,
- EslIp4RxStart,
+ EslIp4RxComplete,
+ NULL, // RxStart
EslIp4TxBuffer,
EslIp4TxComplete,
NULL // TxOobComplete
diff --git a/StdLib/EfiSocketLib/Socket.c b/StdLib/EfiSocketLib/Socket.c
index cf3c32c..1f82a6f 100644
--- a/StdLib/EfiSocketLib/Socket.c
+++ b/StdLib/EfiSocketLib/Socket.c
@@ -29,9 +29,8 @@
operations to complete. After all of the transmits are complete,
this routine discards any receive buffers using a network specific
support routine via ESL_PROTOCOL_API::pfnPortClosePktFree. This
- routine also calls a network specific helper routine via
- ESL_PROTOCOL_API::pfnPortCloseRxStop to abort the pending receive
- operation.
+ routine also calls ::EslSocketRxCancel to abort the pending receive
+ operations.
</li>
<li>State: PORT_STATE_CLOSE_TX_DONE</li>
<li>Arc: ::EslSocketPortCloseRxDone - Waits until all of the receive
@@ -41,13 +40,8 @@
when the port is closed.
<li>State: PORT_STATE_CLOSE_DONE</li>
<li>Arc: ::EslSocketPortClose - Releases the port resources allocated
- by ::EslSocketPortAllocate. Calls ESL_PROTOCOL_API::pfnPortClose to
- close the network specific resources:
- <ul>
- <li>::EslIp4PortClose</li>
- <li>::EslTcp4PortClose</li>
- <li>::EslUp4PortClose</li>
- </ul>
+ by ::EslSocketPortAllocate. Calls ::EslTcp4PortClose via
+ ESL_PROTOCOL_API::pfnPortClose to close the TCP port.
</li>
</ul>
Note that the state machine takes into account that close and receive
@@ -56,24 +50,29 @@
\section ReceiveEngine Receive Engine
- The receive engine is started by calling ::EslSocketRxStart when the
- ::ESL_PORT structure is allocated and stopped when ::EslSocketPortCloseTxDone
- calls the network specific close operation. The receive engine consists
- of a single receive buffer that is posted to the network driver.
-
- Upon receive completion, ::EslSocketRxComplete queues the packet of data
- to either the ESL_SOCKET::pRxOobPacketListTail or ESL_SOCKET::pRxPacketListTail
- depending on whether urgent or normal data was received. To minimize the
- number of buffer copies, the data is not moved until the application makes
- a receive call.
-
- When the application wants to receive data it indirectly calls
- ::EslSocketReceive to remove data from the data queue. This routine
- removes the next available packet from ESL_SOCKET::pRxOobPacketListHead or
- ESL_SOCKET::pRxPacketListHead and copies the data from the packet
- into the application's buffer. For SOCK_STREAM sockets, if the packet
- contains more data then it remains around for the next application receive
- operation, otherwise the packet is placed on the free queue.
+ The receive engine consists of a set of ::ESL_IO_MGMT structures that are allocated
+ along with the ::ESL_PORT structure in ::EslSocketPortAllocate. The ESL_IO_MGMT
+ structure contains the network layer specific receive completion token and event.
+
+ The receive engine is started by calling ::EslSocketRxStart sometime after the
+ ::ESL_PORT structure is allocated. Flow control pauses the receive engine when
+ the amount of receive data waiting for the application meets or exceeds MAX_RX_DATA.
+ Finally, the receive engine is shutdown by ::EslSocketPortCloseTxDone during the
+ port close operation.
+
+ ::EslSocketRxStart connects an ::ESL_PACKET structure to the ::ESL_IO_MGMT structure
+ and then calls the network layer to start the receive operation. Upon
+ receive completion, ::EslSocketRxComplete breaks the connection between these
+ structrues and places the ESL_IO_MGMT structure on to the ESL_PORT::pRxFree list to
+ make it available for another receive operation. EslSocketRxComplete then queues
+ the ESL_PACKET structure (data packet) to either the ESL_SOCKET::pRxOobPacketListTail
+ or ESL_SOCKET::pRxPacketListTail depending on whether urgent or normal data was
+ received. Finally ::EslSocketRxComplete attempts to start another receive operation.
+
+ To minimize the number of buffer copies, the data is not copied until the
+ application makes a receive call. At this point socket performs a single copy
+ in the receive path to move the data from the buffer filled by the network layer
+ into the application's buffer.
The IP4 and UDP4 drivers go one step further to reduce buffer copies. They
allow the socket layer to hold on to the actual receive buffer until the
@@ -81,25 +80,29 @@
of theses operations return the buffer to the lower layer network driver
by calling ESL_PROTOCOL_API::pfnPortClosePktFree.
+ When a socket application wants to receive data it indirectly calls
+ ::EslSocketReceive to remove data from the receive data queue. This routine
+ removes the next available packet from ESL_SOCKET::pRxOobPacketListHead or
+ ESL_SOCKET::pRxPacketListHead and copies the data from the packet
+ into the application's buffer. For SOCK_STREAM sockets, if the packet
+ contains more data then the ESL_PACKET structures remains at the head of the
+ receive queue for the next application receive
+ operation. For SOCK_DGRAM, SOCK_RAW and SOCK_SEQ_PACKET sockets, the ::ESL_PACKET
+ structure is removed from the head of the receive queue and any remaining data is
+ "discarded" as the packet is placed on the free queue.
- During socket layer shutdown the lower layer RxCancel routine is called by
- ::EslSocketShutdown to cancel the pending receive operations. These routines
- are:
- <ul>
- <li>::EslIp4RxCancel</li>
- <li>::EslTcp4RxCancel</li>
- <li>::EslUdp4RxCancel</li>
- </ul>
+ During socket layer shutdown, ::EslSocketShutdown calls ::EslSocketRxCancel to
+ cancel any pending receive operations.
- Receive flow control is applied when the socket is created, since no receive
- operation is pending to the low layer network driver. The flow control gets
+ Receive flow control is applied when the port is created, since no receive
+ operation are pending to the low layer network driver. The flow control gets
released when the low layer network port is configured or the first receive
operation is posted. Flow control remains in the released state until the
maximum buffer space is consumed. During this time, ::EslSocketRxComplete
calls ::EslSocketRxStart. Flow control is applied in EslSocketRxComplete
by skipping the call to EslSocketRxStart. Flow control is eventually
- released when the buffer space drops below the maximum amount and
- EslSocketReceive calls EslSocketRxStart.
+ released in ::EslSocketReceive when the buffer space drops below the
+ maximum amount causing EslSocketReceive to call EslSocketRxStart.
\section TransmitEngine Transmit Engine
@@ -146,22 +149,25 @@ CONST ESL_SOCKET_BINDING cEslSocketBinding[] = {
&gEfiIp4ProtocolGuid,
&mEslIp4ServiceGuid,
OFFSET_OF ( ESL_LAYER, pIp4List ),
- 4,
- 0 },
+ 4, // RX buffers
+ 4, // TX buffers
+ 0 }, // TX Oob buffers
{ L"Tcp4",
&gEfiTcp4ServiceBindingProtocolGuid,
&gEfiTcp4ProtocolGuid,
&mEslTcp4ServiceGuid,
OFFSET_OF ( ESL_LAYER, pTcp4List ),
- 4,
- 4 },
+ 4, // RX buffers
+ 4, // TX buffers
+ 4 }, // TX Oob buffers
{ L"Udp4",
&gEfiUdp4ServiceBindingProtocolGuid,
&gEfiUdp4ProtocolGuid,
&mEslUdp4ServiceGuid,
OFFSET_OF ( ESL_LAYER, pUdp4List ),
- 4,
- 0 }
+ 4, // RX buffers
+ 4, // TX buffers
+ 0 } // TX Oob buffers
};
CONST UINTN cEslSocketBindingEntries = DIM ( cEslSocketBinding );
@@ -1300,7 +1306,7 @@ EslSocketConnect (
}
else {
DEBUG (( DEBUG_CONNECT,
- "ERROR - Invalid TCP4 address length: %d\r\n",
+ "ERROR - Invalid address length: %d\r\n",
SockAddrLength ));
Status = EFI_INVALID_PARAMETER;
pSocket->errno = EINVAL;
@@ -2546,6 +2552,7 @@ EslSocketOptionSet (
@param [in] ppPacket Address to receive the ::ESL_PACKET structure
@param [in] LengthInBytes Length of the packet structure
+ @param [in] ZeroBytes Length of packet to zero
@param [in] DebugFlags Flags for debug messages
@retval EFI_SUCCESS - The packet was allocated successfully
@@ -2555,6 +2562,7 @@ EFI_STATUS
EslSocketPacketAllocate (
IN ESL_PACKET ** ppPacket,
IN size_t LengthInBytes,
+ IN size_t ZeroBytes,
IN UINTN DebugFlags
)
{
@@ -2576,6 +2584,9 @@ EslSocketPacketAllocate (
"0x%08x: Allocate pPacket, %d bytes\r\n",
pPacket,
LengthInBytes ));
+ if ( 0 != ZeroBytes ) {
+ ZeroMem ( &pPacket->Op, ZeroBytes );
+ }
pPacket->PacketSize = LengthInBytes;
}
else {
@@ -2828,7 +2839,7 @@ EslSocketPoll (
@param [in] pSocket Address of an ::ESL_SOCKET structure.
@param [in] pService Address of an ::ESL_SERVICE structure.
- @param [in] ChildHandle TCP4 child handle
+ @param [in] ChildHandle Network protocol child handle
@param [in] pSockAddr Address of a sockaddr structure that contains the
connection point on the local machine. An IPv4 address
of INADDR_ANY specifies that the connection is made to
@@ -2881,7 +2892,8 @@ EslSocketPortAllocate (
pLayer = &mEslLayer;
LengthInBytes = sizeof ( *pPort )
+ ESL_STRUCTURE_ALIGNMENT_BYTES
- + (( pSocketBinding->TxIoNormal
+ + (( pSocketBinding->RxIo
+ + pSocketBinding->TxIoNormal
+ pSocketBinding->TxIoUrgent )
* sizeof ( ESL_IO_MGMT ));
Status = gBS->AllocatePool ( EfiRuntimeServicesData,
@@ -2948,12 +2960,29 @@ EslSocketPortAllocate (
pSocket->pApi->pfnLocalAddrSet ( pPort, pSockAddr );
//
- // Initialize the urgent transmit structures
+ // Initialize the receive structures
//
pBuffer = (UINT8 *)&pPort[ 1 ];
pBuffer = &pBuffer[ ESL_STRUCTURE_ALIGNMENT_BYTES ];
pBuffer = (UINT8 *)( ESL_STRUCTURE_ALIGNMENT_MASK & (UINTN)pBuffer );
pIo = (ESL_IO_MGMT *)pBuffer;
+ if (( 0 != pSocketBinding->RxIo )
+ && ( NULL != pSocket->pApi->pfnRxComplete )) {
+ Status = EslSocketIoInit ( pPort,
+ &pIo,
+ pSocketBinding->RxIo,
+ &pPort->pRxFree,
+ DebugFlags | DEBUG_POOL,
+ "receive",
+ pSocket->pApi->pfnRxComplete );
+ if ( EFI_ERROR ( Status )) {
+ break;
+ }
+ }
+
+ //
+ // Initialize the urgent transmit structures
+ //
if (( 0 != pSocketBinding->TxIoUrgent )
&& ( NULL != pSocket->pApi->pfnTxOobComplete )) {
Status = EslSocketIoInit ( pPort,
@@ -3083,7 +3112,6 @@ EslSocketPortClose (
EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;
CONST ESL_SOCKET_BINDING * pSocketBinding;
ESL_SOCKET * pSocket;
- ESL_TCP4_CONTEXT * pTcp4;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -3157,11 +3185,10 @@ EslSocketPortClose (
//
// Empty the urgent receive queue
//
- pTcp4 = &pPort->Context.Tcp4;
while ( NULL != pSocket->pRxOobPacketListHead ) {
pPacket = pSocket->pRxOobPacketListHead;
pSocket->pRxOobPacketListHead = pPacket->pNext;
- pSocket->RxOobBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
+ pSocket->pApi->pfnPortClosePktFree ( pPacket, &pSocket->RxOobBytes );
EslSocketPacketFree ( pPacket, DEBUG_RX );
}
pSocket->pRxOobPacketListTail = NULL;
@@ -3173,7 +3200,7 @@ EslSocketPortClose (
while ( NULL != pSocket->pRxPacketListHead ) {
pPacket = pSocket->pRxPacketListHead;
pSocket->pRxPacketListHead = pPacket->pNext;
- pSocket->RxBytes -= pPacket->Op.Tcp4Rx.ValidBytes;
+ pSocket->pApi->pfnPortClosePktFree ( pPacket, &pSocket->RxBytes );
EslSocketPacketFree ( pPacket, DEBUG_RX );
}
pSocket->pRxPacketListTail = NULL;
@@ -3191,7 +3218,9 @@ EslSocketPortClose (
//
// Release the network specific resources
//
- Status = pSocket->pApi->pfnPortClose ( pPort );
+ if ( NULL != pSocket->pApi->pfnPortClose ) {
+ Status = pSocket->pApi->pfnPortClose ( pPort );
+ }
//
// Done with the normal transmit events
@@ -3210,6 +3239,14 @@ EslSocketPortClose (
"urgent transmit" );
//
+ // Done with the receive events
+ //
+ Status = EslSocketIoFree ( pPort,
+ &pPort->pRxFree,
+ DebugFlags | DEBUG_POOL,
+ "receive" );
+
+ //
// Done with the lower layer network protocol
//
pSocketBinding = pPort->pSocketBinding;
@@ -3337,11 +3374,9 @@ EslSocketPortCloseComplete (
This routine is called by
<ul>
- <li>::EslIp4RxComplete</li>
<li>::EslSocketPortCloseComplete</li>
<li>::EslSocketPortCloseTxDone</li>
- <li>::EslTcp4RxComplete/li>
- <li>::EslUdp4RxComplete</li>
+ <li>::EslSocketRxComplete</li>
</ul>
to determine the state of the receive operations.
See the \ref PortCloseStateMachine section.
@@ -3359,6 +3394,7 @@ EslSocketPortCloseRxDone (
IN ESL_PORT * pPort
)
{
+ ESL_IO_MGMT * pIo;
PORT_STATE PortState;
ESL_SOCKET * pSocket;
EFI_STATUS Status;
@@ -3381,7 +3417,7 @@ EslSocketPortCloseRxDone (
// Determine if the receive operation is pending
//
Status = EFI_NOT_READY;
- if ( NULL == pPort->pReceivePending ) {
+ if ( NULL == pPort->pRxActive ) {
//
// The receive operation is complete
// Update the port state
@@ -3416,9 +3452,13 @@ EslSocketPortCloseRxDone (
DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
"0x%08x: Port Close: Receive still pending!\r\n",
pPort ));
- DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Packet pending on network adapter\r\n",
- pPort->pReceivePending ));
+ pIo = pPort->pRxActive;
+ while ( NULL != pIo ) {
+ DEBUG (( DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Packet pending on network adapter\r\n",
+ pIo->pPacket ));
+ pIo = pIo->pNext;
+ }
}
}
@@ -3504,7 +3544,7 @@ EslSocketPortCloseStart (
This routine determines the state of the transmit engine and
continue the close operation after the transmission is complete.
- The next step is to stop the \ref Tcp4ReceiveEngine.
+ The next step is to stop the \ref ReceiveEngine.
See the \ref PortCloseStateMachine section.
This routine is called by ::EslSocketPortCloseStart to determine
@@ -3575,45 +3615,22 @@ EslSocketPortCloseTxDone (
pPort ));
//
- // Empty the normal receive queue
- //
- while ( NULL != pSocket->pRxPacketListHead ) {
- pPacket = pSocket->pRxPacketListHead;
- pSocket->pRxPacketListHead = pPacket->pNext;
- pSocket->pApi->pfnPortClosePktFree ( pPacket, &pSocket->RxBytes );
-
- //
- // Done with this packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
- }
- pSocket->pRxPacketListTail = NULL;
- ASSERT ( 0 == pSocket->RxBytes );
-
- //
- // Empty the urgent receive queue
+ // Shutdown the receive operation on the port
//
- while ( NULL != pSocket->pRxOobPacketListHead ) {
- pPacket = pSocket->pRxOobPacketListHead;
- pSocket->pRxOobPacketListHead = pPacket->pNext;
- pSocket->pApi->pfnPortClosePktFree ( pPacket, &pSocket->RxOobBytes );
-
- //
- // Done with this packet
- //
- EslSocketPacketFree ( pPacket, DEBUG_RX );
+ pIo = pPort->pRxActive;
+ while ( NULL != pIo ) {
+ EslSocketRxCancel ( pPort, pIo );
+ pIo = pIo->pNext;
}
- pSocket->pRxOobPacketListTail = NULL;
- ASSERT ( 0 == pSocket->RxOobBytes );
//
- // Shutdown the receive operation on the port
+ // Close the port
//
Status = EFI_SUCCESS;
- if ( NULL != pPort->pReceivePending ) {
- Status = pSocket->pApi->pfnPortCloseRxStop ( pPort );
- ASSERT ( EFI_SUCCESS == Status );
+ if ( NULL != pSocket->pApi->pfnPortCloseOp ) {
+ Status = pSocket->pApi->pfnPortCloseOp ( pPort );
}
+ ASSERT ( EFI_SUCCESS == Status );
}
//
@@ -3920,9 +3937,9 @@ EslSocketReceive (
pPacket ));
//
- // Restart this receive operation if necessary
+ // Restart the receive operation if necessary
//
- if (( NULL == pPort->pReceivePending )
+ if (( NULL != pPort->pRxFree )
&& ( MAX_RX_DATA > pSocket->RxBytes )) {
EslSocketRxStart ( pPort );
}
@@ -4055,6 +4072,50 @@ EslSocketReceive (
/**
+ Cancel the receive operations
+
+ This routine cancels a pending receive operation.
+ See the \ref ReceiveEngine section.
+
+ This routine is called by ::EslSocketShutdown when the socket
+ layer is being shutdown.
+
+ @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
+
+ **/
+VOID
+EslSocketRxCancel (
+ IN ESL_PORT * pPort,
+ IN ESL_IO_MGMT * pIo
+ )
+{
+ EFI_STATUS Status;
+
+ DBG_ENTER ( );
+
+ //
+ // Cancel the outstanding receive
+ //
+ Status = pPort->pfnRxCancel ( pPort->pProtocol.v,
+ &pIo->Token );
+ if ( !EFI_ERROR ( Status )) {
+ DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Packet receive aborted on port: 0x%08x\r\n",
+ pIo->pPacket,
+ pPort ));
+ }
+ else {
+ DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
+ "0x%08x: Packet receive pending on Port 0x%08x\r\n",
+ pIo->pPacket,
+ pPort ));
+ }
+ DBG_EXIT ( );
+}
+
+
+/**
Process the receive completion
This routine queues the data in FIFO order in either the urgent
@@ -4068,7 +4129,7 @@ EslSocketReceive (
<li>::EslUdp4RxComplete</li>
</ul>
- @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
@param [in] Status Receive status
@param [in] LengthInBytes Length of the receive data
@param [in] bUrgent TRUE if urgent data is received and FALSE
@@ -4077,13 +4138,15 @@ EslSocketReceive (
**/
VOID
EslSocketRxComplete (
- IN ESL_PORT * pPort,
+ IN ESL_IO_MGMT * pIo,
IN EFI_STATUS Status,
IN UINTN LengthInBytes,
IN BOOLEAN bUrgent
)
{
+ ESL_IO_MGMT * pIoNext;
ESL_PACKET * pPacket;
+ ESL_PORT * pPort;
ESL_PACKET * pPrevious;
ESL_PACKET ** ppQueueHead;
ESL_PACKET ** ppQueueTail;
@@ -4093,15 +4156,37 @@ EslSocketRxComplete (
DBG_ENTER ( );
//
- // Mark this receive complete
+ // Locate the active receive packet
+ //
+ pPacket = pIo->pPacket;
+ pPort = pIo->pPort;
+ pSocket = pPort->pSocket;
+
+ //
+ // Remove the IO structure from the active list
+ //
+ pIoNext = pPort->pRxActive;
+ while (( NULL != pIoNext ) && ( pIoNext != pIo ) && ( pIoNext->pNext != pIo ))
+ {
+ pIoNext = pIoNext->pNext;
+ }
+ ASSERT ( NULL != pIoNext );
+ if ( pIoNext == pIo ) {
+ pPort->pRxActive = pIo->pNext; // Beginning of list
+ }
+ else {
+ pIoNext->pNext = pIo->pNext; // Middle of list
+ }
+
+ //
+ // Free the IO structure
//
- pPacket = pPort->pReceivePending;
- pPort->pReceivePending = NULL;
+ pIo->pNext = pPort->pRxFree;
+ pPort->pRxFree = pIo;
//
// Determine the queue to use
//
- pSocket = pPort->pSocket;
if ( bUrgent && ( !pSocket->bOobInLine )) {
ppQueueHead = &pSocket->pRxOobPacketListHead;
ppQueueTail = &pSocket->pRxOobPacketListTail;
@@ -4125,13 +4210,6 @@ EslSocketRxComplete (
*pRxBytes += LengthInBytes;
//
- // Set the buffer size and address
- //
- pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
- LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
- pPacket->Op.Tcp4Rx.ValidBytes = LengthInBytes;
-
- //
// Log the received data
//
DEBUG (( DEBUG_RX | DEBUG_INFO,
@@ -4236,6 +4314,8 @@ EslSocketRxStart (
IN ESL_PORT * pPort
)
{
+ UINT8 * pBuffer;
+ ESL_IO_MGMT * pIo;
ESL_PACKET * pPacket;
ESL_SOCKET * pSocket;
EFI_STATUS Status;
@@ -4249,57 +4329,82 @@ EslSocketRxStart (
pPacket = NULL;
pSocket = pPort->pSocket;
if ( !EFI_ERROR ( pPort->pSocket->RxError )) {
- if (( NULL == pPort->pReceivePending )
+ if (( NULL != pPort->pRxFree )
+ && ( !pSocket->bRxDisable )
&& ( PORT_STATE_CLOSE_STARTED > pPort->State )) {
//
- // Determine if there are any free packets
+ // Start all of the pending receive operations
//
- pPacket = pSocket->pRxFree;
- if ( NULL != pPacket ) {
- //
- // Remove this packet from the free list
+ while ( NULL != pPort->pRxFree ) {
//
- pSocket->pRxFree = pPacket->pNext;
- DEBUG (( DEBUG_RX,
- "0x%08x: Port removed packet 0x%08x from free list\r\n",
- pPort,
- pPacket ));
- }
- else {
+ // Determine if there are any free packets
//
- // Allocate a packet structure
- //
- Status = EslSocketPacketAllocate ( &pPacket,
- pSocket->pApi->RxPacketBytes,
- DEBUG_RX );
- if ( EFI_ERROR ( Status )) {
- pPacket = NULL;
- DEBUG (( DEBUG_ERROR | DEBUG_RX,
- "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
+ pPacket = pSocket->pRxFree;
+ if ( NULL != pPacket ) {
+ //
+ // Remove this packet from the free list
+ //
+ pSocket->pRxFree = pPacket->pNext;
+ DEBUG (( DEBUG_RX,
+ "0x%08x: Port removed packet 0x%08x from free list\r\n",
pPort,
- Status ));
+ pPacket ));
+ }
+ else {
+ //
+ // Allocate a packet structure
+ //
+ Status = EslSocketPacketAllocate ( &pPacket,
+ pSocket->pApi->RxPacketBytes,
+ pSocket->pApi->RxZeroBytes,
+ DEBUG_RX );
+ if ( EFI_ERROR ( Status )) {
+ pPacket = NULL;
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "0x%08x: Port failed to allocate RX packet, Status: %r\r\n",
+ pPort,
+ Status ));
+ break;
+ }
}
- }
- //
- // Determine if a packet is available
- //
- if ( NULL != pPacket ) {
//
- // Mark this receive as pending
+ // Connect the IO and packet structures
+ //
+ pIo = pPort->pRxFree;
+ pIo->pPacket = pPacket;
+
+ //
+ // Initialize the packet for receive
+ // No driver buffer for this packet
//
- pPort->pReceivePending = pPacket;
- pPacket->pNext = NULL;
+ pBuffer = (UINT8 *)pIo;
+ pBuffer = &pBuffer[ pSocket->pApi->RxBufferOffset ];
+ *(VOID **)pBuffer = NULL;
+ if ( NULL != pSocket->pApi->pfnRxStart ) {
+ pSocket->pApi->pfnRxStart ( pPort, pIo );
+ }
//
// Start the receive on the packet
//
- Status = pSocket->pApi->pfnRxStart ( pPort, pPacket );
+ Status = pPort->pfnRxStart ( pPort->pProtocol.v, &pIo->Token );
if ( !EFI_ERROR ( Status )) {
DEBUG (( DEBUG_RX | DEBUG_INFO,
"0x%08x: Packet receive pending on port 0x%08x\r\n",
pPacket,
pPort ));
+ //
+ // Allocate the receive control structure
+ //
+ pPort->pRxFree = pIo->pNext;
+
+ //
+ // Mark this receive as pending
+ //
+ pIo->pNext = pPort->pRxActive;
+ pPort->pRxActive = pIo;
+
}
else {
DEBUG (( DEBUG_RX | DEBUG_INFO,
@@ -4316,12 +4421,35 @@ EslSocketRxStart (
//
// Free the packet
//
- pPort->pReceivePending = NULL;
+ pIo->pPacket = NULL;
pPacket->pNext = pSocket->pRxFree;
pSocket->pRxFree = pPacket;
+ break;
}
}
}
+ else {
+ if ( NULL == pPort->pRxFree ) {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Port, no available ESL_IO_MGMT structures\r\n",
+ pPort));
+ }
+ if ( pSocket->bRxDisable ) {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Port, receive disabled!\r\n",
+ pPort ));
+ }
+ if ( PORT_STATE_CLOSE_STARTED <= pPort->State ) {
+ DEBUG (( DEBUG_RX | DEBUG_INFO,
+ "0x%08x: Port, is closing!\r\n",
+ pPort ));
+ }
+ }
+ }
+ else {
+ DEBUG (( DEBUG_ERROR | DEBUG_RX,
+ "ERROR - Previous receive error, Status: %r\r\n",
+ pPort->pSocket->RxError ));
}
DBG_EXIT ( );
@@ -4353,6 +4481,8 @@ EslSocketShutdown (
IN int * pErrno
)
{
+ ESL_IO_MGMT * pIo;
+ ESL_PORT * pPort;
ESL_SOCKET * pSocket;
EFI_STATUS Status;
EFI_TPL TplPrevious;
@@ -4376,53 +4506,63 @@ EslSocketShutdown (
//
if ( pSocket->bConnected ) {
//
- // Verify the API
+ // Validate the How value
//
- if ( NULL == pSocket->pApi->pfnRxCancel ) {
- Status = EFI_UNSUPPORTED;
- pSocket->errno = ENOTSUP;
- }
- else {
+ if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {
//
- // Validate the How value
+ // Synchronize with the socket layer
//
- if (( SHUT_RD <= How ) && ( SHUT_RDWR >= How )) {
- //
- // Synchronize with the socket layer
- //
- RAISE_TPL ( TplPrevious, TPL_SOCKETS );
+ RAISE_TPL ( TplPrevious, TPL_SOCKETS );
- //
- // Disable the receiver if requested
- //
- if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {
- pSocket->bRxDisable = TRUE;
- }
+ //
+ // Disable the receiver if requested
+ //
+ if (( SHUT_RD == How ) || ( SHUT_RDWR == How )) {
+ pSocket->bRxDisable = TRUE;
+ }
- //
- // Disable the transmitter if requested
- //
- if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {
- pSocket->bTxDisable = TRUE;
- }
+ //
+ // Disable the transmitter if requested
+ //
+ if (( SHUT_WR == How ) || ( SHUT_RDWR == How )) {
+ pSocket->bTxDisable = TRUE;
+ }
+ //
+ // Cancel the pending receive operations
+ //
+ if ( pSocket->bRxDisable ) {
//
- // Cancel the pending receive operation
+ // Walk the list of ports
//
- Status = pSocket->pApi->pfnRxCancel ( pSocket );
+ pPort = pSocket->pPortList;
+ while ( NULL != pPort ) {
+ //
+ // Walk the list of active receive operations
+ //
+ pIo = pPort->pRxActive;
+ while ( NULL != pIo ) {
+ EslSocketRxCancel ( pPort, pIo );
+ }
- //
- // Release the socket layer synchronization
- //
- RESTORE_TPL ( TplPrevious );
- }
- else {
- //
- // Invalid How value
- //
- pSocket->errno = EINVAL;
- Status = EFI_INVALID_PARAMETER;
+ //
+ // Set the next port
+ //
+ pPort = pPort->pLinkSocket;
+ }
}
+
+ //
+ // Release the socket layer synchronization
+ //
+ RESTORE_TPL ( TplPrevious );
+ }
+ else {
+ //
+ // Invalid How value
+ //
+ pSocket->errno = EINVAL;
+ Status = EFI_INVALID_PARAMETER;
}
}
else {
@@ -4678,7 +4818,7 @@ EslSocketTxComplete (
pPacket = pIo->pPacket;
pPort = pIo->pPort;
pSocket = pPort->pSocket;
-
+
//
// No more packet
//
diff --git a/StdLib/EfiSocketLib/Socket.h b/StdLib/EfiSocketLib/Socket.h
index 9dfb087..39c7c7a 100644
--- a/StdLib/EfiSocketLib/Socket.h
+++ b/StdLib/EfiSocketLib/Socket.h
@@ -120,8 +120,6 @@ typedef struct
typedef struct
{
EFI_TCP4_RECEIVE_DATA RxData; ///< Receive operation description
- size_t ValidBytes; ///< Length of valid data in bytes
- UINT8 * pBuffer; ///< Current data pointer
UINT8 Buffer[ RX_PACKET_DATA ]; ///< Data buffer
} ESL_TCP4_RX_DATA;
@@ -164,6 +162,8 @@ typedef struct
typedef struct _ESL_PACKET {
ESL_PACKET * pNext; ///< Next packet in the receive list
size_t PacketSize; ///< Size of this data structure
+ size_t ValidBytes; ///< Length of valid data in bytes
+ UINT8 * pBuffer; ///< Current data pointer
union {
ESL_IP4_RX_DATA Ip4Rx; ///< Receive operation description
ESL_IP4_TX_DATA Ip4Tx; ///< Transmit operation description
@@ -210,8 +210,11 @@ typedef struct _ESL_IO_MGMT {
ESL_PORT * pPort; ///< Port structure address
ESL_PACKET * pPacket; ///< Packet structure address
union {
+ EFI_IP4_COMPLETION_TOKEN Ip4Rx; ///< IP4 receive token
EFI_IP4_COMPLETION_TOKEN Ip4Tx; ///< IP4 transmit token
+ EFI_TCP4_IO_TOKEN Tcp4Rx; ///< TCP4 receive token
EFI_TCP4_IO_TOKEN Tcp4Tx; ///< TCP4 transmit token
+ EFI_UDP4_COMPLETION_TOKEN Udp4Rx; ///< UDP4 receive token
EFI_UDP4_COMPLETION_TOKEN Udp4Tx; ///< UDP4 transmit token
} Token; ///< Completion token for the network operation
};
@@ -227,11 +230,6 @@ typedef struct {
//
EFI_IP4_MODE_DATA ModeData; ///< IP4 mode data, includes configuration data
EFI_IPv4_ADDRESS DestinationAddress; ///< Default destination address
-
- //
- // Receive data management
- //
- EFI_IP4_COMPLETION_TOKEN RxToken; ///< Receive token
} ESL_IP4_CONTEXT;
@@ -253,11 +251,6 @@ typedef struct {
EFI_TCP4_LISTEN_TOKEN ListenToken; ///< Listen control
EFI_TCP4_CONNECTION_TOKEN ConnectToken; ///< Connection control
EFI_TCP4_CLOSE_TOKEN CloseToken; ///< Close control
-
- //
- // Receive data management
- //
- EFI_TCP4_IO_TOKEN RxToken; ///< Receive token
} ESL_TCP4_CONTEXT;
/**
@@ -270,11 +263,6 @@ typedef struct {
// UDP4 context
//
EFI_UDP4_CONFIG_DATA ConfigData; ///< UDP4 configuration data
-
- //
- // Receive data management
- //
- EFI_UDP4_COMPLETION_TOKEN RxToken;///< Receive token
} ESL_UDP4_CONTEXT;
@@ -289,7 +277,7 @@ typedef struct {
**/
typedef
EFI_STATUS
-(* PFN_NET_TX_START) (
+(* PFN_NET_IO_START) (
IN VOID * pProtocol,
IN VOID * pToken
);
@@ -333,7 +321,7 @@ typedef struct _ESL_PORT {
//
// Transmit data management
//
- PFN_NET_TX_START pfnTxStart; ///< Start a transmit on the network
+ PFN_NET_IO_START pfnTxStart; ///< Start a transmit on the network
ESL_IO_MGMT * pTxActive; ///< Normal data queue
ESL_IO_MGMT * pTxFree; ///< Normal free queue
@@ -343,7 +331,10 @@ typedef struct _ESL_PORT {
//
// Receive data management
//
- ESL_PACKET * pReceivePending; ///< Receive operation in progress
+ PFN_NET_IO_START pfnRxCancel; ///< Cancel a receive on the network
+ PFN_NET_IO_START pfnRxStart; ///< Start a receive on the network
+ ESL_IO_MGMT * pRxActive; ///< Active receive operation queue
+ ESL_IO_MGMT * pRxFree; ///< Free structure queue
//
// Protocol specific management data
@@ -574,7 +565,7 @@ EFI_STATUS
This routine is called by ::EslSocketPortCloseRxDone as
the last step of closing processing.
- See the \ref Tcp4PortCloseStateMachine section.
+ See the \ref PortCloseStateMachine section.
@param [in] pPort Address of an ::ESL_PORT structure.
@@ -617,7 +608,7 @@ EFI_STATUS
This routine performs the network specific operations necessary
to free a receive packet.
- This routine is called by ::EslSocketPortCloseTx to free a
+ This routine is called by ::EslSocketPortCloseTxDone to free a
receive packet.
@param [in] pPacket Address of an ::ESL_PACKET structure.
@@ -713,38 +704,42 @@ VOID
);
/**
- Cancel the receive operations
+ Process the receive completion
- @param [in] pSocket Address of a ESL_SOCKET structure
-
- @retval EFI_SUCCESS - The cancel was successful
+ This routine handles the receive completion event.
- **/
+ This routine is called by the low level network driver when
+ data is received.
+
+ @param [in] Event The receive completion event
+
+ @param [in] pIo The address of an ::ESL_IO_MGMT structure
+
+**/
typedef
-EFI_STATUS
-(* PFN_API_RX_CANCEL) (
- IN ESL_SOCKET * pSocket
+VOID
+(* PFN_API_RX_COMPLETE) (
+ IN EFI_EVENT Event,
+ IN ESL_IO_MGMT * pIo
);
/**
Start a receive operation
- This routine posts a receive buffer to the network adapter.
+ This routine prepares a packet for the receive operation.
See the \ref ReceiveEngine section.
This support routine is called by EslSocketRxStart.
@param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pPacket Address of an ::ESL_PACKET structure.
-
- @retval EFI_SUCCESS Receive operation started successfully
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure.
**/
typedef
-EFI_STATUS
+VOID
(* PFN_API_RX_START) (
IN ESL_PORT * pPort,
- IN ESL_PACKET * pPacket
+ IN ESL_IO_MGMT * pIo
);
/**
@@ -812,6 +807,8 @@ typedef struct {
socklen_t AddressLength; ///< Address length in bytes
sa_family_t AddressFamily; ///< Address family
UINTN RxPacketBytes; ///< Length of the RX packet allocation
+ UINTN RxZeroBytes; ///< Number of bytes to zero in RX packet
+ UINTN RxBufferOffset; ///< Offset of buffer address in ESL_IO_MGMT structure
BOOLEAN bOobSupported; ///< TRUE if out-of-band messages are supported
PFN_API_ACCEPT pfnAccept; ///< Accept a network connection
PFN_API_CONNECT_POLL pfnConnectPoll; ///< Poll for connection complete
@@ -824,13 +821,13 @@ typedef struct {
PFN_API_OPTION_SET pfnOptionSet; ///< Set the option value
PFN_API_PORT_ALLOC pfnPortAllocate; ///< Allocate the network specific resources for the port
PFN_API_PORT_CLOSE pfnPortClose; ///< Close the network specific resources for the port
+ PFN_API_PORT_CLOSE_OP pfnPortCloseOp; ///< Perform the close operation on the port
PFN_API_PORT_CLOSE_PF pfnPortClosePktFree;///< Free the receive packet
- PFN_API_PORT_CLOSE_OP pfnPortCloseRxStop; ///< Perform the close operation on the port
BOOLEAN bPortCloseComplete; ///< TRUE = Close is complete after close operation
PFN_API_RECEIVE pfnReceive; ///< Attempt to receive some data
PFN_API_REMOTE_ADDR_GET pfnRemoteAddrGet; ///< Get remote address
PFN_API_REMOTE_ADDR_SET pfnRemoteAddrSet; ///< Set the remote system address
- PFN_API_RX_CANCEL pfnRxCancel; ///< Cancel a receive operation
+ PFN_API_RX_COMPLETE pfnRxComplete; ///< RX completion
PFN_API_RX_START pfnRxStart; ///< Start a network specific receive operation
PFN_API_TRANSMIT pfnTransmit; ///< Attempt to buffer a packet for transmit
PFN_API_TX_COMPLETE pfnTxComplete; ///< TX completion for normal data
@@ -1123,11 +1120,13 @@ EslSocketIsConfigured (
/**
Allocate a packet for a receive or transmit operation
- This support routine is called by the network specific RxStart
- and TxBuffer routines to get buffer space for the next operation.
+ This support routine is called by ::EslSocketRxStart and the
+ network specific TxBuffer routines to get buffer space for the
+ next operation.
@param [in] ppPacket Address to receive the ::ESL_PACKET structure
@param [in] LengthInBytes Length of the packet structure
+ @param [in] ZeroBytes Length of packet to zero
@param [in] DebugFlags Flags for debug messages
@retval EFI_SUCCESS - The packet was allocated successfully
@@ -1137,6 +1136,7 @@ EFI_STATUS
EslSocketPacketAllocate (
IN ESL_PACKET ** ppPacket,
IN size_t LengthInBytes,
+ IN size_t ZeroBytes,
IN UINTN DebugFlags
);
@@ -1169,14 +1169,9 @@ EslSocketPacketFree (
specific resources. The resources are released later by the
\ref PortCloseStateMachine.
- This support routine is called by:
- <ul>
- <li>::EslIp4Bind</li>
- <li>::EslTcp4Bind</li>
- <li>::EslTcp4ListenComplete</li>
- <li>::EslUdp4Bind::</li>
- to connect the socket with the underlying network adapter
- to the socket.
+ This support routine is called by ::EslSocketBind and
+ ::EslTcp4ListenComplete to connect the socket with the
+ underlying network adapter to the socket.
@param [in] pSocket Address of an ::ESL_SOCKET structure.
@param [in] pService Address of an ::ESL_SERVICE structure.
@@ -1264,12 +1259,12 @@ EslSocketPortCloseComplete (
This routine is called by
<ul>
<li>::EslIp4RxComplete</li>
+ <li>::EslSocketPortCloseComplete</li>
<li>::EslSocketPortCloseTxDone</li>
- <li>::EslTcp4PortCloseComplete</li>
<li>::EslUdp4RxComplete</li>
</ul>
to determine the state of the receive operations.
- See the \ref Tcp4PortCloseStateMachine section.
+ See the \ref PortCloseStateMachine section.
@param [in] pPort Address of an ::ESL_PORT structure.
@@ -1316,7 +1311,7 @@ EslSocketPortCloseStart (
This routine determines the state of the transmit engine and
continue the close operation after the transmission is complete.
- The next step is to stop the \ref Tcp4ReceiveEngine.
+ The next step is to stop the \ref ReceiveEngine.
See the \ref PortCloseStateMachine section.
This routine is called by ::EslSocketPortCloseStart to determine
@@ -1336,6 +1331,25 @@ EslSocketPortCloseTxDone (
);
/**
+ Cancel the receive operations
+
+ This routine cancels a pending receive operation.
+ See the \ref ReceiveEngine section.
+
+ This routine is called by ::EslSocketShutdown when the socket
+ layer is being shutdown.
+
+ @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
+
+ **/
+VOID
+EslSocketRxCancel (
+ IN ESL_PORT * pPort,
+ IN ESL_IO_MGMT * pIo
+ );
+
+/**
Process the receive completion
This routine queues the data in FIFO order in either the urgent
@@ -1349,7 +1363,7 @@ EslSocketPortCloseTxDone (
<li>::EslUdp4RxComplete</li>
</ul>
- @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
@param [in] Status Receive status
@param [in] LengthInBytes Length of the receive data
@param [in] bUrgent TRUE if urgent data is received and FALSE
@@ -1358,7 +1372,7 @@ EslSocketPortCloseTxDone (
**/
VOID
EslSocketRxComplete (
- IN ESL_PORT * pPort,
+ IN ESL_IO_MGMT * pIo,
IN EFI_STATUS Status,
IN UINTN LengthInBytes,
IN BOOLEAN bUrgent
diff --git a/StdLib/EfiSocketLib/Tcp4.c b/StdLib/EfiSocketLib/Tcp4.c
index e8181b4..fb359f6 100644
--- a/StdLib/EfiSocketLib/Tcp4.c
+++ b/StdLib/EfiSocketLib/Tcp4.c
@@ -82,30 +82,6 @@ EslTcp4ListenComplete (
/**
- Process the receive completion
-
- This routine queues the data in FIFO order in either the urgent
- or normal data queues depending upon the type of data received.
- See the \ref Tcp4ReceiveEngine section.
-
- This routine is called by the TCPv4 driver when some data is
- received.
-
- Buffer the data that was just received.
-
- @param [in] Event The receive completion event
-
- @param [in] pPort Address of an ::ESL_PORT structure
-
-**/
-VOID
-EslTcp4RxComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- );
-
-
-/**
Accept a network connection.
This routine waits for a network connection to the socket and
@@ -1039,13 +1015,13 @@ EslTcp4ListenComplete (
@param [in] pPort Address of an ::ESL_PORT structure.
- @param [out] pAddress Network address to receive the local system address
+ @param [out] pSockAddr Network address to receive the local system address
**/
VOID
EslTcp4LocalAddressGet (
IN ESL_PORT * pPort,
- OUT struct sockaddr * pAddress
+ OUT struct sockaddr * pSockAddr
)
{
struct sockaddr_in * pLocalAddress;
@@ -1057,7 +1033,7 @@ EslTcp4LocalAddressGet (
// Return the local address
//
pTcp4 = &pPort->Context.Tcp4;
- pLocalAddress = (struct sockaddr_in *)pAddress;
+ pLocalAddress = (struct sockaddr_in *)pSockAddr;
pLocalAddress->sin_family = AF_INET;
pLocalAddress->sin_port = SwapBytes16 ( pTcp4->ConfigData.AccessPoint.StationPort );
CopyMem ( &pLocalAddress->sin_addr,
@@ -1075,7 +1051,7 @@ EslTcp4LocalAddressGet (
This support routine is called by ::EslSocketPortAllocate.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] pSockAddr Address of a sockaddr structure that contains the
connection point on the local machine. An IPv4 address
of INADDR_ANY specifies that the connection is made to
@@ -1153,7 +1129,7 @@ EslTcp4LocalAddressSet (
to connect the socket with the underlying network adapter
running the TCPv4 protocol.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] DebugFlags Flags for debug messages
@retval EFI_SUCCESS - Socket successfully created
@@ -1176,31 +1152,12 @@ EslTcp4PortAllocate (
// Use for/break instead of goto
for ( ; ; ) {
//
- // Allocate the receive event
+ // Allocate the close event
//
pSocket = pPort->pSocket;
pTcp4 = &pPort->Context.Tcp4;
Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslTcp4RxComplete,
- pPort,
- &pTcp4->RxToken.CompletionToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the receive event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_RX | DEBUG_POOL,
- "0x%08x: Created receive event\r\n",
- pTcp4->RxToken.CompletionToken.Event ));
-
- //
- // Allocate the close event
- //
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
(EFI_EVENT_NOTIFY)EslSocketPortCloseComplete,
pPort,
&pTcp4->CloseToken.CompletionToken.Event);
@@ -1242,9 +1199,11 @@ EslTcp4PortAllocate (
pSocket->TxTokenOffset = OFFSET_OF ( EFI_TCP4_IO_TOKEN, Packet.TxData );
//
- // Save the transmit address
+ // Save the cancel, receive and transmit addresses
//
- pPort->pfnTxStart = (PFN_NET_TX_START)pPort->pProtocol.TCPv4->Transmit;
+ pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Cancel;
+ pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Receive;
+ pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.TCPv4->Transmit;
//
// Set the configuration flags
@@ -1351,24 +1310,6 @@ EslTcp4PortClose (
}
//
- // Done with the receive event
- //
- if ( NULL != pTcp4->RxToken.CompletionToken.Event ) {
- Status = gBS->CloseEvent ( pTcp4->RxToken.CompletionToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed receive event\r\n",
- pTcp4->RxToken.CompletionToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the receive event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
-
- //
// Return the operation status
//
DBG_EXIT_STATUS ( Status );
@@ -1377,38 +1318,9 @@ EslTcp4PortClose (
/**
- Free a receive packet
-
- This routine performs the network specific operations necessary
- to free a receive packet.
-
- This routine is called by ::EslSocketPortCloseTxDone to free a
- receive packet.
-
- @param [in] pPacket Address of an ::ESL_PACKET structure.
- @param [in, out] pRxBytes Address of the count of RX bytes
-
-**/
-VOID
-EslTcp4PortClosePacketFree (
- IN ESL_PACKET * pPacket,
- IN OUT size_t * pRxBytes
- )
-{
- DBG_ENTER ( );
-
- //
- // Account for the receive bytes
- //
- *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength;
- DBG_EXIT ( );
-}
-
-
-/**
Perform the network specific close operation on the port.
- This routine performs a cancel operations on the UDPv4 port to
+ This routine performs a cancel operations on the TCPv4 port to
shutdown the receive operations on the port.
This routine is called by the ::EslSocketPortCloseTxDone
@@ -1423,7 +1335,7 @@ EslTcp4PortClosePacketFree (
**/
EFI_STATUS
-EslTcp4PortCloseRxStop (
+EslTcp4PortCloseOp (
IN ESL_PORT * pPort
)
{
@@ -1436,6 +1348,7 @@ EslTcp4PortCloseRxStop (
//
// Close the configured port
//
+ Status = EFI_SUCCESS;
pTcp4 = &pPort->Context.Tcp4;
pTcp4Protocol = pPort->pProtocol.TCPv4;
pTcp4->CloseToken.AbortOnClose = FALSE;
@@ -1462,6 +1375,35 @@ EslTcp4PortCloseRxStop (
/**
+ Free a receive packet
+
+ This routine performs the network specific operations necessary
+ to free a receive packet.
+
+ This routine is called by ::EslSocketPortCloseTxDone to free a
+ receive packet.
+
+ @param [in] pPacket Address of an ::ESL_PACKET structure.
+ @param [in, out] pRxBytes Address of the count of RX bytes
+
+**/
+VOID
+EslTcp4PortClosePacketFree (
+ IN ESL_PACKET * pPacket,
+ IN OUT size_t * pRxBytes
+ )
+{
+ DBG_ENTER ( );
+
+ //
+ // Account for the receive bytes
+ //
+ *pRxBytes -= pPacket->Op.Tcp4Rx.RxData.DataLength;
+ DBG_EXIT ( );
+}
+
+
+/**
Receive data from a network connection.
This routine attempts to return buffered data to the caller. The
@@ -1535,7 +1477,7 @@ EslTcp4Receive (
//
// Determine the amount of received data
//
- DataLength = pPacket->Op.Tcp4Rx.ValidBytes;
+ DataLength = pPacket->ValidBytes;
if ( BufferLength < DataLength ) {
DataLength = BufferLength;
}
@@ -1549,7 +1491,7 @@ EslTcp4Receive (
pPacket,
pBuffer,
DataLength ));
- CopyMem ( pBuffer, pPacket->Op.Tcp4Rx.pBuffer, DataLength );
+ CopyMem ( pBuffer, pPacket->pBuffer, DataLength );
//
// Determine if the data is being read
@@ -1558,8 +1500,8 @@ EslTcp4Receive (
//
// Account for the bytes consumed
//
- pPacket->Op.Tcp4Rx.pBuffer += DataLength;
- pPacket->Op.Tcp4Rx.ValidBytes -= DataLength;
+ pPacket->pBuffer += DataLength;
+ pPacket->ValidBytes -= DataLength;
DEBUG (( DEBUG_RX,
"0x%08x: Port account for 0x%08x bytes\r\n",
pPort,
@@ -1568,13 +1510,13 @@ EslTcp4Receive (
//
// Determine if the entire packet was consumed
//
- if (( 0 == pPacket->Op.Tcp4Rx.ValidBytes )
+ if (( 0 == pPacket->ValidBytes )
|| ( SOCK_STREAM != pPort->pSocket->Type )) {
//
// All done with this packet
// Account for any discarded data
//
- *pSkipBytes = pPacket->Op.Tcp4Rx.ValidBytes;
+ *pSkipBytes = pPacket->ValidBytes;
}
else
{
@@ -1677,77 +1619,11 @@ EslTcp4RemoteAddressSet (
/**
- Cancel the receive operations
-
- This routine cancels the pending receive operations.
- See the \ref Tcp4ReceiveEngine section.
-
- This routine is called by ::EslSocketShutdown when the socket
- layer is being shutdown.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure.
-
- @retval EFI_SUCCESS - The cancel was successful
-
- **/
-EFI_STATUS
-EslTcp4RxCancel (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume failure
- //
- Status = EFI_NOT_FOUND;
-
- //
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if a receive is pending
- //
- pTcp4 = &pPort->Context.Tcp4;
- pPacket = pPort->pReceivePending;
- if ( NULL != pPacket ) {
- //
- // Attempt to cancel the receive operation
- //
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->Cancel ( pTcp4Protocol,
- &pTcp4->RxToken.CompletionToken );
- if ( EFI_NOT_FOUND == Status ) {
- //
- // The receive is complete
- //
- Status = EFI_SUCCESS;
- }
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
Process the receive completion
This routine queues the data in FIFO order in either the urgent
or normal data queues depending upon the type of data received.
- See the \ref Tcp4ReceiveEngine section.
+ See the \ref ReceiveEngine section.
This routine is called by the TCPv4 driver when some data is
received.
@@ -1756,19 +1632,18 @@ EslTcp4RxCancel (
@param [in] Event The receive completion event
- @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
**/
VOID
EslTcp4RxComplete (
IN EFI_EVENT Event,
- IN ESL_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
BOOLEAN bUrgent;
size_t LengthInBytes;
ESL_PACKET * pPacket;
- ESL_TCP4_CONTEXT * pTcp4;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -1776,26 +1651,21 @@ EslTcp4RxComplete (
//
// Get the operation status.
//
- pTcp4 = &pPort->Context.Tcp4;
- Status = pTcp4->RxToken.CompletionToken.Status;
+ Status = pIo->Token.Tcp4Rx.CompletionToken.Status;
//
// Get the packet length and type
//
- pPacket = pPort->pReceivePending;
- pPacket->Op.Tcp4Rx.pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
+ pPacket = pIo->pPacket;
+ pPacket->pBuffer = pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer;
LengthInBytes = pPacket->Op.Tcp4Rx.RxData.DataLength;
+ pPacket->ValidBytes = LengthInBytes;
bUrgent = pPacket->Op.Tcp4Rx.RxData.UrgentFlag;
//
- // Set the buffer size
- //
- pPacket->Op.Tcp4Rx.ValidBytes = LengthInBytes;
-
- //
// Complete this request
//
- EslSocketRxComplete ( pPort, Status, LengthInBytes, bUrgent );
+ EslSocketRxComplete ( pIo, Status, LengthInBytes, bUrgent );
DBG_EXIT ( );
}
@@ -1809,45 +1679,30 @@ EslTcp4RxComplete (
This support routine is called by EslSocketRxStart.
@param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pPacket Address of an ::ESL_PACKET structure.
-
- @retval EFI_SUCCESS Receive operation started successfully
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure.
**/
-EFI_STATUS
+VOID
EslTcp4RxStart (
IN ESL_PORT * pPort,
- IN ESL_PACKET * pPacket
+ IN ESL_IO_MGMT * pIo
)
{
- ESL_TCP4_CONTEXT * pTcp4;
- EFI_TCP4_PROTOCOL * pTcp4Protocol;
- EFI_STATUS Status;
+ ESL_PACKET * pPacket;
DBG_ENTER ( );
//
// Initialize the buffer for receive
//
- pTcp4 = &pPort->Context.Tcp4;
- pTcp4->RxToken.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
+ pPacket = pIo->pPacket;
+ pIo->Token.Tcp4Rx.Packet.RxData = &pPacket->Op.Tcp4Rx.RxData;
pPacket->Op.Tcp4Rx.RxData.DataLength = sizeof ( pPacket->Op.Tcp4Rx.Buffer );
pPacket->Op.Tcp4Rx.RxData.FragmentCount = 1;
pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentLength = pPacket->Op.Tcp4Rx.RxData.DataLength;
pPacket->Op.Tcp4Rx.RxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Tcp4Rx.Buffer[0];
- //
- // Start the receive on the packet
- //
- pTcp4Protocol = pPort->pProtocol.TCPv4;
- Status = pTcp4Protocol->Receive ( pTcp4Protocol,
- &pTcp4->RxToken );
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
+ DBG_EXIT ( );
}
@@ -2000,6 +1855,7 @@ EslTcp4TxBuffer (
sizeof ( pPacket->Op.Tcp4Tx )
- sizeof ( pPacket->Op.Tcp4Tx.Buffer )
+ BufferLength,
+ 0,
DEBUG_TX );
if ( !EFI_ERROR ( Status )) {
//
@@ -2242,6 +2098,8 @@ CONST ESL_PROTOCOL_API cEslTcp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Tcp4Rx ),
+ OFFSET_OF ( ESL_PACKET, Op.Tcp4Rx.Buffer ) - OFFSET_OF ( ESL_PACKET, Op ),
+ OFFSET_OF ( ESL_IO_MGMT, Token.Tcp4Rx.Packet.RxData ),
FALSE,
EslTcp4Accept,
EslTcp4ConnectPoll,
@@ -2254,13 +2112,13 @@ CONST ESL_PROTOCOL_API cEslTcp4Api = {
NULL, // OptionSet
EslTcp4PortAllocate,
EslTcp4PortClose,
+ EslTcp4PortCloseOp,
EslTcp4PortClosePacketFree,
- EslTcp4PortCloseRxStop,
FALSE,
EslTcp4Receive,
EslTcp4RemoteAddressGet,
EslTcp4RemoteAddressSet,
- EslTcp4RxCancel,
+ EslTcp4RxComplete,
EslTcp4RxStart,
EslTcp4TxBuffer,
EslTcp4TxComplete,
diff --git a/StdLib/EfiSocketLib/Udp4.c b/StdLib/EfiSocketLib/Udp4.c
index 058ffb2..3d1cb0d 100644
--- a/StdLib/EfiSocketLib/Udp4.c
+++ b/StdLib/EfiSocketLib/Udp4.c
@@ -16,29 +16,6 @@
/**
- Process the receive completion
-
- This routine keeps the UDPv4 driver's buffer and queues it in
- in FIFO order to the data queue. The UDP4 driver's buffer will
- be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
- See the \ref Tcp4ReceiveEngine section.
-
- This routine is called by the UDPv4 driver when data is
- received.
-
- @param [in] Event The receive completion event
-
- @param [in] pPort Address of an ::ESL_PORT structure
-
-**/
-VOID
-EslUdp4RxComplete (
- IN EFI_EVENT Event,
- IN ESL_PORT * pPort
- );
-
-
-/**
Get the local socket address
This routine returns the IPv4 address and UDP port number associated
@@ -49,13 +26,13 @@ EslUdp4RxComplete (
@param [in] pPort Address of an ::ESL_PORT structure.
- @param [out] pAddress Network address to receive the local system address
+ @param [out] pSockAddr Network address to receive the local system address
**/
VOID
EslUdp4LocalAddressGet (
IN ESL_PORT * pPort,
- OUT struct sockaddr * pAddress
+ OUT struct sockaddr * pSockAddr
)
{
struct sockaddr_in * pLocalAddress;
@@ -67,7 +44,7 @@ EslUdp4LocalAddressGet (
// Return the local address
//
pUdp4 = &pPort->Context.Udp4;
- pLocalAddress = (struct sockaddr_in *)pAddress;
+ pLocalAddress = (struct sockaddr_in *)pSockAddr;
pLocalAddress->sin_family = AF_INET;
pLocalAddress->sin_port = SwapBytes16 ( pUdp4->ConfigData.StationPort );
CopyMem ( &pLocalAddress->sin_addr,
@@ -85,7 +62,7 @@ EslUdp4LocalAddressGet (
This support routine is called by ::EslSocketPortAllocate.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] pSockAddr Address of a sockaddr structure that contains the
connection point on the local machine. An IPv4 address
of INADDR_ANY specifies that the connection is made to
@@ -160,7 +137,7 @@ EslUdp4LocalAddressSet (
to connect the socket with the underlying network adapter
running the UDPv4 protocol.
- @param [in] ppPort Address of an ESL_PORT structure
+ @param [in] pPort Address of an ESL_PORT structure
@param [in] DebugFlags Flags for debug messages
@retval EFI_SUCCESS - Socket successfully created
@@ -173,119 +150,37 @@ EslUdp4PortAllocate (
)
{
EFI_UDP4_CONFIG_DATA * pConfig;
- ESL_UDP4_CONTEXT * pUdp4;
ESL_SOCKET * pSocket;
EFI_STATUS Status;
DBG_ENTER ( );
//
- // Use for/break instead of goto
- for ( ; ; ) {
- //
- // Allocate the receive event
- //
- pSocket = pPort->pSocket;
- pUdp4 = &pPort->Context.Udp4;
- Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL,
- TPL_SOCKETS,
- (EFI_EVENT_NOTIFY)EslUdp4RxComplete,
- pPort,
- &pUdp4->RxToken.Event);
- if ( EFI_ERROR ( Status )) {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to create the receive event, Status: %r\r\n",
- Status ));
- pSocket->errno = ENOMEM;
- break;
- }
- DEBUG (( DEBUG_RX | DEBUG_POOL,
- "0x%08x: Created receive event\r\n",
- pUdp4->RxToken.Event ));
-
- //
- // Initialize the port
- //
- pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp4Tx.TxData );
- pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Tx.Event );
- pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN, Packet.TxData );
-
- //
- // Save the transmit address
- //
- pPort->pfnTxStart = (PFN_NET_TX_START)pPort->pProtocol.UDPv4->Transmit;
-
- //
- // Set the configuration flags
- //
- pConfig = &pPort->Context.Udp4.ConfigData;
- pConfig->TimeToLive = 255;
- pConfig->AcceptAnyPort = FALSE;
- pConfig->AcceptBroadcast = FALSE;
- pConfig->AcceptPromiscuous = FALSE;
- pConfig->AllowDuplicatePort = TRUE;
- pConfig->DoNotFragment = TRUE;
- break;
- }
-
- //
- // Return the operation status
+ // Initialize the port
//
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
- Close a UDP4 port.
-
- This routine releases the resources allocated by
- ::EslUdp4PortAllocate.
-
- This routine is called by ::EslSocketPortClose.
- See the \ref PortCloseStateMachine section.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed
- @retval other Port close error
-
-**/
-EFI_STATUS
-EslUdp4PortClose (
- IN ESL_PORT * pPort
- )
-{
- UINTN DebugFlags;
- ESL_UDP4_CONTEXT * pUdp4;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ pSocket = pPort->pSocket;
+ pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Udp4Tx.TxData );
+ pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Tx.Event );
+ pSocket->TxTokenOffset = OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN, Packet.TxData );
//
- // Assume success
+ // Save the cancel, receive and transmit addresses
//
- Status = EFI_SUCCESS;
- DebugFlags = pPort->DebugFlags;
- pUdp4 = &pPort->Context.Udp4;
+ pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Cancel;
+ pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Receive;
+ pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.UDPv4->Transmit;
//
- // Done with the receive event
+ // Set the configuration flags
//
- if ( NULL != pUdp4->RxToken.Event ) {
- Status = gBS->CloseEvent ( pUdp4->RxToken.Event );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( DebugFlags | DEBUG_POOL,
- "0x%08x: Closed receive event\r\n",
- pUdp4->RxToken.Event ));
- }
- else {
- DEBUG (( DEBUG_ERROR | DebugFlags,
- "ERROR - Failed to close the receive event, Status: %r\r\n",
- Status ));
- ASSERT ( EFI_SUCCESS == Status );
- }
- }
+ pConfig = &pPort->Context.Udp4.ConfigData;
+ pConfig->TimeToLive = 255;
+ pConfig->AcceptAnyPort = FALSE;
+ pConfig->AcceptBroadcast = FALSE;
+ pConfig->AcceptPromiscuous = FALSE;
+ pConfig->AllowDuplicatePort = TRUE;
+ pConfig->DoNotFragment = TRUE;
+ Status = EFI_SUCCESS;
//
// Return the operation status
@@ -314,75 +209,26 @@ EslUdp4PortClosePacketFree (
IN OUT size_t * pRxBytes
)
{
+ EFI_UDP4_RECEIVE_DATA * pRxData;
+
DBG_ENTER ( );
//
// Account for the receive bytes
//
- *pRxBytes -= pPacket->Op.Udp4Rx.pRxData->DataLength;
-
- //
- // Return the buffer to the UDP4 driver
- //
- gBS->SignalEvent ( pPacket->Op.Udp4Rx.pRxData->RecycleSignal );
- DBG_EXIT ( );
-}
-
-
-/**
- Perform the network specific close operation on the port.
-
- This routine performs a cancel operations on the UDPv4 port to
- shutdown the receive operations on the port.
-
- This routine is called by the ::EslSocketPortCloseTxDone
- routine after the port completes all of the transmission.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
-
- @retval EFI_SUCCESS The port is closed, not normally returned
- @retval EFI_NOT_READY The port is still closing
- @retval EFI_ALREADY_STARTED Error, the port is in the wrong state,
- most likely the routine was called already.
-
-**/
-EFI_STATUS
-EslUdp4PortCloseRxStop (
- IN ESL_PORT * pPort
- )
-{
- ESL_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
+ pRxData = pPacket->Op.Udp4Rx.pRxData;
+ *pRxBytes -= pRxData->DataLength;
//
- // Reset the port, cancel the outstanding receive
+ // Disconnect the buffer from the packet
//
- pUdp4 = &pPort->Context.Udp4;
- pUdp4Protocol = pPort->pProtocol.UDPv4;
- Status = pUdp4Protocol->Cancel ( pUdp4Protocol,
- &pPort->Context.Udp4.RxToken );
- if ( !EFI_ERROR ( Status )) {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Packet receive aborted on port: 0x%08x\r\n",
- pPort->pReceivePending,
- pPort ));
- }
- else {
- DEBUG (( pPort->DebugFlags | DEBUG_CLOSE | DEBUG_INFO,
- "0x%08x: Packet receive pending on Port 0x%08x\r\n",
- pPort->pReceivePending,
- pPort ));
- Status = EFI_SUCCESS;
- }
+ pPacket->Op.Udp4Rx.pRxData = NULL;
//
- // Return the operation status
+ // Return the buffer to the UDP4 driver
//
- DBG_EXIT_STATUS ( Status );
- return Status;
+ gBS->SignalEvent ( pRxData->RecycleSignal );
+ DBG_EXIT ( );
}
@@ -575,97 +421,30 @@ EslUdp4RemoteAddressSet (
/**
- Cancel the receive operations
-
- This routine cancels the pending receive operations.
- See the \ref Udp4ReceiveEngine section.
-
- This routine is called by ::EslSocketShutdown when the socket
- layer is being shutdown.
-
- @param [in] pSocket Address of an ::ESL_SOCKET structure
-
- @retval EFI_SUCCESS - The cancel was successful
-
- **/
-EFI_STATUS
-EslUdp4RxCancel (
- IN ESL_SOCKET * pSocket
- )
-{
- ESL_PACKET * pPacket;
- ESL_PORT * pPort;
- ESL_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Assume failure
- //
- Status = EFI_NOT_FOUND;
-
- //
- // Locate the port
- //
- pPort = pSocket->pPortList;
- if ( NULL != pPort ) {
- //
- // Determine if a receive is pending
- //
- pUdp4 = &pPort->Context.Udp4;
- pPacket = pPort->pReceivePending;
- if ( NULL != pPacket ) {
- //
- // Attempt to cancel the receive operation
- //
- pUdp4Protocol = pPort->pProtocol.UDPv4;
- Status = pUdp4Protocol->Cancel ( pUdp4Protocol,
- &pUdp4->RxToken );
- if ( EFI_NOT_FOUND == Status ) {
- //
- // The receive is complete
- //
- Status = EFI_SUCCESS;
- }
- }
- }
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
Process the receive completion
This routine keeps the UDPv4 driver's buffer and queues it in
in FIFO order to the data queue. The UDP4 driver's buffer will
be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
- See the \ref Tcp4ReceiveEngine section.
+ See the \ref ReceiveEngine section.
This routine is called by the UDPv4 driver when data is
received.
@param [in] Event The receive completion event
- @param [in] pPort Address of an ::ESL_PORT structure
+ @param [in] pIo Address of an ::ESL_IO_MGMT structure
**/
VOID
EslUdp4RxComplete (
IN EFI_EVENT Event,
- IN ESL_PORT * pPort
+ IN ESL_IO_MGMT * pIo
)
{
size_t LengthInBytes;
ESL_PACKET * pPacket;
EFI_UDP4_RECEIVE_DATA * pRxData;
- ESL_UDP4_CONTEXT * pUdp4;
EFI_STATUS Status;
DBG_ENTER ( );
@@ -673,85 +452,36 @@ EslUdp4RxComplete (
//
// Get the operation status.
//
- pUdp4 = &pPort->Context.Udp4;
- Status = pUdp4->RxToken.Status;
+ Status = pIo->Token.Udp4Rx.Status;
//
// Get the packet length
//
- pRxData = pUdp4->RxToken.Packet.RxData;
+ pRxData = pIo->Token.Udp4Rx.Packet.RxData;
LengthInBytes = pRxData->DataLength;
//
// Save the data in the packet
//
- pPacket = pPort->pReceivePending;
+ pPacket = pIo->pPacket;
pPacket->Op.Udp4Rx.pRxData = pRxData;
//
// Complete this request
//
- EslSocketRxComplete ( pPort, Status, LengthInBytes, FALSE );
+ EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );
DBG_EXIT ( );
}
/**
- Start a receive operation
-
- This routine posts a receive buffer to the UDPv4 driver.
- See the \ref ReceiveEngine section.
-
- This support routine is called by EslSocketRxStart.
-
- @param [in] pPort Address of an ::ESL_PORT structure.
- @param [in] pPacket Address of an ::ESL_PACKET structure.
-
- @retval EFI_SUCCESS Receive operation started successfully
-
- **/
-EFI_STATUS
-EslUdp4RxStart (
- IN ESL_PORT * pPort,
- IN ESL_PACKET * pPacket
- )
-{
- ESL_UDP4_CONTEXT * pUdp4;
- EFI_UDP4_PROTOCOL * pUdp4Protocol;
- EFI_STATUS Status;
-
- DBG_ENTER ( );
-
- //
- // Initialize the buffer for receive
- //
- pPacket->Op.Udp4Rx.pRxData = NULL;
- pUdp4 = &pPort->Context.Udp4;
- pUdp4->RxToken.Packet.RxData = NULL;
-
- //
- // Start the receive on the packet
- //
- pUdp4Protocol = pPort->pProtocol.UDPv4;
- Status = pUdp4Protocol->Receive ( pUdp4Protocol,
- &pUdp4->RxToken );
-
- //
- // Return the operation status
- //
- DBG_EXIT_STATUS ( Status );
- return Status;
-}
-
-
-/**
Determine if the socket is configured.
This routine uses the flag ESL_SOCKET::bConfigured to determine
if the network layer's configuration routine has been called.
This routine calls the bind and configuration routines if they
were not already called. After the port is configured, the
- \ref Udp4ReceiveEngine is started.
+ \ref ReceiveEngine is started.
This routine is called by EslSocketIsConfigured to verify
that the socket is configured.
@@ -1018,6 +748,7 @@ EslUdp4TxBuffer (
sizeof ( pPacket->Op.Udp4Tx )
- sizeof ( pPacket->Op.Udp4Tx.Buffer )
+ BufferLength,
+ 0,
DEBUG_TX );
if ( !EFI_ERROR ( Status )) {
//
@@ -1224,6 +955,8 @@ CONST ESL_PROTOCOL_API cEslUdp4Api = {
sizeof ( struct sockaddr_in ),
AF_INET,
sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),
+ sizeof (((ESL_PACKET *)0 )->Op.Udp4Rx ),
+ OFFSET_OF ( ESL_IO_MGMT, Token.Udp4Rx.Packet.RxData ),
FALSE,
NULL, // Accept
NULL, // ConnectPoll
@@ -1235,15 +968,15 @@ CONST ESL_PROTOCOL_API cEslUdp4Api = {
NULL, // OptionGet
NULL, // OptionSet
EslUdp4PortAllocate,
- EslUdp4PortClose,
+ NULL, // PortClose,
+ NULL, // PortCloseOp
EslUdp4PortClosePacketFree,
- EslUdp4PortCloseRxStop,
TRUE,
EslUdp4Receive,
EslUdp4RemoteAddressGet,
EslUdp4RemoteAddressSet,
- EslUdp4RxCancel,
- EslUdp4RxStart,
+ EslUdp4RxComplete,
+ NULL, // RxStart
EslUdp4TxBuffer,
EslUdp4TxComplete,
NULL // TxOobComplete
diff --git a/StdLib/Include/Efi/EfiSocketLib.h b/StdLib/Include/Efi/EfiSocketLib.h
index 9f81fec..2d0cb37 100644
--- a/StdLib/Include/Efi/EfiSocketLib.h
+++ b/StdLib/Include/Efi/EfiSocketLib.h
@@ -130,6 +130,7 @@ typedef struct {
EFI_GUID * pNetworkProtocolGuid;///< Network protocol GUID
CONST EFI_GUID * pTagGuid; ///< Tag to mark protocol in use
UINTN ServiceListOffset; ///< Offset in ::ESL_LAYER for the list of services
+ UINTN RxIo; ///< Number of receive ESL_IO_MGMT structures for data
UINTN TxIoNormal; ///< Number of transmit ESL_IO_MGMT structures for normal data
UINTN TxIoUrgent; ///< Number of transmit ESL_IO_MGMT structures for urgent data
} ESL_SOCKET_BINDING;