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 IPv6 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 EslUdp6LocalAddressGet (
35 OUT
struct sockaddr
* pSockAddr
38 struct sockaddr_in6
* pLocalAddress
;
39 ESL_UDP6_CONTEXT
* pUdp6
;
44 // Return the local address
46 pUdp6
= &pPort
->Context
.Udp6
;
47 pLocalAddress
= (struct sockaddr_in6
*)pSockAddr
;
48 pLocalAddress
->sin6_family
= AF_INET6
;
49 pLocalAddress
->sin6_port
= SwapBytes16 ( pUdp6
->ConfigData
.StationPort
);
50 CopyMem ( &pLocalAddress
->sin6_addr
,
51 &pUdp6
->ConfigData
.StationAddress
.Addr
[0],
52 sizeof ( pLocalAddress
->sin6_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 IPv6 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 IPv6 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 EslUdp6LocalAddressSet (
84 IN CONST
struct sockaddr
* pSockAddr
,
88 EFI_UDP6_CONFIG_DATA
* pConfig
;
89 CONST
struct sockaddr_in6
* pIpAddress
;
90 CONST UINT8
* pIPv6Address
;
96 // Set the local address
98 pIpAddress
= (struct sockaddr_in6
*)pSockAddr
;
99 pIPv6Address
= (UINT8
*)&pIpAddress
->sin6_addr
;
100 pConfig
= &pPort
->Context
.Udp6
.ConfigData
;
101 CopyMem ( &pConfig
->StationAddress
,
103 sizeof ( pConfig
->StationAddress
));
106 // Validate the IP address
108 pConfig
->StationPort
= 0;
109 Status
= bBindTest
? EslSocketBindTest ( pPort
, EADDRNOTAVAIL
)
111 if ( !EFI_ERROR ( Status
)) {
113 // Set the port number
115 pConfig
->StationPort
= SwapBytes16 ( pIpAddress
->sin6_port
);
116 pPort
->pSocket
->bAddressSet
= TRUE
;
119 // Display the local address
122 "0x%08x: Port, Local UDP6 Address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
124 pConfig
->StationAddress
.Addr
[0],
125 pConfig
->StationAddress
.Addr
[1],
126 pConfig
->StationAddress
.Addr
[2],
127 pConfig
->StationAddress
.Addr
[3],
128 pConfig
->StationAddress
.Addr
[4],
129 pConfig
->StationAddress
.Addr
[5],
130 pConfig
->StationAddress
.Addr
[6],
131 pConfig
->StationAddress
.Addr
[7],
132 pConfig
->StationAddress
.Addr
[8],
133 pConfig
->StationAddress
.Addr
[9],
134 pConfig
->StationAddress
.Addr
[10],
135 pConfig
->StationAddress
.Addr
[11],
136 pConfig
->StationAddress
.Addr
[12],
137 pConfig
->StationAddress
.Addr
[13],
138 pConfig
->StationAddress
.Addr
[14],
139 pConfig
->StationAddress
.Addr
[15],
140 pConfig
->StationPort
));
144 // Return the operation status
146 DBG_EXIT_STATUS ( Status
);
152 Free a receive packet
154 This routine performs the network specific operations necessary
155 to free a receive packet.
157 This routine is called by ::EslSocketPortCloseTxDone to free a
160 @param [in] pPacket Address of an ::ESL_PACKET structure.
161 @param [in, out] pRxBytes Address of the count of RX bytes
166 IN ESL_PACKET
* pPacket
,
167 IN OUT
size_t * pRxBytes
170 EFI_UDP6_RECEIVE_DATA
* pRxData
;
175 // Account for the receive bytes
177 pRxData
= pPacket
->Op
.Udp6Rx
.pRxData
;
178 *pRxBytes
-= pRxData
->DataLength
;
181 // Disconnect the buffer from the packet
183 pPacket
->Op
.Udp6Rx
.pRxData
= NULL
;
186 // Return the buffer to the UDP6 driver
188 gBS
->SignalEvent ( pRxData
->RecycleSignal
);
194 Initialize the network specific portions of an ::ESL_PORT structure.
196 This routine initializes the network specific portions of an
197 ::ESL_PORT structure for use by the socket.
199 This support routine is called by ::EslSocketPortAllocate
200 to connect the socket with the underlying network adapter
201 running the UDPv4 protocol.
203 @param [in] pPort Address of an ESL_PORT structure
204 @param [in] DebugFlags Flags for debug messages
206 @retval EFI_SUCCESS - Socket successfully created
210 EslUdp6PortAllocate (
215 EFI_UDP6_CONFIG_DATA
* pConfig
;
216 ESL_SOCKET
* pSocket
;
222 // Initialize the port
224 pSocket
= pPort
->pSocket
;
225 pSocket
->TxPacketOffset
= OFFSET_OF ( ESL_PACKET
, Op
.Udp6Tx
.TxData
);
226 pSocket
->TxTokenEventOffset
= OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp6Tx
.Event
);
227 pSocket
->TxTokenOffset
= OFFSET_OF ( EFI_UDP6_COMPLETION_TOKEN
, Packet
.TxData
);
230 // Save the cancel, receive and transmit addresses
232 pPort
->pfnConfigure
= (PFN_NET_CONFIGURE
)pPort
->pProtocol
.UDPv6
->Configure
;
233 pPort
->pfnRxCancel
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Cancel
;
234 pPort
->pfnRxPoll
= (PFN_NET_POLL
)pPort
->pProtocol
.UDPv6
->Poll
;
235 pPort
->pfnRxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Receive
;
236 pPort
->pfnTxStart
= (PFN_NET_IO_START
)pPort
->pProtocol
.UDPv6
->Transmit
;
239 // Do not drop packets
241 pConfig
= &pPort
->Context
.Udp6
.ConfigData
;
242 pConfig
->ReceiveTimeout
= 0;
243 pConfig
->ReceiveTimeout
= pConfig
->ReceiveTimeout
;
246 // Set the configuration flags
248 pConfig
->AllowDuplicatePort
= TRUE
;
249 pConfig
->AcceptAnyPort
= FALSE
;
250 pConfig
->AcceptPromiscuous
= FALSE
;
251 pConfig
->HopLimit
= 255;
252 pConfig
->TrafficClass
= 0;
254 Status
= EFI_SUCCESS
;
257 // Return the operation status
259 DBG_EXIT_STATUS ( Status
);
265 Receive data from a network connection.
267 This routine attempts to return buffered data to the caller. The
268 data is removed from the urgent queue if the message flag MSG_OOB
269 is specified, otherwise data is removed from the normal queue.
270 See the \ref ReceiveEngine section.
272 This routine is called by ::EslSocketReceive to handle the network
273 specific receive operation to support SOCK_DGRAM sockets.
275 @param [in] pPort Address of an ::ESL_PORT structure.
277 @param [in] pPacket Address of an ::ESL_PACKET structure.
279 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed
281 @param [in] BufferLength Length of the the buffer
283 @param [in] pBuffer Address of a buffer to receive the data.
285 @param [in] pDataLength Number of received data bytes in the buffer.
287 @param [out] pAddress Network address to receive the remote system address
289 @param [out] pSkipBytes Address to receive the number of bytes skipped
291 @return Returns the address of the next free byte in the buffer.
297 IN ESL_PACKET
* pPacket
,
298 IN BOOLEAN
* pbConsumePacket
,
299 IN
size_t BufferLength
,
301 OUT
size_t * pDataLength
,
302 OUT
struct sockaddr
* pAddress
,
303 OUT
size_t * pSkipBytes
307 struct sockaddr_in6
* pRemoteAddress
;
308 EFI_UDP6_RECEIVE_DATA
* pRxData
;
312 pRxData
= pPacket
->Op
.Udp6Rx
.pRxData
;
314 // Return the remote system address if requested
316 if ( NULL
!= pAddress
) {
318 // Build the remote address
321 "Getting packet remote address: [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
322 pRxData
->UdpSession
.SourceAddress
.Addr
[0],
323 pRxData
->UdpSession
.SourceAddress
.Addr
[1],
324 pRxData
->UdpSession
.SourceAddress
.Addr
[2],
325 pRxData
->UdpSession
.SourceAddress
.Addr
[3],
326 pRxData
->UdpSession
.SourceAddress
.Addr
[4],
327 pRxData
->UdpSession
.SourceAddress
.Addr
[5],
328 pRxData
->UdpSession
.SourceAddress
.Addr
[6],
329 pRxData
->UdpSession
.SourceAddress
.Addr
[7],
330 pRxData
->UdpSession
.SourceAddress
.Addr
[8],
331 pRxData
->UdpSession
.SourceAddress
.Addr
[9],
332 pRxData
->UdpSession
.SourceAddress
.Addr
[10],
333 pRxData
->UdpSession
.SourceAddress
.Addr
[11],
334 pRxData
->UdpSession
.SourceAddress
.Addr
[12],
335 pRxData
->UdpSession
.SourceAddress
.Addr
[13],
336 pRxData
->UdpSession
.SourceAddress
.Addr
[14],
337 pRxData
->UdpSession
.SourceAddress
.Addr
[15],
338 pRxData
->UdpSession
.SourcePort
));
339 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
340 CopyMem ( &pRemoteAddress
->sin6_addr
,
341 &pRxData
->UdpSession
.SourceAddress
.Addr
[0],
342 sizeof ( pRemoteAddress
->sin6_addr
));
343 pRemoteAddress
->sin6_port
= SwapBytes16 ( pRxData
->UdpSession
.SourcePort
);
347 // Copy the received data
349 pBuffer
= EslSocketCopyFragmentedBuffer ( pRxData
->FragmentCount
,
350 (EFI_IP4_FRAGMENT_DATA
*)&pRxData
->FragmentTable
[0],
356 // Determine if the data is being read
358 if ( *pbConsumePacket
) {
360 // Display for the bytes consumed
363 "0x%08x: Port account for 0x%08x bytes\r\n",
368 // Account for any discarded data
370 *pSkipBytes
= pRxData
->DataLength
- DataBytes
;
374 // Return the data length and the buffer address
376 *pDataLength
= DataBytes
;
377 DBG_EXIT_HEX ( pBuffer
);
383 Get the remote socket address
385 This routine returns the address of the remote connection point
386 associated with the SOCK_DGRAM socket.
388 This routine is called by ::EslSocketGetPeerAddress to detemine
389 the UDPv4 address and port number associated with the network adapter.
391 @param [in] pPort Address of an ::ESL_PORT structure.
393 @param [out] pAddress Network address to receive the remote system address
397 EslUdp6RemoteAddressGet (
399 OUT
struct sockaddr
* pAddress
402 struct sockaddr_in6
* pRemoteAddress
;
403 ESL_UDP6_CONTEXT
* pUdp6
;
408 // Return the remote address
410 pUdp6
= &pPort
->Context
.Udp6
;
411 pRemoteAddress
= (struct sockaddr_in6
*)pAddress
;
412 pRemoteAddress
->sin6_family
= AF_INET6
;
413 pRemoteAddress
->sin6_port
= SwapBytes16 ( pUdp6
->ConfigData
.RemotePort
);
414 CopyMem ( &pRemoteAddress
->sin6_addr
,
415 &pUdp6
->ConfigData
.RemoteAddress
.Addr
[0],
416 sizeof ( pRemoteAddress
->sin6_addr
));
423 Set the remote address
425 This routine sets the remote address in the port.
427 This routine is called by ::EslSocketConnect to specify the
428 remote network address.
430 @param [in] pPort Address of an ::ESL_PORT structure.
432 @param [in] pSockAddr Network address of the remote system.
434 @param [in] SockAddrLength Length in bytes of the network address.
436 @retval EFI_SUCCESS The operation was successful
440 EslUdp6RemoteAddressSet (
442 IN CONST
struct sockaddr
* pSockAddr
,
443 IN socklen_t SockAddrLength
446 CONST
struct sockaddr_in6
* pRemoteAddress
;
447 ESL_UDP6_CONTEXT
* pUdp6
;
453 // Set the remote address
455 pUdp6
= &pPort
->Context
.Udp6
;
456 pRemoteAddress
= (struct sockaddr_in6
*)pSockAddr
;
457 CopyMem ( &pUdp6
->ConfigData
.RemoteAddress
,
458 &pRemoteAddress
->sin6_addr
,
459 sizeof ( pUdp6
->ConfigData
.RemoteAddress
));
460 pUdp6
->ConfigData
.RemotePort
= SwapBytes16 ( pRemoteAddress
->sin6_port
);
461 Status
= EFI_SUCCESS
;
464 // Return the operation status
466 DBG_EXIT_STATUS ( Status
);
472 Process the receive completion
474 This routine keeps the UDPv4 driver's buffer and queues it in
475 in FIFO order to the data queue. The UDP6 driver's buffer will
476 be returned by either ::EslUdp6Receive or ::EslSocketPortCloseTxDone.
477 See the \ref ReceiveEngine section.
479 This routine is called by the UDPv4 driver when data is
482 @param [in] Event The receive completion event
484 @param [in] pIo Address of an ::ESL_IO_MGMT structure
493 size_t LengthInBytes
;
494 ESL_PACKET
* pPacket
;
495 EFI_UDP6_RECEIVE_DATA
* pRxData
;
501 // Get the operation status.
503 Status
= pIo
->Token
.Udp6Rx
.Status
;
506 // Get the packet length
508 pRxData
= pIo
->Token
.Udp6Rx
.Packet
.RxData
;
509 LengthInBytes
= pRxData
->DataLength
;
512 // +--------------------+ +-----------------------+
513 // | ESL_IO_MGMT | | Data Buffer |
514 // | | | (Driver owned) |
515 // | +---------------+ +-----------------------+
518 // | | | +-----------------------+
519 // | | RxData --> | EFI_UDP6_RECEIVE_DATA |
520 // +----+---------------+ | (Driver owned) |
521 // +-----------------------+
522 // +--------------------+ ^
525 // | +---------------+ .
526 // | | pRxData --> NULL .......
527 // +----+---------------+
530 // Save the data in the packet
532 pPacket
= pIo
->pPacket
;
533 pPacket
->Op
.Udp6Rx
.pRxData
= pRxData
;
536 // Complete this request
538 EslSocketRxComplete ( pIo
, Status
, LengthInBytes
, FALSE
);
544 Determine if the socket is configured.
546 This routine uses the flag ESL_SOCKET::bConfigured to determine
547 if the network layer's configuration routine has been called.
548 This routine calls the bind and configuration routines if they
549 were not already called. After the port is configured, the
550 \ref ReceiveEngine is started.
552 This routine is called by EslSocketIsConfigured to verify
553 that the socket is configured.
555 @param [in] pSocket Address of an ::ESL_SOCKET structure
557 @retval EFI_SUCCESS - The port is connected
558 @retval EFI_NOT_STARTED - The port is not connected
562 EslUdp6SocketIsConfigured (
563 IN ESL_SOCKET
* pSocket
566 EFI_UDP6_CONFIG_DATA
* pConfigData
;
568 ESL_PORT
* pNextPort
;
569 ESL_UDP6_CONTEXT
* pUdp6
;
570 EFI_UDP6_PROTOCOL
* pUdp6Protocol
;
572 struct sockaddr_in6 LocalAddress
;
579 Status
= EFI_SUCCESS
;
582 // Configure the port if necessary
584 if ( !pSocket
->bConfigured
) {
586 // Fill in the port list if necessary
588 pSocket
->errno
= ENETDOWN
;
589 if ( NULL
== pSocket
->pPortList
) {
590 ZeroMem ( &LocalAddress
, sizeof ( LocalAddress
));
591 LocalAddress
.sin6_len
= sizeof ( LocalAddress
);
592 LocalAddress
.sin6_family
= AF_INET6
;
593 Status
= EslSocketBind ( &pSocket
->SocketProtocol
,
594 (struct sockaddr
*)&LocalAddress
,
595 LocalAddress
.sin6_len
,
600 // Walk the port list
602 pPort
= pSocket
->pPortList
;
603 while ( NULL
!= pPort
) {
605 // Attempt to configure the port
607 pNextPort
= pPort
->pLinkSocket
;
608 pUdp6
= &pPort
->Context
.Udp6
;
609 pUdp6Protocol
= pPort
->pProtocol
.UDPv6
;
610 pConfigData
= &pUdp6
->ConfigData
;
612 "0x%08x: pPort Configuring for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",
614 pConfigData
->StationAddress
.Addr
[0],
615 pConfigData
->StationAddress
.Addr
[1],
616 pConfigData
->StationAddress
.Addr
[2],
617 pConfigData
->StationAddress
.Addr
[3],
618 pConfigData
->StationAddress
.Addr
[4],
619 pConfigData
->StationAddress
.Addr
[5],
620 pConfigData
->StationAddress
.Addr
[6],
621 pConfigData
->StationAddress
.Addr
[7],
622 pConfigData
->StationAddress
.Addr
[8],
623 pConfigData
->StationAddress
.Addr
[9],
624 pConfigData
->StationAddress
.Addr
[10],
625 pConfigData
->StationAddress
.Addr
[11],
626 pConfigData
->StationAddress
.Addr
[12],
627 pConfigData
->StationAddress
.Addr
[13],
628 pConfigData
->StationAddress
.Addr
[14],
629 pConfigData
->StationAddress
.Addr
[15],
630 pConfigData
->StationPort
));
632 "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
633 pConfigData
->RemoteAddress
.Addr
[0],
634 pConfigData
->RemoteAddress
.Addr
[1],
635 pConfigData
->RemoteAddress
.Addr
[2],
636 pConfigData
->RemoteAddress
.Addr
[3],
637 pConfigData
->RemoteAddress
.Addr
[4],
638 pConfigData
->RemoteAddress
.Addr
[5],
639 pConfigData
->RemoteAddress
.Addr
[6],
640 pConfigData
->RemoteAddress
.Addr
[7],
641 pConfigData
->RemoteAddress
.Addr
[8],
642 pConfigData
->RemoteAddress
.Addr
[9],
643 pConfigData
->RemoteAddress
.Addr
[10],
644 pConfigData
->RemoteAddress
.Addr
[11],
645 pConfigData
->RemoteAddress
.Addr
[12],
646 pConfigData
->RemoteAddress
.Addr
[13],
647 pConfigData
->RemoteAddress
.Addr
[14],
648 pConfigData
->RemoteAddress
.Addr
[15],
649 pConfigData
->RemotePort
));
650 Status
= pUdp6Protocol
->Configure ( pUdp6Protocol
,
652 if ( !EFI_ERROR ( Status
)) {
654 // Update the configuration data
656 Status
= pUdp6Protocol
->GetModeData ( pUdp6Protocol
,
662 if ( EFI_ERROR ( Status
)) {
663 if ( !pSocket
->bConfigured
) {
664 DEBUG (( DEBUG_LISTEN
,
665 "ERROR - Failed to configure the Udp6 port, Status: %r\r\n",
668 case EFI_ACCESS_DENIED
:
669 pSocket
->errno
= EACCES
;
673 case EFI_DEVICE_ERROR
:
674 pSocket
->errno
= EIO
;
677 case EFI_INVALID_PARAMETER
:
678 pSocket
->errno
= EADDRNOTAVAIL
;
682 pSocket
->errno
= EAFNOSUPPORT
;
685 case EFI_OUT_OF_RESOURCES
:
686 pSocket
->errno
= ENOBUFS
;
689 case EFI_UNSUPPORTED
:
690 pSocket
->errno
= EOPNOTSUPP
;
697 "0x%08x: pPort Configured for [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d --> ",
699 pConfigData
->StationAddress
.Addr
[0],
700 pConfigData
->StationAddress
.Addr
[1],
701 pConfigData
->StationAddress
.Addr
[2],
702 pConfigData
->StationAddress
.Addr
[3],
703 pConfigData
->StationAddress
.Addr
[4],
704 pConfigData
->StationAddress
.Addr
[5],
705 pConfigData
->StationAddress
.Addr
[6],
706 pConfigData
->StationAddress
.Addr
[7],
707 pConfigData
->StationAddress
.Addr
[8],
708 pConfigData
->StationAddress
.Addr
[9],
709 pConfigData
->StationAddress
.Addr
[10],
710 pConfigData
->StationAddress
.Addr
[11],
711 pConfigData
->StationAddress
.Addr
[12],
712 pConfigData
->StationAddress
.Addr
[13],
713 pConfigData
->StationAddress
.Addr
[14],
714 pConfigData
->StationAddress
.Addr
[15],
715 pConfigData
->StationPort
));
717 "[%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
718 pConfigData
->RemoteAddress
.Addr
[0],
719 pConfigData
->RemoteAddress
.Addr
[1],
720 pConfigData
->RemoteAddress
.Addr
[2],
721 pConfigData
->RemoteAddress
.Addr
[3],
722 pConfigData
->RemoteAddress
.Addr
[4],
723 pConfigData
->RemoteAddress
.Addr
[5],
724 pConfigData
->RemoteAddress
.Addr
[6],
725 pConfigData
->RemoteAddress
.Addr
[7],
726 pConfigData
->RemoteAddress
.Addr
[8],
727 pConfigData
->RemoteAddress
.Addr
[9],
728 pConfigData
->RemoteAddress
.Addr
[10],
729 pConfigData
->RemoteAddress
.Addr
[11],
730 pConfigData
->RemoteAddress
.Addr
[12],
731 pConfigData
->RemoteAddress
.Addr
[13],
732 pConfigData
->RemoteAddress
.Addr
[14],
733 pConfigData
->RemoteAddress
.Addr
[15],
734 pConfigData
->RemotePort
));
735 pPort
->bConfigured
= TRUE
;
736 pSocket
->bConfigured
= TRUE
;
739 // Start the first read on the port
741 EslSocketRxStart ( pPort
);
744 // The socket is connected
746 pSocket
->State
= SOCKET_STATE_CONNECTED
;
758 // Determine the socket configuration status
760 Status
= pSocket
->bConfigured
? EFI_SUCCESS
: EFI_NOT_STARTED
;
763 // Return the port connected state.
765 DBG_EXIT_STATUS ( Status
);
771 Buffer data for transmission over a network connection.
773 This routine buffers data for the transmit engine in the normal
774 data queue. When the \ref TransmitEngine has resources, this
775 routine will start the transmission of the next buffer on the
778 This routine is called by ::EslSocketTransmit to buffer
779 data for transmission. The data is copied into a local buffer
780 freeing the application buffer for reuse upon return. When
781 necessary, this routine starts the transmit engine that
782 performs the data transmission on the network connection. The
783 transmit engine transmits the data a packet at a time over the
786 Transmission errors are returned during the next transmission or
787 during the close operation. Only buffering errors are returned
788 during the current transmission attempt.
790 @param [in] pSocket Address of an ::ESL_SOCKET structure
792 @param [in] Flags Message control flags
794 @param [in] BufferLength Length of the the buffer
796 @param [in] pBuffer Address of a buffer to receive the data.
798 @param [in] pDataLength Number of received data bytes in the buffer.
800 @param [in] pAddress Network address of the remote system address
802 @param [in] AddressLength Length of the remote network address structure
804 @retval EFI_SUCCESS - Socket data successfully buffered
809 IN ESL_SOCKET
* pSocket
,
811 IN
size_t BufferLength
,
812 IN CONST UINT8
* pBuffer
,
813 OUT
size_t * pDataLength
,
814 IN
const struct sockaddr
* pAddress
,
815 IN socklen_t AddressLength
818 ESL_PACKET
* pPacket
;
819 ESL_PACKET
* pPreviousPacket
;
821 const struct sockaddr_in6
* pRemoteAddress
;
822 ESL_UDP6_CONTEXT
* pUdp6
;
824 ESL_UDP6_TX_DATA
* pTxData
;
833 Status
= EFI_UNSUPPORTED
;
834 pSocket
->errno
= ENOTCONN
;
838 // Verify that the socket is connected
840 if ( SOCKET_STATE_CONNECTED
== pSocket
->State
) {
842 // Verify that there is enough room to buffer another
843 // transmit operation
845 pTxBytes
= &pSocket
->TxBytes
;
846 if ( pSocket
->MaxTxBuf
> *pTxBytes
) {
850 pPort
= pSocket
->pPortList
;
851 while ( NULL
!= pPort
) {
853 // Determine the queue head
855 pUdp6
= &pPort
->Context
.Udp6
;
858 // Attempt to allocate the packet
860 Status
= EslSocketPacketAllocate ( &pPacket
,
861 sizeof ( pPacket
->Op
.Udp6Tx
)
862 - sizeof ( pPacket
->Op
.Udp6Tx
.Buffer
)
866 if ( !EFI_ERROR ( Status
)) {
868 // Initialize the transmit operation
870 pTxData
= &pPacket
->Op
.Udp6Tx
;
871 pTxData
->TxData
.UdpSessionData
= NULL
;
872 pTxData
->TxData
.DataLength
= (UINT32
) BufferLength
;
873 pTxData
->TxData
.FragmentCount
= 1;
874 pTxData
->TxData
.FragmentTable
[0].FragmentLength
= (UINT32
) BufferLength
;
875 pTxData
->TxData
.FragmentTable
[0].FragmentBuffer
= &pPacket
->Op
.Udp6Tx
.Buffer
[0];
878 // Set the remote system address if necessary
880 pTxData
->TxData
.UdpSessionData
= NULL
;
881 if ( NULL
!= pAddress
) {
882 pRemoteAddress
= (const struct sockaddr_in6
*)pAddress
;
883 CopyMem ( &pTxData
->Session
.SourceAddress
,
884 &pUdp6
->ConfigData
.StationAddress
,
885 sizeof ( pTxData
->Session
.SourceAddress
));
886 pTxData
->Session
.SourcePort
= 0;
887 CopyMem ( &pTxData
->Session
.DestinationAddress
,
888 &pRemoteAddress
->sin6_addr
,
889 sizeof ( pTxData
->Session
.DestinationAddress
));
890 pTxData
->Session
.DestinationPort
= SwapBytes16 ( pRemoteAddress
->sin6_port
);
893 // Use the remote system address when sending this packet
895 pTxData
->TxData
.UdpSessionData
= &pTxData
->Session
;
899 // Copy the data into the buffer
901 CopyMem ( &pPacket
->Op
.Udp6Tx
.Buffer
[0],
906 // Synchronize with the socket layer
908 RAISE_TPL ( TplPrevious
, TPL_SOCKETS
);
911 // Display the request
914 "Send %d bytes from 0x%08x to [%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x]:%d\r\n",
917 pTxData
->Session
.DestinationAddress
.Addr
[0],
918 pTxData
->Session
.DestinationAddress
.Addr
[1],
919 pTxData
->Session
.DestinationAddress
.Addr
[2],
920 pTxData
->Session
.DestinationAddress
.Addr
[3],
921 pTxData
->Session
.DestinationAddress
.Addr
[4],
922 pTxData
->Session
.DestinationAddress
.Addr
[5],
923 pTxData
->Session
.DestinationAddress
.Addr
[6],
924 pTxData
->Session
.DestinationAddress
.Addr
[7],
925 pTxData
->Session
.DestinationAddress
.Addr
[8],
926 pTxData
->Session
.DestinationAddress
.Addr
[9],
927 pTxData
->Session
.DestinationAddress
.Addr
[10],
928 pTxData
->Session
.DestinationAddress
.Addr
[11],
929 pTxData
->Session
.DestinationAddress
.Addr
[12],
930 pTxData
->Session
.DestinationAddress
.Addr
[13],
931 pTxData
->Session
.DestinationAddress
.Addr
[14],
932 pTxData
->Session
.DestinationAddress
.Addr
[15],
933 pTxData
->Session
.DestinationPort
));
936 // Queue the data for transmission
938 pPacket
->pNext
= NULL
;
939 pPreviousPacket
= pSocket
->pTxPacketListTail
;
940 if ( NULL
== pPreviousPacket
) {
941 pSocket
->pTxPacketListHead
= pPacket
;
944 pPreviousPacket
->pNext
= pPacket
;
946 pSocket
->pTxPacketListTail
= pPacket
;
948 "0x%08x: Packet on transmit list\r\n",
952 // Account for the buffered data
954 *pTxBytes
+= BufferLength
;
955 *pDataLength
= BufferLength
;
958 // Start the transmit engine if it is idle
960 if ( NULL
!= pPort
->pTxFree
) {
961 EslSocketTxStart ( pPort
,
962 &pSocket
->pTxPacketListHead
,
963 &pSocket
->pTxPacketListTail
,
968 // Ignore any transmit error
970 if ( EFI_ERROR ( pSocket
->TxError
)) {
972 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",
977 pSocket
->TxError
= EFI_SUCCESS
;
981 // Release the socket layer synchronization
983 RESTORE_TPL ( TplPrevious
);
987 // Packet allocation failed
989 pSocket
->errno
= ENOMEM
;
996 pPort
= pPort
->pLinkSocket
;
1001 // Not enough buffer space available
1003 pSocket
->errno
= EAGAIN
;
1004 Status
= EFI_NOT_READY
;
1009 // Return the operation status
1011 DBG_EXIT_STATUS ( Status
);
1017 Process the transmit completion
1019 This routine use ::EslSocketTxComplete to perform the transmit
1020 completion processing for data packets.
1022 This routine is called by the UDPv4 network layer when a data
1023 transmit request completes.
1025 @param [in] Event The normal transmit completion event
1027 @param [in] pIo Address of an ::ESL_IO_MGMT structure
1033 IN ESL_IO_MGMT
* pIo
1036 UINT32 LengthInBytes
;
1038 ESL_PACKET
* pPacket
;
1039 ESL_SOCKET
* pSocket
;
1045 // Locate the active transmit packet
1047 pPacket
= pIo
->pPacket
;
1049 pSocket
= pPort
->pSocket
;
1052 // Get the transmit length and status
1054 LengthInBytes
= pPacket
->Op
.Udp6Tx
.TxData
.DataLength
;
1055 pSocket
->TxBytes
-= LengthInBytes
;
1056 Status
= pIo
->Token
.Udp6Tx
.Status
;
1059 // Ignore the transmit error
1061 if ( EFI_ERROR ( Status
)) {
1063 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",
1067 Status
= EFI_SUCCESS
;
1071 // Complete the transmit operation
1073 EslSocketTxComplete ( pIo
,
1077 &pSocket
->pTxPacketListHead
,
1078 &pSocket
->pTxPacketListTail
,
1086 Verify the adapter's IP address
1088 This support routine is called by EslSocketBindTest.
1090 @param [in] pPort Address of an ::ESL_PORT structure.
1091 @param [in] pConfigData Address of the configuration data
1093 @retval EFI_SUCCESS - The IP address is valid
1094 @retval EFI_NOT_STARTED - The IP address is invalid
1098 EslUdp6VerifyLocalIpAddress (
1099 IN ESL_PORT
* pPort
,
1100 IN EFI_UDP6_CONFIG_DATA
* pConfigData
1104 EFI_IP6_ADDRESS_INFO
* pAddressInfo
;
1106 EFI_IP6_CONFIG_INTERFACE_INFO
* pIpConfigData
;
1107 EFI_IP6_CONFIG_PROTOCOL
* pIpConfigProtocol
;
1108 ESL_SERVICE
* pService
;
1114 // Use break instead of goto
1116 pIpConfigData
= NULL
;
1119 // Determine if the IP address is specified
1121 DEBUG (( DEBUG_BIND
,
1122 "Requested IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1123 pConfigData
->StationAddress
.Addr
[0],
1124 pConfigData
->StationAddress
.Addr
[1],
1125 pConfigData
->StationAddress
.Addr
[2],
1126 pConfigData
->StationAddress
.Addr
[3],
1127 pConfigData
->StationAddress
.Addr
[4],
1128 pConfigData
->StationAddress
.Addr
[5],
1129 pConfigData
->StationAddress
.Addr
[6],
1130 pConfigData
->StationAddress
.Addr
[7],
1131 pConfigData
->StationAddress
.Addr
[8],
1132 pConfigData
->StationAddress
.Addr
[9],
1133 pConfigData
->StationAddress
.Addr
[10],
1134 pConfigData
->StationAddress
.Addr
[11],
1135 pConfigData
->StationAddress
.Addr
[12],
1136 pConfigData
->StationAddress
.Addr
[13],
1137 pConfigData
->StationAddress
.Addr
[14],
1138 pConfigData
->StationAddress
.Addr
[15]));
1139 if (( 0 == pConfigData
->StationAddress
.Addr
[ 0 ])
1140 && ( 0 == pConfigData
->StationAddress
.Addr
[ 1 ])
1141 && ( 0 == pConfigData
->StationAddress
.Addr
[ 2 ])
1142 && ( 0 == pConfigData
->StationAddress
.Addr
[ 3 ])
1143 && ( 0 == pConfigData
->StationAddress
.Addr
[ 4 ])
1144 && ( 0 == pConfigData
->StationAddress
.Addr
[ 5 ])
1145 && ( 0 == pConfigData
->StationAddress
.Addr
[ 6 ])
1146 && ( 0 == pConfigData
->StationAddress
.Addr
[ 7 ])
1147 && ( 0 == pConfigData
->StationAddress
.Addr
[ 8 ])
1148 && ( 0 == pConfigData
->StationAddress
.Addr
[ 9 ])
1149 && ( 0 == pConfigData
->StationAddress
.Addr
[ 10 ])
1150 && ( 0 == pConfigData
->StationAddress
.Addr
[ 11 ])
1151 && ( 0 == pConfigData
->StationAddress
.Addr
[ 12 ])
1152 && ( 0 == pConfigData
->StationAddress
.Addr
[ 13 ])
1153 && ( 0 == pConfigData
->StationAddress
.Addr
[ 14 ])
1154 && ( 0 == pConfigData
->StationAddress
.Addr
[ 15 ]))
1156 Status
= EFI_SUCCESS
;
1161 // Open the configuration protocol
1163 pService
= pPort
->pService
;
1164 Status
= gBS
->OpenProtocol ( pService
->Controller
,
1165 &gEfiIp6ConfigProtocolGuid
,
1166 (VOID
**)&pIpConfigProtocol
,
1169 EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
1170 if ( EFI_ERROR ( Status
)) {
1171 DEBUG (( DEBUG_ERROR
,
1172 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",
1178 // Get the IP configuration data size
1181 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1182 Ip6ConfigDataTypeInterfaceInfo
,
1185 if ( EFI_BUFFER_TOO_SMALL
!= Status
) {
1186 DEBUG (( DEBUG_ERROR
,
1187 "ERROR - Failed to get IP Configuration data size, Status: %r\r\n",
1193 // Allocate the configuration data buffer
1195 pIpConfigData
= AllocatePool ( DataSize
);
1196 if ( NULL
== pIpConfigData
) {
1197 DEBUG (( DEBUG_ERROR
,
1198 "ERROR - Not enough memory to allocate IP Configuration data!\r\n" ));
1199 Status
= EFI_OUT_OF_RESOURCES
;
1204 // Get the IP configuration
1206 Status
= pIpConfigProtocol
->GetData ( pIpConfigProtocol
,
1207 Ip6ConfigDataTypeInterfaceInfo
,
1210 if ( EFI_ERROR ( Status
)) {
1211 DEBUG (( DEBUG_ERROR
,
1212 "ERROR - Failed to return IP Configuration data, Status: %r\r\n",
1218 // Display the current configuration
1220 DEBUG (( DEBUG_BIND
,
1221 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1222 pIpConfigData
->HwAddress
.Addr
[ 0 ],
1223 pIpConfigData
->HwAddress
.Addr
[ 1 ],
1224 pIpConfigData
->HwAddress
.Addr
[ 2 ],
1225 pIpConfigData
->HwAddress
.Addr
[ 3 ],
1226 pIpConfigData
->HwAddress
.Addr
[ 4 ],
1227 pIpConfigData
->HwAddress
.Addr
[ 5 ],
1228 pIpConfigData
->HwAddress
.Addr
[ 6 ],
1229 pIpConfigData
->HwAddress
.Addr
[ 7 ],
1230 pIpConfigData
->HwAddress
.Addr
[ 8 ],
1231 pIpConfigData
->HwAddress
.Addr
[ 9 ],
1232 pIpConfigData
->HwAddress
.Addr
[ 10 ],
1233 pIpConfigData
->HwAddress
.Addr
[ 11 ],
1234 pIpConfigData
->HwAddress
.Addr
[ 12 ],
1235 pIpConfigData
->HwAddress
.Addr
[ 13 ],
1236 pIpConfigData
->HwAddress
.Addr
[ 14 ],
1237 pIpConfigData
->HwAddress
.Addr
[ 15 ]));
1240 // Validate the hardware address
1242 Status
= EFI_SUCCESS
;
1243 if (( 16 == pIpConfigData
->HwAddressSize
)
1244 && ( pConfigData
->StationAddress
.Addr
[ 0 ] == pIpConfigData
->HwAddress
.Addr
[ 0 ])
1245 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pIpConfigData
->HwAddress
.Addr
[ 1 ])
1246 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pIpConfigData
->HwAddress
.Addr
[ 2 ])
1247 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pIpConfigData
->HwAddress
.Addr
[ 3 ])
1248 && ( pConfigData
->StationAddress
.Addr
[ 4 ] == pIpConfigData
->HwAddress
.Addr
[ 4 ])
1249 && ( pConfigData
->StationAddress
.Addr
[ 5 ] == pIpConfigData
->HwAddress
.Addr
[ 5 ])
1250 && ( pConfigData
->StationAddress
.Addr
[ 6 ] == pIpConfigData
->HwAddress
.Addr
[ 6 ])
1251 && ( pConfigData
->StationAddress
.Addr
[ 7 ] == pIpConfigData
->HwAddress
.Addr
[ 7 ])
1252 && ( pConfigData
->StationAddress
.Addr
[ 8 ] == pIpConfigData
->HwAddress
.Addr
[ 8 ])
1253 && ( pConfigData
->StationAddress
.Addr
[ 9 ] == pIpConfigData
->HwAddress
.Addr
[ 9 ])
1254 && ( pConfigData
->StationAddress
.Addr
[ 10 ] == pIpConfigData
->HwAddress
.Addr
[ 10 ])
1255 && ( pConfigData
->StationAddress
.Addr
[ 11 ] == pIpConfigData
->HwAddress
.Addr
[ 11 ])
1256 && ( pConfigData
->StationAddress
.Addr
[ 12 ] == pIpConfigData
->HwAddress
.Addr
[ 12 ])
1257 && ( pConfigData
->StationAddress
.Addr
[ 13 ] == pIpConfigData
->HwAddress
.Addr
[ 13 ])
1258 && ( pConfigData
->StationAddress
.Addr
[ 14 ] == pIpConfigData
->HwAddress
.Addr
[ 14 ])
1259 && ( pConfigData
->StationAddress
.Addr
[ 15 ] == pIpConfigData
->HwAddress
.Addr
[ 15 ])) {
1264 // Walk the list of other IP addresses assigned to this adapter
1266 for ( AddressCount
= 0; pIpConfigData
->AddressInfoCount
> AddressCount
; AddressCount
+= 1 ) {
1267 pAddressInfo
= &pIpConfigData
->AddressInfo
[ AddressCount
];
1270 // Display the IP address
1272 DEBUG (( DEBUG_BIND
,
1273 "Actual adapter IP address: %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x\r\n",
1274 pAddressInfo
->Address
.Addr
[ 0 ],
1275 pAddressInfo
->Address
.Addr
[ 1 ],
1276 pAddressInfo
->Address
.Addr
[ 2 ],
1277 pAddressInfo
->Address
.Addr
[ 3 ],
1278 pAddressInfo
->Address
.Addr
[ 4 ],
1279 pAddressInfo
->Address
.Addr
[ 5 ],
1280 pAddressInfo
->Address
.Addr
[ 6 ],
1281 pAddressInfo
->Address
.Addr
[ 7 ],
1282 pAddressInfo
->Address
.Addr
[ 8 ],
1283 pAddressInfo
->Address
.Addr
[ 9 ],
1284 pAddressInfo
->Address
.Addr
[ 10 ],
1285 pAddressInfo
->Address
.Addr
[ 11 ],
1286 pAddressInfo
->Address
.Addr
[ 12 ],
1287 pAddressInfo
->Address
.Addr
[ 13 ],
1288 pAddressInfo
->Address
.Addr
[ 14 ],
1289 pAddressInfo
->Address
.Addr
[ 15 ]));
1292 // Validate the IP address
1294 if (( pConfigData
->StationAddress
.Addr
[ 0 ] == pAddressInfo
->Address
.Addr
[ 0 ])
1295 && ( pConfigData
->StationAddress
.Addr
[ 1 ] == pAddressInfo
->Address
.Addr
[ 1 ])
1296 && ( pConfigData
->StationAddress
.Addr
[ 2 ] == pAddressInfo
->Address
.Addr
[ 2 ])
1297 && ( pConfigData
->StationAddress
.Addr
[ 3 ] == pAddressInfo
->Address
.Addr
[ 3 ])
1298 && ( pConfigData
->StationAddress
.Addr
[ 4 ] == pAddressInfo
->Address
.Addr
[ 4 ])
1299 && ( pConfigData
->StationAddress
.Addr
[ 5 ] == pAddressInfo
->Address
.Addr
[ 5 ])
1300 && ( pConfigData
->StationAddress
.Addr
[ 6 ] == pAddressInfo
->Address
.Addr
[ 6 ])
1301 && ( pConfigData
->StationAddress
.Addr
[ 7 ] == pAddressInfo
->Address
.Addr
[ 7 ])
1302 && ( pConfigData
->StationAddress
.Addr
[ 8 ] == pAddressInfo
->Address
.Addr
[ 8 ])
1303 && ( pConfigData
->StationAddress
.Addr
[ 9 ] == pAddressInfo
->Address
.Addr
[ 9 ])
1304 && ( pConfigData
->StationAddress
.Addr
[ 10 ] == pAddressInfo
->Address
.Addr
[ 10 ])
1305 && ( pConfigData
->StationAddress
.Addr
[ 11 ] == pAddressInfo
->Address
.Addr
[ 11 ])
1306 && ( pConfigData
->StationAddress
.Addr
[ 12 ] == pAddressInfo
->Address
.Addr
[ 12 ])
1307 && ( pConfigData
->StationAddress
.Addr
[ 13 ] == pAddressInfo
->Address
.Addr
[ 13 ])
1308 && ( pConfigData
->StationAddress
.Addr
[ 14 ] == pAddressInfo
->Address
.Addr
[ 14 ])
1309 && ( pConfigData
->StationAddress
.Addr
[ 15 ] == pAddressInfo
->Address
.Addr
[ 15 ])) {
1313 if ( pIpConfigData
->AddressInfoCount
> AddressCount
) {
1318 // The IP address did not match
1320 Status
= EFI_NOT_STARTED
;
1325 // Free the buffer if necessary
1327 if ( NULL
!= pIpConfigData
) {
1328 FreePool ( pIpConfigData
);
1332 // Return the IP address status
1334 DBG_EXIT_STATUS ( Status
);
1340 Interface between the socket layer and the network specific
1341 code that supports SOCK_DGRAM sockets over UDPv4.
1343 CONST ESL_PROTOCOL_API cEslUdp6Api
= {
1346 OFFSET_OF ( ESL_PORT
, Context
.Udp6
.ConfigData
),
1347 OFFSET_OF ( ESL_LAYER
, pUdp6List
),
1348 sizeof ( struct sockaddr_in6
),
1349 sizeof ( struct sockaddr_in6
),
1351 sizeof (((ESL_PACKET
*)0 )->Op
.Udp6Rx
),
1352 sizeof (((ESL_PACKET
*)0 )->Op
.Udp6Rx
),
1353 OFFSET_OF ( ESL_IO_MGMT
, Token
.Udp6Rx
.Packet
.RxData
),
1357 NULL
, // ConnectPoll
1358 NULL
, // ConnectStart
1359 EslUdp6SocketIsConfigured
,
1360 EslUdp6LocalAddressGet
,
1361 EslUdp6LocalAddressSet
,
1366 EslUdp6PortAllocate
,
1368 NULL
, // PortCloseOp
1371 EslUdp6RemoteAddressGet
,
1372 EslUdp6RemoteAddressSet
,
1377 NULL
, // TxOobComplete
1378 (PFN_API_VERIFY_LOCAL_IP_ADDRESS
)EslUdp6VerifyLocalIpAddress