2 Implement IP4 pseudo interface.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 // Mac address with all zero, used to determine whether the ARP
13 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
15 EFI_MAC_ADDRESS mZeroMacAddress
;
18 Callback function when frame transmission is finished. It will
19 call the frame owner's callback function to tell it the result.
21 @param[in] Context Context which is point to the token.
31 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
33 @param[in] Event The transmit token's event.
34 @param[in] Context Context which is point to the token.
45 Callback function when ARP request are finished. It will cancelled
46 all the queued frame if the ARP requests failed. Or transmit them
47 if the request succeed.
49 @param[in] Context The context of the callback, a point to the ARP
60 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
62 @param Event The Arp request event.
63 @param Context The context of the callback, a point to the ARP
75 Received a frame from MNP, wrap it in net buffer then deliver
76 it to IP's input function. The ownship of the packet also
77 transferred to IP. When Ip is finished with this packet, it
78 will call NetbufFree to release the packet, NetbufFree will
79 again call the Ip4RecycleFrame to signal MNP's event and free
82 @param Context Context for the callback.
87 Ip4OnFrameReceivedDpc (
92 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
94 @param Event The receive event delivered to MNP for receive.
95 @param Context Context for the callback.
106 Remove all the frames on the ARP queue that pass the FrameToCancel,
107 that is, either FrameToCancel is NULL or it returns true for the frame.
109 @param[in] ArpQue ARP frame to remove the frames from.
110 @param[in] IoStatus The status returned to the cancelled frames'
112 @param[in] FrameToCancel Function to select which frame to cancel.
113 @param[in] Context Opaque parameter to the FrameToCancel.
118 IN IP4_ARP_QUE
*ArpQue
,
119 IN EFI_STATUS IoStatus
,
120 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
126 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
128 @param[in] Interface The interface to send out to.
129 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
130 the packet is sent by the IP4 driver itself.
131 @param[in] Packet The packet to transmit
132 @param[in] CallBack Call back function to execute if transmission
134 @param[in] Context Opaque parameter to the call back.
135 @param[in] IpSb The pointer to the IP4 service binding instance.
137 @retval Token The wrapped token if succeed
138 @retval NULL The wrapped token if NULL
143 IN IP4_INTERFACE
*Interface
,
144 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
146 IN IP4_FRAME_CALLBACK CallBack
,
151 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
152 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
153 IP4_LINK_TX_TOKEN
*Token
;
157 Token
= AllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
158 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
164 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
165 InitializeListHead (&Token
->Link
);
167 Token
->Interface
= Interface
;
168 Token
->IpInstance
= IpInstance
;
170 Token
->CallBack
= CallBack
;
171 Token
->Packet
= Packet
;
172 Token
->Context
= Context
;
173 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
174 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
176 MnpToken
= &(Token
->MnpToken
);
177 MnpToken
->Status
= EFI_NOT_READY
;
179 Status
= gBS
->CreateEvent (
187 if (EFI_ERROR (Status
)) {
192 MnpTxData
= &Token
->MnpTxData
;
193 MnpToken
->Packet
.TxData
= MnpTxData
;
195 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
196 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
197 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
198 MnpTxData
->DataLength
= Packet
->TotalSize
;
199 MnpTxData
->HeaderLength
= 0;
201 Count
= Packet
->BlockOpNum
;
203 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
204 MnpTxData
->FragmentCount
= (UINT16
)Count
;
211 Free the link layer transmit token. It will close the event
212 then free the memory used.
214 @param[in] Token Token to free
219 IN IP4_LINK_TX_TOKEN
*Token
222 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
224 gBS
->CloseEvent (Token
->MnpToken
.Event
);
230 Create an IP_ARP_QUE structure to request ARP service.
232 @param[in] Interface The interface to send ARP from.
233 @param[in] DestIp The destination IP (host byte order) to request MAC
236 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
241 IN IP4_INTERFACE
*Interface
,
248 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
250 if (ArpQue
== NULL
) {
254 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
255 InitializeListHead (&ArpQue
->Link
);
257 InitializeListHead (&ArpQue
->Frames
);
258 ArpQue
->Interface
= Interface
;
260 Status
= gBS
->CreateEvent (
268 if (EFI_ERROR (Status
)) {
274 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
281 Remove all the transmit requests queued on the ARP queue, then free it.
283 @param[in] ArpQue Arp queue to free
284 @param[in] IoStatus The transmit status returned to transmit requests'
290 IN IP4_ARP_QUE
*ArpQue
,
291 IN EFI_STATUS IoStatus
294 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
297 // Remove all the frame waiting the ARP response
299 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
301 gBS
->CloseEvent (ArpQue
->OnResolved
);
307 Create a link layer receive token to wrap the receive request
309 @param[in] Interface The interface to receive from
310 @param[in] IpInstance The instance that request the receive (NULL for IP4
312 @param[in] CallBack Call back function to execute when finished.
313 @param[in] Context Opaque parameters to the callback
315 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
319 Ip4CreateLinkRxToken (
320 IN IP4_INTERFACE
*Interface
,
321 IN IP4_PROTOCOL
*IpInstance
,
322 IN IP4_FRAME_CALLBACK CallBack
,
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
327 IP4_LINK_RX_TOKEN
*Token
;
330 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
335 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
336 Token
->Interface
= Interface
;
337 Token
->IpInstance
= IpInstance
;
338 Token
->CallBack
= CallBack
;
339 Token
->Context
= Context
;
341 MnpToken
= &Token
->MnpToken
;
342 MnpToken
->Status
= EFI_NOT_READY
;
344 Status
= gBS
->CreateEvent (
352 if (EFI_ERROR (Status
)) {
357 MnpToken
->Packet
.RxData
= NULL
;
363 Free the link layer request token. It will close the event
364 then free the memory used.
366 @param[in] Token Request token to free.
370 Ip4FreeFrameRxToken (
371 IN IP4_LINK_RX_TOKEN
*Token
375 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
377 gBS
->CloseEvent (Token
->MnpToken
.Event
);
383 Remove all the frames on the ARP queue that pass the FrameToCancel,
384 that is, either FrameToCancel is NULL or it returns true for the frame.
386 @param[in] ArpQue ARP frame to remove the frames from.
387 @param[in] IoStatus The status returned to the cancelled frames'
389 @param[in] FrameToCancel Function to select which frame to cancel.
390 @param[in] Context Opaque parameter to the FrameToCancel.
395 IN IP4_ARP_QUE
*ArpQue
,
396 IN EFI_STATUS IoStatus
,
397 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
403 IP4_LINK_TX_TOKEN
*Token
;
405 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
406 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
408 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
409 RemoveEntryList (Entry
);
411 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
412 Ip4FreeLinkTxToken (Token
);
419 Remove all the frames on the interface that pass the FrameToCancel,
420 either queued on ARP queues or that have already been delivered to
421 MNP and not yet recycled.
423 @param[in] Interface Interface to remove the frames from.
424 @param[in] IoStatus The transmit status returned to the frames'
426 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
428 @param[in] Context Opaque parameters passed to FrameToCancel.
433 IN IP4_INTERFACE
*Interface
,
434 IN EFI_STATUS IoStatus
,
435 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
442 IP4_LINK_TX_TOKEN
*Token
;
445 // Cancel all the pending frames on ARP requests
447 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
448 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
450 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
452 if (IsListEmpty (&ArpQue
->Frames
)) {
453 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
458 // Cancel all the frames that have been delivered to MNP
459 // but not yet recycled.
461 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
462 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
464 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
465 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
472 Create an IP4_INTERFACE. Delay the creation of ARP instance until
473 the interface is configured.
475 @param[in] Mnp The shared MNP child of this IP4 service binding
477 @param[in] Controller The controller this IP4 service binding instance
478 is installed. Most like the UNDI handle.
479 @param[in] ImageHandle This driver's image handle.
481 @return Point to the created IP4_INTERFACE, otherwise NULL.
486 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
487 IN EFI_HANDLE Controller
,
488 IN EFI_HANDLE ImageHandle
491 IP4_INTERFACE
*Interface
;
492 EFI_SIMPLE_NETWORK_MODE SnpMode
;
498 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
500 if (Interface
== NULL
) {
504 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
505 InitializeListHead (&Interface
->Link
);
506 Interface
->RefCnt
= 1;
508 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
509 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
510 Interface
->Configured
= FALSE
;
512 Interface
->Controller
= Controller
;
513 Interface
->Image
= ImageHandle
;
514 Interface
->Mnp
= Mnp
;
515 Interface
->Arp
= NULL
;
516 Interface
->ArpHandle
= NULL
;
518 InitializeListHead (&Interface
->ArpQues
);
519 InitializeListHead (&Interface
->SentFrames
);
521 Interface
->RecvRequest
= NULL
;
524 // Get the interface's Mac address and broadcast mac address from SNP
526 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
527 FreePool (Interface
);
531 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
532 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
533 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
535 InitializeListHead (&Interface
->IpInstances
);
536 Interface
->PromiscRecv
= FALSE
;
543 Set the interface's address, create and configure
544 the ARP child if necessary.
546 @param Interface The interface to set the address.
547 @param IpAddr The interface's IP address.
548 @param SubnetMask The interface's netmask.
550 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
551 and a ARP is created for it.
552 @retval Others Failed to set the interface's address.
557 IN OUT IP4_INTERFACE
*Interface
,
559 IN IP4_ADDR SubnetMask
562 EFI_ARP_CONFIG_DATA ArpConfig
;
565 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
568 // Set the ip/netmask, then compute the subnet broadcast
569 // and network broadcast for easy access. When computing
570 // network broadcast, the subnet mask is most like longer
571 // than the default netmask (not subneted) as defined in
572 // RFC793. If that isn't the case, we are aggregating the
573 // networks, use the subnet's mask instead.
575 Interface
->Ip
= IpAddr
;
576 Interface
->SubnetMask
= SubnetMask
;
577 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
578 Interface
->NetBrdcast
= (IpAddr
| ~SubnetMask
);
581 // Do clean up for Arp child
583 if (Interface
->ArpHandle
!= NULL
) {
584 if (Interface
->Arp
!= NULL
) {
586 Interface
->ArpHandle
,
587 &gEfiArpProtocolGuid
,
589 Interface
->Controller
592 Interface
->Arp
= NULL
;
595 NetLibDestroyServiceChild (
596 Interface
->Controller
,
598 &gEfiArpServiceBindingProtocolGuid
,
602 Interface
->ArpHandle
= NULL
;
606 // If the address is NOT all zero, create then configure an ARP child.
607 // Pay attention: DHCP configures its station address as 0.0.0.0/0
609 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
610 Status
= NetLibCreateServiceChild (
611 Interface
->Controller
,
613 &gEfiArpServiceBindingProtocolGuid
,
614 &Interface
->ArpHandle
617 if (EFI_ERROR (Status
)) {
621 Status
= gBS
->OpenProtocol (
622 Interface
->ArpHandle
,
623 &gEfiArpProtocolGuid
,
624 (VOID
**) &Interface
->Arp
,
626 Interface
->Controller
,
627 EFI_OPEN_PROTOCOL_BY_DRIVER
630 if (EFI_ERROR (Status
)) {
634 IpAddr
= HTONL (IpAddr
);
635 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
636 ArpConfig
.SwAddressLength
= 4;
637 ArpConfig
.StationAddress
= &IpAddr
;
638 ArpConfig
.EntryTimeOut
= 0;
639 ArpConfig
.RetryCount
= 0;
640 ArpConfig
.RetryTimeOut
= 0;
642 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
644 if (EFI_ERROR (Status
)) {
646 Interface
->ArpHandle
,
647 &gEfiArpProtocolGuid
,
649 Interface
->Controller
656 Interface
->Configured
= TRUE
;
660 NetLibDestroyServiceChild (
661 Interface
->Controller
,
663 &gEfiArpServiceBindingProtocolGuid
,
672 Filter function to cancel all the frame related to an IP instance.
674 @param[in] Frame The transmit request to test whether to cancel
675 @param[in] Context The context which is the Ip instance that issued
678 @retval TRUE The frame belongs to this instance and is to be
680 @retval FALSE The frame doesn't belong to this instance.
684 Ip4CancelInstanceFrame (
685 IN IP4_LINK_TX_TOKEN
*Frame
,
689 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
699 If there is a pending receive request, cancel it. Don't call
700 the receive request's callback because this function can be only
701 called if the instance or driver is tearing itself down. It
702 doesn't make sense to call it back. But it is necessary to call
703 the transmit token's callback to give it a chance to free the
704 packet and update the upper layer's transmit request status, say
707 @param[in] Interface The interface used by the IpInstance
712 IN IP4_INTERFACE
*Interface
716 IP4_LINK_RX_TOKEN
*Token
;
718 if ((Token
= Interface
->RecvRequest
) != NULL
) {
719 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
721 Interface
->RecvRequest
= NULL
;
722 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
724 gBS
->RestoreTPL (OldTpl
);
730 Free the interface used by IpInstance. All the IP instance with
731 the same Ip/Netmask pair share the same interface. It is reference
732 counted. All the frames haven't been sent will be cancelled.
733 Because the IpInstance is optional, the caller must remove
734 IpInstance from the interface's instance list itself.
736 @param[in] Interface The interface used by the IpInstance.
737 @param[in] IpInstance The Ip instance that free the interface. NULL if
738 the Ip driver is releasing the default interface.
740 @retval EFI_SUCCESS The interface use IpInstance is freed.
745 IN IP4_INTERFACE
*Interface
,
746 IN IP4_PROTOCOL
*IpInstance OPTIONAL
749 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
750 ASSERT (Interface
->RefCnt
> 0);
753 // Remove all the pending transmit token related to this IP instance.
755 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
757 if (--Interface
->RefCnt
> 0) {
762 // Destroy the interface if this is the last IP instance that
763 // has the address. Remove all the system transmitted packets
764 // from this interface, cancel the receive request if there is
765 // one, and destroy the ARP requests.
767 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
768 Ip4CancelReceive (Interface
);
770 ASSERT (IsListEmpty (&Interface
->IpInstances
));
771 ASSERT (IsListEmpty (&Interface
->ArpQues
));
772 ASSERT (IsListEmpty (&Interface
->SentFrames
));
774 if (Interface
->Arp
!= NULL
) {
776 Interface
->ArpHandle
,
777 &gEfiArpProtocolGuid
,
779 Interface
->Controller
782 NetLibDestroyServiceChild (
783 Interface
->Controller
,
785 &gEfiArpServiceBindingProtocolGuid
,
790 RemoveEntryList (&Interface
->Link
);
791 FreePool (Interface
);
797 This function tries to send all the queued frames in ArpQue to the default gateway if
798 the ARP resolve for direct destination address is failed when using /32 subnet mask.
800 @param[in] ArpQue The ARP queue of a failed request.
802 @retval EFI_SUCCESS All the queued frames have been send to the default route.
803 @retval Others Failed to send the queued frames.
807 Ip4SendFrameToDefaultRoute (
808 IN IP4_ARP_QUE
*ArpQue
813 IP4_ROUTE_CACHE_ENTRY
*RtCacheEntry
;
814 IP4_LINK_TX_TOKEN
*Token
;
817 IP4_ROUTE_ENTRY
*DefaultRoute
;
820 // ARP resolve failed when using /32 subnet mask.
822 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
823 RemoveEntryList (Entry
);
824 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
825 ASSERT (Token
->Interface
->SubnetMask
== IP4_ALLONE_ADDRESS
);
827 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
830 if (Token
->IpInstance
!= NULL
) {
831 RtCacheEntry
= Ip4FindRouteCache (Token
->IpInstance
->RouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
833 if (RtCacheEntry
== NULL
) {
834 RtCacheEntry
= Ip4FindRouteCache (Token
->IpSb
->DefaultRouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
836 if (RtCacheEntry
== NULL
) {
837 Status
= EFI_NO_MAPPING
;
840 DefaultRoute
= (IP4_ROUTE_ENTRY
*)RtCacheEntry
->Tag
;
841 if (DefaultRoute
== NULL
) {
842 Status
= EFI_NO_MAPPING
;
846 // Try to send the frame to the default route.
848 Gateway
= DefaultRoute
->NextHop
;
849 if (ArpQue
->Ip
== Gateway
) {
851 // ARP resolve for the default route is failed, return error to caller.
853 Status
= EFI_NO_MAPPING
;
856 RtCacheEntry
->NextHop
= Gateway
;
857 Status
= Ip4SendFrame (Token
->Interface
,Token
->IpInstance
,Token
->Packet
,Gateway
,Token
->CallBack
,Token
->Context
,Token
->IpSb
);
858 if (EFI_ERROR (Status
)) {
859 Status
= EFI_NO_MAPPING
;
862 Ip4FreeRouteCacheEntry (RtCacheEntry
);
868 if (RtCacheEntry
!= NULL
) {
869 Ip4FreeRouteCacheEntry (RtCacheEntry
);
871 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
872 Ip4FreeLinkTxToken (Token
);
878 Callback function when ARP request are finished. It will cancel
879 all the queued frame if the ARP requests failed. Or transmit them
880 if the request succeed.
882 @param[in] Context The context of the callback, a point to the ARP
888 Ip4OnArpResolvedDpc (
895 IP4_INTERFACE
*Interface
;
896 IP4_LINK_TX_TOKEN
*Token
;
900 ArpQue
= (IP4_ARP_QUE
*) Context
;
901 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
903 RemoveEntryList (&ArpQue
->Link
);
906 // ARP resolve failed for some reason.
908 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
909 if (ArpQue
->Interface
->SubnetMask
!= IP4_ALLONE_ADDRESS
) {
911 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
914 IoStatus
= EFI_NO_MAPPING
;
917 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
920 IoStatus
= Ip4SendFrameToDefaultRoute (ArpQue
);
926 // ARP resolve succeeded, Transmit all the frame. Release the ARP
927 // queue. It isn't necessary for us to cache the ARP binding because
928 // we always check the ARP cache first before transmit.
930 IoStatus
= EFI_SUCCESS
;
931 Interface
= ArpQue
->Interface
;
933 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
934 RemoveEntryList (Entry
);
936 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
937 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
940 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
941 // may be called before Mnp->Transmit returns which will remove this tx
942 // token from the SentFrames list. Remove it from the list if the returned
943 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
944 // FrameSentDpc won't be queued.
946 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
948 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
949 if (EFI_ERROR (Status
)) {
950 RemoveEntryList (&Token
->Link
);
951 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
953 Ip4FreeLinkTxToken (Token
);
959 Ip4FreeArpQue (ArpQue
, IoStatus
);
963 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
965 @param Event The Arp request event.
966 @param Context The context of the callback, a point to the ARP
978 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
980 QueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
986 Callback function when frame transmission is finished. It will
987 call the frame owner's callback function to tell it the result.
989 @param[in] Context Context which is point to the token.
998 IP4_LINK_TX_TOKEN
*Token
;
1000 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
1001 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
1003 RemoveEntryList (&Token
->Link
);
1008 Token
->MnpToken
.Status
,
1013 Ip4FreeLinkTxToken (Token
);
1017 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1019 @param[in] Event The transmit token's event.
1020 @param[in] Context Context which is point to the token.
1031 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1033 QueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
1039 Send a frame from the interface. If the next hop is broadcast or
1040 multicast address, it is transmitted immediately. If the next hop
1041 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1042 If some error happened, the CallBack won't be called. So, the caller
1043 must test the return value, and take action when there is an error.
1045 @param[in] Interface The interface to send the frame from
1046 @param[in] IpInstance The IP child that request the transmission. NULL
1047 if it is the IP4 driver itself.
1048 @param[in] Packet The packet to transmit.
1049 @param[in] NextHop The immediate destination to transmit the packet
1051 @param[in] CallBack Function to call back when transmit finished.
1052 @param[in] Context Opaque parameter to the call back.
1053 @param[in] IpSb The pointer to the IP4 service binding instance.
1055 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1056 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1057 @retval EFI_SUCCESS The packet is successfully transmitted.
1058 @retval other Other error occurs.
1063 IN IP4_INTERFACE
*Interface
,
1064 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1066 IN IP4_ADDR NextHop
,
1067 IN IP4_FRAME_CALLBACK CallBack
,
1069 IN IP4_SERVICE
*IpSb
1072 IP4_LINK_TX_TOKEN
*Token
;
1074 IP4_ARP_QUE
*ArpQue
;
1075 EFI_ARP_PROTOCOL
*Arp
;
1078 ASSERT (Interface
->Configured
);
1080 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
, IpSb
);
1082 if (Token
== NULL
) {
1083 return EFI_OUT_OF_RESOURCES
;
1087 // Get the destination MAC address for multicast and broadcasts.
1088 // Don't depend on ARP to solve the address since there maybe no
1089 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1090 // all the broadcasts.
1092 if (NextHop
== IP4_ALLONE_ADDRESS
) {
1093 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
1096 } else if (IP4_IS_MULTICAST (NextHop
)) {
1098 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
1100 if (EFI_ERROR (Status
)) {
1108 // Can only send out multicast/broadcast if the IP address is zero
1110 if ((Arp
= Interface
->Arp
) == NULL
) {
1111 Status
= EFI_NO_MAPPING
;
1116 // First check whether this binding is in the ARP cache.
1118 NextHop
= HTONL (NextHop
);
1119 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1121 if (Status
== EFI_SUCCESS
) {
1124 } else if (Status
!= EFI_NOT_READY
) {
1129 // Have to do asynchronous ARP resolution. First check
1130 // whether there is already a pending request.
1134 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1135 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1137 if (ArpQue
->Ip
== NextHop
) {
1143 // Found a pending ARP request, enqueue the frame then return
1145 if (Entry
!= &Interface
->ArpQues
) {
1146 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1151 // First frame to NextHop, issue an asynchronous ARP requests
1153 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1155 if (ArpQue
== NULL
) {
1156 Status
= EFI_OUT_OF_RESOURCES
;
1160 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1162 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1163 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1167 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1168 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1173 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1174 // Remove it if the returned status is not EFI_SUCCESS.
1176 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1177 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1178 if (EFI_ERROR (Status
)) {
1179 RemoveEntryList (&Token
->Link
);
1186 Ip4FreeLinkTxToken (Token
);
1192 Call back function when the received packet is freed.
1193 Check Ip4OnFrameReceived for information.
1195 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1204 IP4_LINK_RX_TOKEN
*Frame
;
1206 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1207 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1209 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1210 Ip4FreeFrameRxToken (Frame
);
1215 Received a frame from MNP, wrap it in net buffer then deliver
1216 it to IP's input function. The ownship of the packet also
1217 transferred to IP. When Ip is finished with this packet, it
1218 will call NetbufFree to release the packet, NetbufFree will
1219 again call the Ip4RecycleFrame to signal MNP's event and free
1222 @param Context Context for the callback.
1227 Ip4OnFrameReceivedDpc (
1231 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1232 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1233 IP4_LINK_RX_TOKEN
*Token
;
1234 NET_FRAGMENT Netfrag
;
1238 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1239 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1242 // First clear the interface's receive request in case the
1243 // caller wants to call Ip4ReceiveFrame in the callback.
1245 Token
->Interface
->RecvRequest
= NULL
;
1247 MnpToken
= &Token
->MnpToken
;
1248 MnpRxData
= MnpToken
->Packet
.RxData
;
1250 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1251 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1252 Ip4FreeFrameRxToken (Token
);
1258 // Wrap the frame in a net buffer then deliver it to IP input.
1259 // IP will reassemble the packet, and deliver it to upper layer
1261 Netfrag
.Len
= MnpRxData
->DataLength
;
1262 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1264 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1266 if (Packet
== NULL
) {
1267 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1269 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1270 Ip4FreeFrameRxToken (Token
);
1275 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1276 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1277 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1279 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1283 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1285 @param Event The receive event delivered to MNP for receive.
1286 @param Context Context for the callback.
1291 Ip4OnFrameReceived (
1297 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1299 QueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1304 Request to receive the packet from the interface.
1306 @param[in] Interface The interface to receive the frames from.
1307 @param[in] IpInstance The instance that requests the receive. NULL for
1309 @param[in] CallBack Function to call when receive finished.
1310 @param[in] Context Opaque parameter to the callback.
1312 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1313 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1314 @retval EFI_SUCCESS The receive request has been started.
1315 @retval other Other error occurs.
1320 IN IP4_INTERFACE
*Interface
,
1321 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1322 IN IP4_FRAME_CALLBACK CallBack
,
1326 IP4_LINK_RX_TOKEN
*Token
;
1329 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1331 if (Interface
->RecvRequest
!= NULL
) {
1332 return EFI_ALREADY_STARTED
;
1335 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1337 if (Token
== NULL
) {
1338 return EFI_OUT_OF_RESOURCES
;
1341 Interface
->RecvRequest
= Token
;
1342 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1343 if (EFI_ERROR (Status
)) {
1344 Interface
->RecvRequest
= NULL
;
1345 Ip4FreeFrameRxToken (Token
);