2 Implement IP4 pesudo 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 whethter the ARP
13 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
15 EFI_MAC_ADDRESS mZeroMacAddress
;
18 Callback funtion 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
;
494 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
496 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
500 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
501 InitializeListHead (&Interface
->Link
);
502 Interface
->RefCnt
= 1;
504 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
505 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
506 Interface
->Configured
= FALSE
;
508 Interface
->Controller
= Controller
;
509 Interface
->Image
= ImageHandle
;
510 Interface
->Mnp
= Mnp
;
511 Interface
->Arp
= NULL
;
512 Interface
->ArpHandle
= NULL
;
514 InitializeListHead (&Interface
->ArpQues
);
515 InitializeListHead (&Interface
->SentFrames
);
517 Interface
->RecvRequest
= NULL
;
520 // Get the interface's Mac address and broadcast mac address from SNP
522 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
523 FreePool (Interface
);
527 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
528 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
529 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
531 InitializeListHead (&Interface
->IpInstances
);
532 Interface
->PromiscRecv
= FALSE
;
539 Set the interface's address, create and configure
540 the ARP child if necessary.
542 @param Interface The interface to set the address.
543 @param IpAddr The interface's IP address.
544 @param SubnetMask The interface's netmask.
546 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
547 and a ARP is created for it.
548 @retval Others Failed to set the interface's address.
553 IN OUT IP4_INTERFACE
*Interface
,
555 IN IP4_ADDR SubnetMask
558 EFI_ARP_CONFIG_DATA ArpConfig
;
561 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
564 // Set the ip/netmask, then compute the subnet broadcast
565 // and network broadcast for easy access. When computing
566 // nework broadcast, the subnet mask is most like longer
567 // than the default netmask (not subneted) as defined in
568 // RFC793. If that isn't the case, we are aggregating the
569 // networks, use the subnet's mask instead.
571 Interface
->Ip
= IpAddr
;
572 Interface
->SubnetMask
= SubnetMask
;
573 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
574 Interface
->NetBrdcast
= (IpAddr
| ~SubnetMask
);
577 // Do clean up for Arp child
579 if (Interface
->ArpHandle
!= NULL
) {
580 if (Interface
->Arp
!= NULL
) {
582 Interface
->ArpHandle
,
583 &gEfiArpProtocolGuid
,
585 Interface
->Controller
588 Interface
->Arp
= NULL
;
591 NetLibDestroyServiceChild (
592 Interface
->Controller
,
594 &gEfiArpServiceBindingProtocolGuid
,
595 &Interface
->ArpHandle
598 Interface
->ArpHandle
= NULL
;
602 // If the address is NOT all zero, create then configure an ARP child.
603 // Pay attention: DHCP configures its station address as 0.0.0.0/0
605 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
606 Status
= NetLibCreateServiceChild (
607 Interface
->Controller
,
609 &gEfiArpServiceBindingProtocolGuid
,
610 &Interface
->ArpHandle
613 if (EFI_ERROR (Status
)) {
617 Status
= gBS
->OpenProtocol (
618 Interface
->ArpHandle
,
619 &gEfiArpProtocolGuid
,
620 (VOID
**) &Interface
->Arp
,
622 Interface
->Controller
,
623 EFI_OPEN_PROTOCOL_BY_DRIVER
626 if (EFI_ERROR (Status
)) {
630 IpAddr
= HTONL (IpAddr
);
631 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
632 ArpConfig
.SwAddressLength
= 4;
633 ArpConfig
.StationAddress
= &IpAddr
;
634 ArpConfig
.EntryTimeOut
= 0;
635 ArpConfig
.RetryCount
= 0;
636 ArpConfig
.RetryTimeOut
= 0;
638 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
640 if (EFI_ERROR (Status
)) {
642 Interface
->ArpHandle
,
643 &gEfiArpProtocolGuid
,
645 Interface
->Controller
652 Interface
->Configured
= TRUE
;
656 NetLibDestroyServiceChild (
657 Interface
->Controller
,
659 &gEfiArpServiceBindingProtocolGuid
,
660 &Interface
->ArpHandle
668 Filter function to cancel all the frame related to an IP instance.
670 @param[in] Frame The transmit request to test whether to cancel
671 @param[in] Context The context which is the Ip instance that issued
674 @retval TRUE The frame belongs to this instance and is to be
676 @retval FALSE The frame doesn't belong to this instance.
680 Ip4CancelInstanceFrame (
681 IN IP4_LINK_TX_TOKEN
*Frame
,
685 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
695 If there is a pending receive request, cancel it. Don't call
696 the receive request's callback because this function can be only
697 called if the instance or driver is tearing itself down. It
698 doesn't make sense to call it back. But it is necessary to call
699 the transmit token's callback to give it a chance to free the
700 packet and update the upper layer's transmit request status, say
703 @param[in] Interface The interface used by the IpInstance
708 IN IP4_INTERFACE
*Interface
712 IP4_LINK_RX_TOKEN
*Token
;
714 if ((Token
= Interface
->RecvRequest
) != NULL
) {
715 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
717 Interface
->RecvRequest
= NULL
;
718 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
720 gBS
->RestoreTPL (OldTpl
);
726 Free the interface used by IpInstance. All the IP instance with
727 the same Ip/Netmask pair share the same interface. It is reference
728 counted. All the frames haven't been sent will be cancelled.
729 Because the IpInstance is optional, the caller must remove
730 IpInstance from the interface's instance list itself.
732 @param[in] Interface The interface used by the IpInstance.
733 @param[in] IpInstance The Ip instance that free the interface. NULL if
734 the Ip driver is releasing the default interface.
736 @retval EFI_SUCCESS The interface use IpInstance is freed.
741 IN IP4_INTERFACE
*Interface
,
742 IN IP4_PROTOCOL
*IpInstance OPTIONAL
745 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
746 ASSERT (Interface
->RefCnt
> 0);
749 // Remove all the pending transmit token related to this IP instance.
751 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
753 if (--Interface
->RefCnt
> 0) {
758 // Destroy the interface if this is the last IP instance that
759 // has the address. Remove all the system transmitted packets
760 // from this interface, cancel the receive request if there is
761 // one, and destroy the ARP requests.
763 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
764 Ip4CancelReceive (Interface
);
766 ASSERT (IsListEmpty (&Interface
->IpInstances
));
767 ASSERT (IsListEmpty (&Interface
->ArpQues
));
768 ASSERT (IsListEmpty (&Interface
->SentFrames
));
770 if (Interface
->Arp
!= NULL
) {
772 Interface
->ArpHandle
,
773 &gEfiArpProtocolGuid
,
775 Interface
->Controller
778 NetLibDestroyServiceChild (
779 Interface
->Controller
,
781 &gEfiArpServiceBindingProtocolGuid
,
786 RemoveEntryList (&Interface
->Link
);
787 FreePool (Interface
);
793 This function tries to send all the queued frames in ArpQue to the default gateway if
794 the ARP resolve for direct destination address is failed when using /32 subnet mask.
796 @param[in] ArpQue The ARP queue of a failed request.
798 @retval EFI_SUCCESS All the queued frames have been send to the default route.
799 @retval Others Failed to send the queued frames.
803 Ip4SendFrameToDefaultRoute (
804 IN IP4_ARP_QUE
*ArpQue
809 IP4_ROUTE_CACHE_ENTRY
*RtCacheEntry
;
810 IP4_LINK_TX_TOKEN
*Token
;
813 IP4_ROUTE_ENTRY
*DefaultRoute
;
816 // ARP resolve failed when using /32 subnet mask.
818 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
819 RemoveEntryList (Entry
);
820 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
821 ASSERT (Token
->Interface
->SubnetMask
== IP4_ALLONE_ADDRESS
);
823 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
826 if (Token
->IpInstance
!= NULL
) {
827 RtCacheEntry
= Ip4FindRouteCache (Token
->IpInstance
->RouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
829 if (RtCacheEntry
== NULL
) {
830 RtCacheEntry
= Ip4FindRouteCache (Token
->IpSb
->DefaultRouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
832 if (RtCacheEntry
== NULL
) {
833 Status
= EFI_NO_MAPPING
;
836 DefaultRoute
= (IP4_ROUTE_ENTRY
*)RtCacheEntry
->Tag
;
837 if (DefaultRoute
== NULL
) {
838 Status
= EFI_NO_MAPPING
;
842 // Try to send the frame to the default route.
844 Gateway
= DefaultRoute
->NextHop
;
845 if (ArpQue
->Ip
== Gateway
) {
847 // ARP resolve for the default route is failed, return error to caller.
849 Status
= EFI_NO_MAPPING
;
852 RtCacheEntry
->NextHop
= Gateway
;
853 Status
= Ip4SendFrame (Token
->Interface
,Token
->IpInstance
,Token
->Packet
,Gateway
,Token
->CallBack
,Token
->Context
,Token
->IpSb
);
854 if (EFI_ERROR (Status
)) {
855 Status
= EFI_NO_MAPPING
;
858 Ip4FreeRouteCacheEntry (RtCacheEntry
);
864 if (RtCacheEntry
!= NULL
) {
865 Ip4FreeRouteCacheEntry (RtCacheEntry
);
867 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
868 Ip4FreeLinkTxToken (Token
);
874 Callback function when ARP request are finished. It will cancel
875 all the queued frame if the ARP requests failed. Or transmit them
876 if the request succeed.
878 @param[in] Context The context of the callback, a point to the ARP
884 Ip4OnArpResolvedDpc (
891 IP4_INTERFACE
*Interface
;
892 IP4_LINK_TX_TOKEN
*Token
;
896 ArpQue
= (IP4_ARP_QUE
*) Context
;
897 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
899 RemoveEntryList (&ArpQue
->Link
);
902 // ARP resolve failed for some reason.
904 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
905 if (ArpQue
->Interface
->SubnetMask
!= IP4_ALLONE_ADDRESS
) {
907 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
910 IoStatus
= EFI_NO_MAPPING
;
913 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
916 IoStatus
= Ip4SendFrameToDefaultRoute (ArpQue
);
922 // ARP resolve succeeded, Transmit all the frame. Release the ARP
923 // queue. It isn't necessary for us to cache the ARP binding because
924 // we always check the ARP cache first before transmit.
926 IoStatus
= EFI_SUCCESS
;
927 Interface
= ArpQue
->Interface
;
929 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
930 RemoveEntryList (Entry
);
932 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
933 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
936 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
937 // may be called before Mnp->Transmit returns which will remove this tx
938 // token from the SentFrames list. Remove it from the list if the returned
939 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
940 // FrameSentDpc won't be queued.
942 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
944 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
945 if (EFI_ERROR (Status
)) {
946 RemoveEntryList (&Token
->Link
);
947 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
949 Ip4FreeLinkTxToken (Token
);
955 Ip4FreeArpQue (ArpQue
, IoStatus
);
959 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
961 @param Event The Arp request event.
962 @param Context The context of the callback, a point to the ARP
974 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
976 QueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
982 Callback funtion when frame transmission is finished. It will
983 call the frame owner's callback function to tell it the result.
985 @param[in] Context Context which is point to the token.
994 IP4_LINK_TX_TOKEN
*Token
;
996 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
997 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
999 RemoveEntryList (&Token
->Link
);
1004 Token
->MnpToken
.Status
,
1009 Ip4FreeLinkTxToken (Token
);
1013 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1015 @param[in] Event The transmit token's event.
1016 @param[in] Context Context which is point to the token.
1027 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1029 QueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
1035 Send a frame from the interface. If the next hop is broadcast or
1036 multicast address, it is transmitted immediately. If the next hop
1037 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1038 If some error happened, the CallBack won't be called. So, the caller
1039 must test the return value, and take action when there is an error.
1041 @param[in] Interface The interface to send the frame from
1042 @param[in] IpInstance The IP child that request the transmission. NULL
1043 if it is the IP4 driver itself.
1044 @param[in] Packet The packet to transmit.
1045 @param[in] NextHop The immediate destination to transmit the packet
1047 @param[in] CallBack Function to call back when transmit finished.
1048 @param[in] Context Opaque parameter to the call back.
1049 @param[in] IpSb The pointer to the IP4 service binding instance.
1051 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1052 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1053 @retval EFI_SUCCESS The packet is successfully transmitted.
1054 @retval other Other error occurs.
1059 IN IP4_INTERFACE
*Interface
,
1060 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1062 IN IP4_ADDR NextHop
,
1063 IN IP4_FRAME_CALLBACK CallBack
,
1065 IN IP4_SERVICE
*IpSb
1068 IP4_LINK_TX_TOKEN
*Token
;
1070 IP4_ARP_QUE
*ArpQue
;
1071 EFI_ARP_PROTOCOL
*Arp
;
1074 ASSERT (Interface
->Configured
);
1076 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
, IpSb
);
1078 if (Token
== NULL
) {
1079 return EFI_OUT_OF_RESOURCES
;
1083 // Get the destination MAC address for multicast and broadcasts.
1084 // Don't depend on ARP to solve the address since there maybe no
1085 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1086 // all the broadcasts.
1088 if (NextHop
== IP4_ALLONE_ADDRESS
) {
1089 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
1092 } else if (IP4_IS_MULTICAST (NextHop
)) {
1094 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
1096 if (EFI_ERROR (Status
)) {
1104 // Can only send out multicast/broadcast if the IP address is zero
1106 if ((Arp
= Interface
->Arp
) == NULL
) {
1107 Status
= EFI_NO_MAPPING
;
1112 // First check whether this binding is in the ARP cache.
1114 NextHop
= HTONL (NextHop
);
1115 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1117 if (Status
== EFI_SUCCESS
) {
1120 } else if (Status
!= EFI_NOT_READY
) {
1125 // Have to do asynchronous ARP resolution. First check
1126 // whether there is already a pending request.
1130 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1131 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1133 if (ArpQue
->Ip
== NextHop
) {
1139 // Found a pending ARP request, enqueue the frame then return
1141 if (Entry
!= &Interface
->ArpQues
) {
1142 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1147 // First frame to NextHop, issue an asynchronous ARP requests
1149 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1151 if (ArpQue
== NULL
) {
1152 Status
= EFI_OUT_OF_RESOURCES
;
1156 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1158 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1159 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1163 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1164 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1169 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1170 // Remove it if the returned status is not EFI_SUCCESS.
1172 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1173 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1174 if (EFI_ERROR (Status
)) {
1175 RemoveEntryList (&Token
->Link
);
1182 Ip4FreeLinkTxToken (Token
);
1188 Call back function when the received packet is freed.
1189 Check Ip4OnFrameReceived for information.
1191 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1200 IP4_LINK_RX_TOKEN
*Frame
;
1202 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1203 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1205 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1206 Ip4FreeFrameRxToken (Frame
);
1211 Received a frame from MNP, wrap it in net buffer then deliver
1212 it to IP's input function. The ownship of the packet also
1213 transferred to IP. When Ip is finished with this packet, it
1214 will call NetbufFree to release the packet, NetbufFree will
1215 again call the Ip4RecycleFrame to signal MNP's event and free
1218 @param Context Context for the callback.
1223 Ip4OnFrameReceivedDpc (
1227 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1228 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1229 IP4_LINK_RX_TOKEN
*Token
;
1230 NET_FRAGMENT Netfrag
;
1234 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1235 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1238 // First clear the interface's receive request in case the
1239 // caller wants to call Ip4ReceiveFrame in the callback.
1241 Token
->Interface
->RecvRequest
= NULL
;
1243 MnpToken
= &Token
->MnpToken
;
1244 MnpRxData
= MnpToken
->Packet
.RxData
;
1246 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1247 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1248 Ip4FreeFrameRxToken (Token
);
1254 // Wrap the frame in a net buffer then deliever it to IP input.
1255 // IP will reassemble the packet, and deliver it to upper layer
1257 Netfrag
.Len
= MnpRxData
->DataLength
;
1258 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1260 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1262 if (Packet
== NULL
) {
1263 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1265 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1266 Ip4FreeFrameRxToken (Token
);
1271 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1272 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1273 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1275 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1279 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1281 @param Event The receive event delivered to MNP for receive.
1282 @param Context Context for the callback.
1287 Ip4OnFrameReceived (
1293 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1295 QueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1300 Request to receive the packet from the interface.
1302 @param[in] Interface The interface to receive the frames from.
1303 @param[in] IpInstance The instance that requests the receive. NULL for
1305 @param[in] CallBack Function to call when receive finished.
1306 @param[in] Context Opaque parameter to the callback.
1308 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1309 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1310 @retval EFI_SUCCESS The recieve request has been started.
1311 @retval other Other error occurs.
1316 IN IP4_INTERFACE
*Interface
,
1317 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1318 IN IP4_FRAME_CALLBACK CallBack
,
1322 IP4_LINK_RX_TOKEN
*Token
;
1325 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1327 if (Interface
->RecvRequest
!= NULL
) {
1328 return EFI_ALREADY_STARTED
;
1331 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1333 if (Token
== NULL
) {
1334 return EFI_OUT_OF_RESOURCES
;
1337 Interface
->RecvRequest
= Token
;
1338 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1339 if (EFI_ERROR (Status
)) {
1340 Interface
->RecvRequest
= NULL
;
1341 Ip4FreeFrameRxToken (Token
);