2 Implement the UDP4 driver support for the socket layer.
4 Copyright (c) 2011, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Get the local socket address
21 This routine returns the IPv4 address and UDP port number associated
22 with the local socket.
24 This routine is called by ::EslSocketGetLocalAddress to determine the
25 network address for the SOCK_DGRAM socket.
27 @param [in] pPort Address of an ::ESL_PORT structure.
29 @param [out] pSockAddr Network address to receive the local system address
33 EslUdp4LocalAddressGet (
35 OUT
struct sockaddr
* pSockAddr
38 struct sockaddr_in
* pLocalAddress
;
39 ESL_UDP4_CONTEXT
* pUdp4
;
44 // Return the local address
46 pUdp4
= &pPort
->Context
.Udp4
;
47 pLocalAddress
= (struct sockaddr_in
*)pSockAddr
;
48 pLocalAddress
->sin_family
= AF_INET
;
49 pLocalAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.StationPort
);
50 CopyMem ( &pLocalAddress
->sin_addr
,
51 &pUdp4
->ConfigData
.StationAddress
.Addr
[0],
52 sizeof ( pLocalAddress
->sin_addr
));
59 Set the local port address.
61 This routine sets the local port address.
63 This support routine is called by ::EslSocketPortAllocate.
65 @param [in] pPort Address of an ESL_PORT structure
66 @param [in] pSockAddr Address of a sockaddr structure that contains the
67 connection point on the local machine. An IPv4 address
68 of INADDR_ANY specifies that the connection is made to
69 all of the network stacks on the platform. Specifying a
70 specific IPv4 address restricts the connection to the
71 network stack supporting that address. Specifying zero
72 for the port causes the network layer to assign a port
73 number from the dynamic range. Specifying a specific
74 port number causes the network layer to use that port.
76 @param [in] bBindTest TRUE = run bind testing
78 @retval EFI_SUCCESS The operation was successful
82 EslUdp4LocalAddressSet (
84 IN CONST
struct sockaddr
* pSockAddr
,
88 EFI_UDP4_CONFIG_DATA
* pConfig
;
89 CONST
struct sockaddr_in
* pIpAddress
;
90 CONST UINT8
* pIpv4Address
;
96 // Validate the address
98 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
99 if ( INADDR_BROADCAST
== pIpAddress
->sin_addr
.s_addr
) {
101 // The local address must not be the broadcast address
103 Status
= EFI_INVALID_PARAMETER
;
104 pPort
->pSocket
->errno
= EADDRNOTAVAIL
;
108 // Set the local address
110 pIpAddress
= (struct sockaddr_in
*)pSockAddr
;
111 pIpv4Address
= (UINT8
*)&pIpAddress
->sin_addr
.s_addr
;
112 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
113 pConfig
->StationAddress
.Addr
[0] = pIpv4Address
[0];
114 pConfig
->StationAddress
.Addr
[1] = pIpv4Address
[1];
115 pConfig
->StationAddress
.Addr
[2] = pIpv4Address
[2];
116 pConfig
->StationAddress
.Addr
[3] = pIpv4Address
[3];
119 // Determine if the default address is used
121 pConfig
->UseDefaultAddress
= (BOOLEAN
)( 0 == pIpAddress
->sin_addr
.s_addr
);
124 // Set the subnet mask
126 if ( pConfig
->UseDefaultAddress
) {
127 pConfig
->SubnetMask
.Addr
[0] = 0;
128 pConfig
->SubnetMask
.Addr
[1] = 0;
129 pConfig
->SubnetMask
.Addr
[2] = 0;
130 pConfig
->SubnetMask
.Addr
[3] = 0;
133 pConfig
->SubnetMask
.Addr
[0] = 0xff;
134 pConfig
->SubnetMask
.Addr
[1] = 0xff;
135 pConfig
->SubnetMask
.Addr
[2] = 0xff;
136 pConfig
->SubnetMask
.Addr
[3] = 0xff;
140 // Validate the IP address
142 pConfig
->StationPort
= 0;
143 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
145 if ( !EFI_ERROR ( Status
)) {
147 // Set the port number
149 pConfig
->StationPort
= SwapBytes16 ( pIpAddress
->sin_port
);
152 // Display the local address
155 "0x%08x: Port, Local UDP4 Address: %d.%d.%d.%d:%d\r\n",
157 pConfig
->StationAddress
.Addr
[0],
158 pConfig
->StationAddress
.Addr
[1],
159 pConfig
->StationAddress
.Addr
[2],
160 pConfig
->StationAddress
.Addr
[3],
161 pConfig
->StationPort
));
166 // Return the operation status
168 DBG_EXIT_STATUS ( Status
);
174 Free a receive packet
176 This routine performs the network specific operations necessary
177 to free a receive packet.
179 This routine is called by ::EslSocketPortCloseTxDone to free a
182 @param [in] pPacket Address of an ::ESL_PACKET structure.
183 @param [in, out] pRxBytes Address of the count of RX bytes
188 IN ESL_PACKET
* pPacket
,
189 IN OUT
size_t * pRxBytes
192 EFI_UDP4_RECEIVE_DATA
* pRxData
;
197 // Account for the receive bytes
199 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
200 *pRxBytes
-= pRxData
->DataLength
;
203 // Disconnect the buffer from the packet
205 pPacket
->Op
.Udp4Rx
.pRxData
= NULL
;
208 // Return the buffer to the UDP4 driver
210 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
216 Initialize the network specific portions of an ::ESL_PORT structure.
218 This routine initializes the network specific portions of an
219 ::ESL_PORT structure for use by the socket.
221 This support routine is called by ::EslSocketPortAllocate
222 to connect the socket with the underlying network adapter
223 running the UDPv4 protocol.
225 @param [in] pPort Address of an ESL_PORT structure
226 @param [in] DebugFlags Flags for debug messages
228 @retval EFI_SUCCESS - Socket successfully created
232 EslUdp4PortAllocate (
237 EFI_UDP4_CONFIG_DATA
* pConfig
;
238 ESL_SOCKET
* pSocket
;
244 // Initialize the port
246 pSocket
= pPort
->pSocket
;
247 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Udp4Tx
.TxData
);
248 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Tx
.Event
);
249 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_UDP4_COMPLETION_TOKEN
, Packet
.TxData
);
252 // Save the cancel, receive and transmit addresses
254 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.UDPv4
->Configure
;
255 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Cancel
;
256 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.UDPv4
->Poll
;
257 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Receive
;
258 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv4
->Transmit
;
261 // Set the configuration flags
263 pConfig
= &pPort
->Context
.Udp4
.ConfigData
;
264 pConfig
->TimeToLive
= 255;
265 pConfig
->AcceptAnyPort
= FALSE
;
266 pConfig
->AcceptBroadcast
= FALSE
;
267 pConfig
->AcceptPromiscuous
= FALSE
;
268 pConfig
->AllowDuplicatePort
= TRUE
;
269 pConfig
->DoNotFragment
= TRUE
;
270 Status
= EFI_SUCCESS
;
273 // Return the operation status
275 DBG_EXIT_STATUS ( Status
);
281 Receive data from a network connection.
283 This routine attempts to return buffered data to the caller. The
284 data is removed from the urgent queue if the message flag MSG_OOB
285 is specified, otherwise data is removed from the normal queue.
286 See the \ref ReceiveEngine section.
288 This routine is called by ::EslSocketReceive to handle the network
289 specific receive operation to support SOCK_DGRAM sockets.
291 @param [in] pPort Address of an ::ESL_PORT structure.
293 @param [in] pPacket Address of an ::ESL_PACKET structure.
295 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
297 @param [in] BufferLength Length of the the buffer
299 @param [in] pBuffer Address of a buffer to receive the data.
301 @param [in] pDataLength Number of received data bytes in the buffer.
303 @param [out] pAddress Network address to receive the remote system address
305 @param [out] pSkipBytes Address to receive the number of bytes skipped
307 @return Returns the address of the next free byte in the buffer.
313 IN ESL_PACKET
* pPacket
,
314 IN BOOLEAN
* pbConsumePacket
,
315 IN
size_t BufferLength
,
317 OUT
size_t * pDataLength
,
318 OUT
struct sockaddr
* pAddress
,
319 OUT
size_t * pSkipBytes
323 struct sockaddr_in
* pRemoteAddress
;
324 EFI_UDP4_RECEIVE_DATA
* pRxData
;
328 pRxData
= pPacket
->Op
.Udp4Rx
.pRxData
;
330 // Return the remote system address if requested
332 if ( NULL
!= pAddress
) {
334 // Build the remote address
337 "Getting packet remote address: %d.%d.%d.%d:%d\r\n",
338 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
339 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
340 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
341 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
342 pRxData
->UdpSession
.SourcePort
));
343 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
344 CopyMem ( &pRemoteAddress
->sin_addr
,
345 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
346 sizeof ( pRemoteAddress
->sin_addr
));
347 pRemoteAddress
->sin_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
351 // Copy the received data
353 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
354 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
360 // Determine if the data is being read
362 if ( *pbConsumePacket
) {
364 // Display for the bytes consumed
367 "0x%08x: Port account for 0x%08x bytes\r\n",
372 // Account for any discarded data
374 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
378 // Return the data length and the buffer address
380 *pDataLength
= DataBytes
;
381 DBG_EXIT_HEX ( pBuffer
);
387 Get the remote socket address
389 This routine returns the address of the remote connection point
390 associated with the SOCK_DGRAM socket.
392 This routine is called by ::EslSocketGetPeerAddress to detemine
393 the UDPv4 address and port number associated with the network adapter.
395 @param [in] pPort Address of an ::ESL_PORT structure.
397 @param [out] pAddress Network address to receive the remote system address
401 EslUdp4RemoteAddressGet (
403 OUT
struct sockaddr
* pAddress
406 struct sockaddr_in
* pRemoteAddress
;
407 ESL_UDP4_CONTEXT
* pUdp4
;
412 // Return the remote address
414 pUdp4
= &pPort
->Context
.Udp4
;
415 pRemoteAddress
= (struct sockaddr_in
*)pAddress
;
416 pRemoteAddress
->sin_family
= AF_INET
;
417 pRemoteAddress
->sin_port
= SwapBytes16 ( pUdp4
->ConfigData
.RemotePort
);
418 CopyMem ( &pRemoteAddress
->sin_addr
,
419 &pUdp4
->ConfigData
.RemoteAddress
.Addr
[0],
420 sizeof ( pRemoteAddress
->sin_addr
));
427 Set the remote address
429 This routine sets the remote address in the port.
431 This routine is called by ::EslSocketConnect to specify the
432 remote network address.
434 @param [in] pPort Address of an ::ESL_PORT structure.
436 @param [in] pSockAddr Network address of the remote system.
438 @param [in] SockAddrLength Length in bytes of the network address.
440 @retval EFI_SUCCESS The operation was successful
444 EslUdp4RemoteAddressSet (
446 IN CONST
struct sockaddr
* pSockAddr
,
447 IN socklen_t SockAddrLength
450 CONST
struct sockaddr_in
* pRemoteAddress
;
451 ESL_UDP4_CONTEXT
* pUdp4
;
457 // Set the remote address
459 pUdp4
= &pPort
->Context
.Udp4
;
460 pRemoteAddress
= (struct sockaddr_in
*)pSockAddr
;
461 pUdp4
->ConfigData
.RemoteAddress
.Addr
[0] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
);
462 pUdp4
->ConfigData
.RemoteAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
463 pUdp4
->ConfigData
.RemoteAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
464 pUdp4
->ConfigData
.RemoteAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
465 pUdp4
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
466 Status
= EFI_SUCCESS
;
469 // Return the operation status
471 DBG_EXIT_STATUS ( Status
);
477 Process the receive completion
479 This routine keeps the UDPv4 driver's buffer and queues it in
480 in FIFO order to the data queue. The UDP4 driver's buffer will
481 be returned by either ::EslUdp4Receive or ::EslSocketPortCloseTxDone.
482 See the \ref ReceiveEngine section.
484 This routine is called by the UDPv4 driver when data is
487 @param [in] Event The receive completion event
489 @param [in] pIo Address of an ::ESL_IO_MGMT structure
498 size_t LengthInBytes
;
499 ESL_PACKET
* pPacket
;
500 EFI_UDP4_RECEIVE_DATA
* pRxData
;
506 // Get the operation status.
508 Status
= pIo
->Token
.Udp4Rx
.Status
;
511 // Get the packet length
513 pRxData
= pIo
->Token
.Udp4Rx
.Packet
.RxData
;
514 LengthInBytes
= pRxData
->DataLength
;
517 // +--------------------+ +-----------------------+
518 // | ESL_IO_MGMT | | Data Buffer |
519 // | | | (Driver owned) |
520 // | +---------------+ +-----------------------+
523 // | | | +-----------------------+
524 // | | RxData --> | EFI_UDP4_RECEIVE_DATA |
525 // +----+---------------+ | (Driver owned) |
526 // +-----------------------+
527 // +--------------------+ ^
530 // | +---------------+ .
531 // | | pRxData --> NULL .......
532 // +----+---------------+
535 // Save the data in the packet
537 pPacket
= pIo
->pPacket
;
538 pPacket
->Op
.Udp4Rx
.pRxData
= pRxData
;
541 // Complete this request
543 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
549 Determine if the socket is configured.
551 This routine uses the flag ESL_SOCKET::bConfigured to determine
552 if the network layer's configuration routine has been called.
553 This routine calls the bind and configuration routines if they
554 were not already called. After the port is configured, the
555 \ref ReceiveEngine is started.
557 This routine is called by EslSocketIsConfigured to verify
558 that the socket is configured.
560 @param [in] pSocket Address of an ::ESL_SOCKET structure
562 @retval EFI_SUCCESS - The port is connected
563 @retval EFI_NOT_STARTED - The port is not connected
567 EslUdp4SocketIsConfigured (
568 IN ESL_SOCKET
* pSocket
571 EFI_UDP4_CONFIG_DATA
* pConfigData
;
573 ESL_PORT
* pNextPort
;
574 ESL_UDP4_CONTEXT
* pUdp4
;
575 EFI_UDP4_PROTOCOL
* pUdp4Protocol
;
577 struct sockaddr_in LocalAddress
;
584 Status
= EFI_SUCCESS
;
587 // Configure the port if necessary
589 if ( !pSocket
->bConfigured
) {
591 // Fill in the port list if necessary
593 if ( NULL
== pSocket
->pPortList
) {
594 LocalAddress
.sin_len
= sizeof ( LocalAddress
);
595 LocalAddress
.sin_family
= AF_INET
;
596 LocalAddress
.sin_addr
.s_addr
= 0;
597 LocalAddress
.sin_port
= 0;
598 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
599 (struct sockaddr
*)&LocalAddress
,
600 LocalAddress
.sin_len
,
605 // Walk the port list
607 pPort
= pSocket
->pPortList
;
608 while ( NULL
!= pPort
) {
610 // Attempt to configure the port
612 pNextPort
= pPort
->pLinkSocket
;
613 pUdp4
= &pPort
->Context
.Udp4
;
614 pUdp4Protocol
= pPort
->pProtocol
.UDPv4
;
615 pConfigData
= &pUdp4
->ConfigData
;
617 "0x%08x: pPort Configuring for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
619 pConfigData
->StationAddress
.Addr
[0],
620 pConfigData
->StationAddress
.Addr
[1],
621 pConfigData
->StationAddress
.Addr
[2],
622 pConfigData
->StationAddress
.Addr
[3],
623 pConfigData
->StationPort
,
624 pConfigData
->RemoteAddress
.Addr
[0],
625 pConfigData
->RemoteAddress
.Addr
[1],
626 pConfigData
->RemoteAddress
.Addr
[2],
627 pConfigData
->RemoteAddress
.Addr
[3],
628 pConfigData
->RemotePort
));
629 Status
= pUdp4Protocol
->Configure ( pUdp4Protocol
,
631 if ( !EFI_ERROR ( Status
)) {
633 // Update the configuration data
635 Status
= pUdp4Protocol
->GetModeData ( pUdp4Protocol
,
641 if ( EFI_ERROR ( Status
)) {
642 DEBUG (( DEBUG_LISTEN
,
643 "ERROR - Failed to configure the Udp4 port, Status: %r\r\n",
646 case EFI_ACCESS_DENIED
:
647 pSocket
->errno
= EACCES
;
651 case EFI_DEVICE_ERROR
:
652 pSocket
->errno
= EIO
;
655 case EFI_INVALID_PARAMETER
:
656 pSocket
->errno
= EADDRNOTAVAIL
;
660 pSocket
->errno
= EAFNOSUPPORT
;
663 case EFI_OUT_OF_RESOURCES
:
664 pSocket
->errno
= ENOBUFS
;
667 case EFI_UNSUPPORTED
:
668 pSocket
->errno
= EOPNOTSUPP
;
674 "0x%08x: pPort Configured for %d.%d.%d.%d:%d --> %d.%d.%d.%d:%d\r\n",
676 pConfigData
->StationAddress
.Addr
[0],
677 pConfigData
->StationAddress
.Addr
[1],
678 pConfigData
->StationAddress
.Addr
[2],
679 pConfigData
->StationAddress
.Addr
[3],
680 pConfigData
->StationPort
,
681 pConfigData
->RemoteAddress
.Addr
[0],
682 pConfigData
->RemoteAddress
.Addr
[1],
683 pConfigData
->RemoteAddress
.Addr
[2],
684 pConfigData
->RemoteAddress
.Addr
[3],
685 pConfigData
->RemotePort
));
686 pPort
->bConfigured
= TRUE
;
689 // Start the first read on the port
691 EslSocketRxStart ( pPort
);
694 // The socket is connected
696 pSocket
->State
= SOCKET_STATE_CONNECTED
;
706 // Determine the configuration status
708 if ( NULL
!= pSocket
->pPortList
) {
709 pSocket
->bConfigured
= TRUE
;
714 // Determine the socket configuration status
716 if ( !EFI_ERROR ( Status
)) {
717 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
721 // Return the port connected state.
723 DBG_EXIT_STATUS ( Status
);
729 Buffer data for transmission over a network connection.
731 This routine buffers data for the transmit engine in the normal
732 data queue. When the \ref TransmitEngine has resources, this
733 routine will start the transmission of the next buffer on the
736 This routine is called by ::EslSocketTransmit to buffer
737 data for transmission. The data is copied into a local buffer
738 freeing the application buffer for reuse upon return. When
739 necessary, this routine starts the transmit engine that
740 performs the data transmission on the network connection. The
741 transmit engine transmits the data a packet at a time over the
744 Transmission errors are returned during the next transmission or
745 during the close operation. Only buffering errors are returned
746 during the current transmission attempt.
748 @param [in] pSocket Address of an ::ESL_SOCKET structure
750 @param [in] Flags Message control flags
752 @param [in] BufferLength Length of the the buffer
754 @param [in] pBuffer Address of a buffer to receive the data.
756 @param [in] pDataLength Number of received data bytes in the buffer.
758 @param [in] pAddress Network address of the remote system address
760 @param [in] AddressLength Length of the remote network address structure
762 @retval EFI_SUCCESS - Socket data successfully buffered
767 IN ESL_SOCKET
* pSocket
,
769 IN
size_t BufferLength
,
770 IN CONST UINT8
* pBuffer
,
771 OUT
size_t * pDataLength
,
772 IN
const struct sockaddr
* pAddress
,
773 IN socklen_t AddressLength
776 ESL_PACKET
* pPacket
;
777 ESL_PACKET
* pPreviousPacket
;
779 const struct sockaddr_in
* pRemoteAddress
;
780 ESL_UDP4_CONTEXT
* pUdp4
;
782 ESL_UDP4_TX_DATA
* pTxData
;
791 Status
= EFI_UNSUPPORTED
;
792 pSocket
->errno
= ENOTCONN
;
796 // Verify that the socket is connected
798 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
802 pPort
= pSocket
->pPortList
;
803 if ( NULL
!= pPort
) {
805 // Determine the queue head
807 pUdp4
= &pPort
->Context
.Udp4
;
808 pTxBytes
= &pSocket
->TxBytes
;
811 // Verify that there is enough room to buffer another
812 // transmit operation
814 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
816 // Attempt to allocate the packet
818 Status
= EslSocketPacketAllocate ( &pPacket
,
819 sizeof ( pPacket
->Op
.Udp4Tx
)
820 - sizeof ( pPacket
->Op
.Udp4Tx
.Buffer
)
824 if ( !EFI_ERROR ( Status
)) {
826 // Initialize the transmit operation
828 pTxData
= &pPacket
->Op
.Udp4Tx
;
829 pTxData
->TxData
.GatewayAddress
= NULL
;
830 pTxData
->TxData
.UdpSessionData
= NULL
;
831 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
832 pTxData
->TxData
.FragmentCount
= 1;
833 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
834 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp4Tx
.Buffer
[0];
835 pTxData
->RetransmitCount
= 0;
838 // Set the remote system address if necessary
840 pTxData
->TxData
.UdpSessionData
= NULL
;
841 if ( NULL
!= pAddress
) {
842 pRemoteAddress
= (const struct sockaddr_in
*)pAddress
;
843 pTxData
->Session
.SourceAddress
.Addr
[0] = pUdp4
->ConfigData
.StationAddress
.Addr
[0];
844 pTxData
->Session
.SourceAddress
.Addr
[1] = pUdp4
->ConfigData
.StationAddress
.Addr
[1];
845 pTxData
->Session
.SourceAddress
.Addr
[2] = pUdp4
->ConfigData
.StationAddress
.Addr
[2];
846 pTxData
->Session
.SourceAddress
.Addr
[3] = pUdp4
->ConfigData
.StationAddress
.Addr
[3];
847 pTxData
->Session
.SourcePort
= 0;
848 pTxData
->Session
.DestinationAddress
.Addr
[0] = (UINT8
)pRemoteAddress
->sin_addr
.s_addr
;
849 pTxData
->Session
.DestinationAddress
.Addr
[1] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 8 );
850 pTxData
->Session
.DestinationAddress
.Addr
[2] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 16 );
851 pTxData
->Session
.DestinationAddress
.Addr
[3] = (UINT8
)( pRemoteAddress
->sin_addr
.s_addr
>> 24 );
852 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin_port
);
855 // Use the remote system address when sending this packet
857 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
861 // Copy the data into the buffer
863 CopyMem ( &pPacket
->Op
.Udp4Tx
.Buffer
[0],
868 // Synchronize with the socket layer
870 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
873 // Stop transmission after an error
875 if ( !EFI_ERROR ( pSocket
->TxError
)) {
877 // Display the request
880 "Send %d %s bytes from 0x%08x\r\n",
885 // Queue the data for transmission
887 pPacket
->pNext
= NULL
;
888 pPreviousPacket
= pSocket
->pTxPacketListTail
;
889 if ( NULL
== pPreviousPacket
) {
890 pSocket
->pTxPacketListHead
= pPacket
;
893 pPreviousPacket
->pNext
= pPacket
;
895 pSocket
->pTxPacketListTail
= pPacket
;
897 "0x%08x: Packet on transmit list\r\n",
901 // Account for the buffered data
903 *pTxBytes
+= BufferLength
;
904 *pDataLength
= BufferLength
;
907 // Start the transmit engine if it is idle
909 if ( NULL
!= pPort
->pTxFree
) {
910 EslSocketTxStart ( pPort
,
911 &pSocket
->pTxPacketListHead
,
912 &pSocket
->pTxPacketListTail
,
919 // Previous transmit error
922 Status
= pSocket
->TxError
;
923 pSocket
->errno
= EIO
;
928 EslSocketPacketFree ( pPacket
, DEBUG_TX
);
932 // Release the socket layer synchronization
934 RESTORE_TPL ( TplPrevious
);
938 // Packet allocation failed
940 pSocket
->errno
= ENOMEM
;
945 // Not enough buffer space available
947 pSocket
->errno
= EAGAIN
;
948 Status
= EFI_NOT_READY
;
954 // Return the operation status
956 DBG_EXIT_STATUS ( Status
);
962 Process the transmit completion
964 This routine use ::EslSocketTxComplete to perform the transmit
965 completion processing for data packets.
967 This routine is called by the UDPv4 network layer when a data
968 transmit request completes.
970 @param [in] Event The normal transmit completion event
972 @param [in] pIo Address of an ::ESL_IO_MGMT structure
981 UINT32 LengthInBytes
;
983 ESL_PACKET
* pPacket
;
984 ESL_SOCKET
* pSocket
;
990 // Locate the active transmit packet
992 pPacket
= pIo
->pPacket
;
994 pSocket
= pPort
->pSocket
;
997 // Get the transmit length and status
999 LengthInBytes
= pPacket
->Op
.Udp4Tx
.TxData
.DataLength
;
1000 pSocket
->TxBytes
-= LengthInBytes
;
1001 Status
= pIo
->Token
.Udp4Tx
.Status
;
1004 // Complete the transmit operation
1006 EslSocketTxComplete ( pIo
,
1010 &pSocket
->pTxPacketListHead
,
1011 &pSocket
->pTxPacketListTail
,
1019 Interface between the socket layer and the network specific
1020 code that supports SOCK_DGRAM sockets over UDPv4.
1022 CONST ESL_PROTOCOL_API cEslUdp4Api
= {
1025 OFFSET_OF ( ESL_PORT
, Context
.Udp4
.ConfigData
),
1026 OFFSET_OF ( ESL_LAYER
, pUdp4List
),
1027 OFFSET_OF ( struct sockaddr_in
, sin_zero
),
1028 sizeof ( struct sockaddr_in
),
1030 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1031 sizeof (((ESL_PACKET
*)0 )->Op
.Udp4Rx
),
1032 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp4Rx
.Packet
.RxData
),
1036 NULL
, // ConnectPoll
1037 NULL
, // ConnectStart
1038 EslUdp4SocketIsConfigured
,
1039 EslUdp4LocalAddressGet
,
1040 EslUdp4LocalAddressSet
,
1045 EslUdp4PortAllocate
,
1047 NULL
, // PortCloseOp
1050 EslUdp4RemoteAddressGet
,
1051 EslUdp4RemoteAddressSet
,
1056 NULL
// TxOobComplete