2 Implement IP4 pesudo interface.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 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.
18 // Mac address with all zero, used to determine whethter the ARP
19 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
21 EFI_MAC_ADDRESS mZeroMacAddress
;
24 Callback funtion when frame transmission is finished. It will
25 call the frame owner's callback function to tell it the result.
27 @param[in] Context Context which is point to the token.
37 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
39 @param[in] Event The transmit token's event.
40 @param[in] Context Context which is point to the token.
51 Callback function when ARP request are finished. It will cancelled
52 all the queued frame if the ARP requests failed. Or transmit them
53 if the request succeed.
55 @param[in] Context The context of the callback, a point to the ARP
66 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
68 @param Event The Arp request event.
69 @param Context The context of the callback, a point to the ARP
81 Received a frame from MNP, wrap it in net buffer then deliver
82 it to IP's input function. The ownship of the packet also
83 transferred to IP. When Ip is finished with this packet, it
84 will call NetbufFree to release the packet, NetbufFree will
85 again call the Ip4RecycleFrame to signal MNP's event and free
88 @param Context Context for the callback.
93 Ip4OnFrameReceivedDpc (
98 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
100 @param Event The receive event delivered to MNP for receive.
101 @param Context Context for the callback.
112 Remove all the frames on the ARP queue that pass the FrameToCancel,
113 that is, either FrameToCancel is NULL or it returns true for the frame.
115 @param[in] ArpQue ARP frame to remove the frames from.
116 @param[in] IoStatus The status returned to the cancelled frames'
118 @param[in] FrameToCancel Function to select which frame to cancel.
119 @param[in] Context Opaque parameter to the FrameToCancel.
124 IN IP4_ARP_QUE
*ArpQue
,
125 IN EFI_STATUS IoStatus
,
126 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
132 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
134 @param[in] Interface The interface to send out to.
135 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
136 the packet is sent by the IP4 driver itself.
137 @param[in] Packet The packet to transmit
138 @param[in] CallBack Call back function to execute if transmission
140 @param[in] Context Opaque parameter to the call back.
141 @param[in] IpSb The pointer to the IP4 service binding instance.
143 @retval Token The wrapped token if succeed
144 @retval NULL The wrapped token if NULL
149 IN IP4_INTERFACE
*Interface
,
150 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
152 IN IP4_FRAME_CALLBACK CallBack
,
157 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
158 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
159 IP4_LINK_TX_TOKEN
*Token
;
163 Token
= AllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
164 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
170 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
171 InitializeListHead (&Token
->Link
);
173 Token
->Interface
= Interface
;
174 Token
->IpInstance
= IpInstance
;
176 Token
->CallBack
= CallBack
;
177 Token
->Packet
= Packet
;
178 Token
->Context
= Context
;
179 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
180 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
182 MnpToken
= &(Token
->MnpToken
);
183 MnpToken
->Status
= EFI_NOT_READY
;
185 Status
= gBS
->CreateEvent (
193 if (EFI_ERROR (Status
)) {
198 MnpTxData
= &Token
->MnpTxData
;
199 MnpToken
->Packet
.TxData
= MnpTxData
;
201 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
202 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
203 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
204 MnpTxData
->DataLength
= Packet
->TotalSize
;
205 MnpTxData
->HeaderLength
= 0;
207 Count
= Packet
->BlockOpNum
;
209 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
210 MnpTxData
->FragmentCount
= (UINT16
)Count
;
217 Free the link layer transmit token. It will close the event
218 then free the memory used.
220 @param[in] Token Token to free
225 IN IP4_LINK_TX_TOKEN
*Token
228 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
230 gBS
->CloseEvent (Token
->MnpToken
.Event
);
236 Create an IP_ARP_QUE structure to request ARP service.
238 @param[in] Interface The interface to send ARP from.
239 @param[in] DestIp The destination IP (host byte order) to request MAC
242 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
247 IN IP4_INTERFACE
*Interface
,
254 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
256 if (ArpQue
== NULL
) {
260 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
261 InitializeListHead (&ArpQue
->Link
);
263 InitializeListHead (&ArpQue
->Frames
);
264 ArpQue
->Interface
= Interface
;
266 Status
= gBS
->CreateEvent (
274 if (EFI_ERROR (Status
)) {
280 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
287 Remove all the transmit requests queued on the ARP queue, then free it.
289 @param[in] ArpQue Arp queue to free
290 @param[in] IoStatus The transmit status returned to transmit requests'
296 IN IP4_ARP_QUE
*ArpQue
,
297 IN EFI_STATUS IoStatus
300 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
303 // Remove all the frame waiting the ARP response
305 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
307 gBS
->CloseEvent (ArpQue
->OnResolved
);
313 Create a link layer receive token to wrap the receive request
315 @param[in] Interface The interface to receive from
316 @param[in] IpInstance The instance that request the receive (NULL for IP4
318 @param[in] CallBack Call back function to execute when finished.
319 @param[in] Context Opaque parameters to the callback
321 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
325 Ip4CreateLinkRxToken (
326 IN IP4_INTERFACE
*Interface
,
327 IN IP4_PROTOCOL
*IpInstance
,
328 IN IP4_FRAME_CALLBACK CallBack
,
332 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
333 IP4_LINK_RX_TOKEN
*Token
;
336 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
341 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
342 Token
->Interface
= Interface
;
343 Token
->IpInstance
= IpInstance
;
344 Token
->CallBack
= CallBack
;
345 Token
->Context
= Context
;
347 MnpToken
= &Token
->MnpToken
;
348 MnpToken
->Status
= EFI_NOT_READY
;
350 Status
= gBS
->CreateEvent (
358 if (EFI_ERROR (Status
)) {
363 MnpToken
->Packet
.RxData
= NULL
;
369 Free the link layer request token. It will close the event
370 then free the memory used.
372 @param[in] Token Request token to free.
376 Ip4FreeFrameRxToken (
377 IN IP4_LINK_RX_TOKEN
*Token
381 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
383 gBS
->CloseEvent (Token
->MnpToken
.Event
);
389 Remove all the frames on the ARP queue that pass the FrameToCancel,
390 that is, either FrameToCancel is NULL or it returns true for the frame.
392 @param[in] ArpQue ARP frame to remove the frames from.
393 @param[in] IoStatus The status returned to the cancelled frames'
395 @param[in] FrameToCancel Function to select which frame to cancel.
396 @param[in] Context Opaque parameter to the FrameToCancel.
401 IN IP4_ARP_QUE
*ArpQue
,
402 IN EFI_STATUS IoStatus
,
403 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
409 IP4_LINK_TX_TOKEN
*Token
;
411 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
412 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
414 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
415 RemoveEntryList (Entry
);
417 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
418 Ip4FreeLinkTxToken (Token
);
425 Remove all the frames on the interface that pass the FrameToCancel,
426 either queued on ARP queues or that have already been delivered to
427 MNP and not yet recycled.
429 @param[in] Interface Interface to remove the frames from.
430 @param[in] IoStatus The transmit status returned to the frames'
432 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
434 @param[in] Context Opaque parameters passed to FrameToCancel.
439 IN IP4_INTERFACE
*Interface
,
440 IN EFI_STATUS IoStatus
,
441 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
448 IP4_LINK_TX_TOKEN
*Token
;
451 // Cancel all the pending frames on ARP requests
453 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
454 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
456 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
458 if (IsListEmpty (&ArpQue
->Frames
)) {
459 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
464 // Cancel all the frames that have been delivered to MNP
465 // but not yet recycled.
467 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
468 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
470 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
471 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
478 Create an IP4_INTERFACE. Delay the creation of ARP instance until
479 the interface is configured.
481 @param[in] Mnp The shared MNP child of this IP4 service binding
483 @param[in] Controller The controller this IP4 service binding instance
484 is installed. Most like the UNDI handle.
485 @param[in] ImageHandle This driver's image handle.
487 @return Point to the created IP4_INTERFACE, otherwise NULL.
492 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
493 IN EFI_HANDLE Controller
,
494 IN EFI_HANDLE ImageHandle
497 IP4_INTERFACE
*Interface
;
498 EFI_SIMPLE_NETWORK_MODE SnpMode
;
500 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
502 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
506 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
507 InitializeListHead (&Interface
->Link
);
508 Interface
->RefCnt
= 1;
510 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
511 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
512 Interface
->Configured
= FALSE
;
514 Interface
->Controller
= Controller
;
515 Interface
->Image
= ImageHandle
;
516 Interface
->Mnp
= Mnp
;
517 Interface
->Arp
= NULL
;
518 Interface
->ArpHandle
= NULL
;
520 InitializeListHead (&Interface
->ArpQues
);
521 InitializeListHead (&Interface
->SentFrames
);
523 Interface
->RecvRequest
= NULL
;
526 // Get the interface's Mac address and broadcast mac address from SNP
528 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
529 FreePool (Interface
);
533 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
534 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
535 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
537 InitializeListHead (&Interface
->IpInstances
);
538 Interface
->PromiscRecv
= FALSE
;
545 Set the interface's address, create and configure
546 the ARP child if necessary.
548 @param Interface The interface to set the address.
549 @param IpAddr The interface's IP address.
550 @param SubnetMask The interface's netmask.
552 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
553 and a ARP is created for it.
554 @retval Others Failed to set the interface's address.
559 IN OUT IP4_INTERFACE
*Interface
,
561 IN IP4_ADDR SubnetMask
564 EFI_ARP_CONFIG_DATA ArpConfig
;
567 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
570 // Set the ip/netmask, then compute the subnet broadcast
571 // and network broadcast for easy access. When computing
572 // nework broadcast, the subnet mask is most like longer
573 // than the default netmask (not subneted) as defined in
574 // RFC793. If that isn't the case, we are aggregating the
575 // networks, use the subnet's mask instead.
577 Interface
->Ip
= IpAddr
;
578 Interface
->SubnetMask
= SubnetMask
;
579 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
580 Interface
->NetBrdcast
= (IpAddr
| ~SubnetMask
);
583 // Do clean up for Arp child
585 if (Interface
->ArpHandle
!= NULL
) {
586 if (Interface
->Arp
!= NULL
) {
588 Interface
->ArpHandle
,
589 &gEfiArpProtocolGuid
,
591 Interface
->Controller
594 Interface
->Arp
= NULL
;
597 NetLibDestroyServiceChild (
598 Interface
->Controller
,
600 &gEfiArpServiceBindingProtocolGuid
,
601 &Interface
->ArpHandle
604 Interface
->ArpHandle
= NULL
;
608 // If the address is NOT all zero, create then configure an ARP child.
609 // Pay attention: DHCP configures its station address as 0.0.0.0/0
611 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
612 Status
= NetLibCreateServiceChild (
613 Interface
->Controller
,
615 &gEfiArpServiceBindingProtocolGuid
,
616 &Interface
->ArpHandle
619 if (EFI_ERROR (Status
)) {
623 Status
= gBS
->OpenProtocol (
624 Interface
->ArpHandle
,
625 &gEfiArpProtocolGuid
,
626 (VOID
**) &Interface
->Arp
,
628 Interface
->Controller
,
629 EFI_OPEN_PROTOCOL_BY_DRIVER
632 if (EFI_ERROR (Status
)) {
636 IpAddr
= HTONL (IpAddr
);
637 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
638 ArpConfig
.SwAddressLength
= 4;
639 ArpConfig
.StationAddress
= &IpAddr
;
640 ArpConfig
.EntryTimeOut
= 0;
641 ArpConfig
.RetryCount
= 0;
642 ArpConfig
.RetryTimeOut
= 0;
644 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
646 if (EFI_ERROR (Status
)) {
648 Interface
->ArpHandle
,
649 &gEfiArpProtocolGuid
,
651 Interface
->Controller
658 Interface
->Configured
= TRUE
;
662 NetLibDestroyServiceChild (
663 Interface
->Controller
,
665 &gEfiArpServiceBindingProtocolGuid
,
666 &Interface
->ArpHandle
674 Filter function to cancel all the frame related to an IP instance.
676 @param[in] Frame The transmit request to test whether to cancel
677 @param[in] Context The context which is the Ip instance that issued
680 @retval TRUE The frame belongs to this instance and is to be
682 @retval FALSE The frame doesn't belong to this instance.
686 Ip4CancelInstanceFrame (
687 IN IP4_LINK_TX_TOKEN
*Frame
,
691 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
701 If there is a pending receive request, cancel it. Don't call
702 the receive request's callback because this function can be only
703 called if the instance or driver is tearing itself down. It
704 doesn't make sense to call it back. But it is necessary to call
705 the transmit token's callback to give it a chance to free the
706 packet and update the upper layer's transmit request status, say
709 @param[in] Interface The interface used by the IpInstance
714 IN IP4_INTERFACE
*Interface
718 IP4_LINK_RX_TOKEN
*Token
;
720 if ((Token
= Interface
->RecvRequest
) != NULL
) {
721 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
723 Interface
->RecvRequest
= NULL
;
724 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
726 gBS
->RestoreTPL (OldTpl
);
732 Free the interface used by IpInstance. All the IP instance with
733 the same Ip/Netmask pair share the same interface. It is reference
734 counted. All the frames haven't been sent will be cancelled.
735 Because the IpInstance is optional, the caller must remove
736 IpInstance from the interface's instance list itself.
738 @param[in] Interface The interface used by the IpInstance.
739 @param[in] IpInstance The Ip instance that free the interface. NULL if
740 the Ip driver is releasing the default interface.
742 @retval EFI_SUCCESS The interface use IpInstance is freed.
747 IN IP4_INTERFACE
*Interface
,
748 IN IP4_PROTOCOL
*IpInstance OPTIONAL
751 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
752 ASSERT (Interface
->RefCnt
> 0);
755 // Remove all the pending transmit token related to this IP instance.
757 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
759 if (--Interface
->RefCnt
> 0) {
764 // Destroy the interface if this is the last IP instance that
765 // has the address. Remove all the system transmitted packets
766 // from this interface, cancel the receive request if there is
767 // one, and destroy the ARP requests.
769 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
770 Ip4CancelReceive (Interface
);
772 ASSERT (IsListEmpty (&Interface
->IpInstances
));
773 ASSERT (IsListEmpty (&Interface
->ArpQues
));
774 ASSERT (IsListEmpty (&Interface
->SentFrames
));
776 if (Interface
->Arp
!= NULL
) {
778 Interface
->ArpHandle
,
779 &gEfiArpProtocolGuid
,
781 Interface
->Controller
784 NetLibDestroyServiceChild (
785 Interface
->Controller
,
787 &gEfiArpServiceBindingProtocolGuid
,
792 RemoveEntryList (&Interface
->Link
);
793 FreePool (Interface
);
799 This function tries to send all the queued frames in ArpQue to the default gateway if
800 the ARP resolve for direct destination address is failed when using /32 subnet mask.
802 @param[in] ArpQue The ARP queue of a failed request.
804 @retval EFI_SUCCESS All the queued frames have been send to the default route.
805 @retval Others Failed to send the queued frames.
809 Ip4SendFrameToDefaultRoute (
810 IN IP4_ARP_QUE
*ArpQue
815 IP4_ROUTE_CACHE_ENTRY
*RtCacheEntry
;
816 IP4_LINK_TX_TOKEN
*Token
;
819 IP4_ROUTE_ENTRY
*DefaultRoute
;
822 // ARP resolve failed when using /32 subnet mask.
824 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
825 RemoveEntryList (Entry
);
826 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
827 ASSERT (Token
->Interface
->SubnetMask
== IP4_ALLONE_ADDRESS
);
829 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
832 if (Token
->IpInstance
!= NULL
) {
833 RtCacheEntry
= Ip4FindRouteCache (Token
->IpInstance
->RouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
835 if (RtCacheEntry
== NULL
) {
836 RtCacheEntry
= Ip4FindRouteCache (Token
->IpSb
->DefaultRouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
838 if (RtCacheEntry
== NULL
) {
839 Status
= EFI_NO_MAPPING
;
842 DefaultRoute
= (IP4_ROUTE_ENTRY
*)RtCacheEntry
->Tag
;
843 if (DefaultRoute
== NULL
) {
844 Status
= EFI_NO_MAPPING
;
848 // Try to send the frame to the default route.
850 Gateway
= DefaultRoute
->NextHop
;
851 if (ArpQue
->Ip
== Gateway
) {
853 // ARP resolve for the default route is failed, return error to caller.
855 Status
= EFI_NO_MAPPING
;
858 RtCacheEntry
->NextHop
= Gateway
;
859 Status
= Ip4SendFrame (Token
->Interface
,Token
->IpInstance
,Token
->Packet
,Gateway
,Token
->CallBack
,Token
->Context
,Token
->IpSb
);
860 if (EFI_ERROR (Status
)) {
861 Status
= EFI_NO_MAPPING
;
864 Ip4FreeRouteCacheEntry (RtCacheEntry
);
870 if (RtCacheEntry
!= NULL
) {
871 Ip4FreeRouteCacheEntry (RtCacheEntry
);
873 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
874 Ip4FreeLinkTxToken (Token
);
880 Callback function when ARP request are finished. It will cancel
881 all the queued frame if the ARP requests failed. Or transmit them
882 if the request succeed.
884 @param[in] Context The context of the callback, a point to the ARP
890 Ip4OnArpResolvedDpc (
897 IP4_INTERFACE
*Interface
;
898 IP4_LINK_TX_TOKEN
*Token
;
902 ArpQue
= (IP4_ARP_QUE
*) Context
;
903 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
905 RemoveEntryList (&ArpQue
->Link
);
908 // ARP resolve failed for some reason.
910 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
911 if (ArpQue
->Interface
->SubnetMask
!= IP4_ALLONE_ADDRESS
) {
913 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
916 IoStatus
= EFI_NO_MAPPING
;
919 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
922 IoStatus
= Ip4SendFrameToDefaultRoute (ArpQue
);
928 // ARP resolve succeeded, Transmit all the frame. Release the ARP
929 // queue. It isn't necessary for us to cache the ARP binding because
930 // we always check the ARP cache first before transmit.
932 IoStatus
= EFI_SUCCESS
;
933 Interface
= ArpQue
->Interface
;
935 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
936 RemoveEntryList (Entry
);
938 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
939 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
942 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
943 // may be called before Mnp->Transmit returns which will remove this tx
944 // token from the SentFrames list. Remove it from the list if the returned
945 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
946 // FrameSentDpc won't be queued.
948 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
950 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
951 if (EFI_ERROR (Status
)) {
952 RemoveEntryList (&Token
->Link
);
953 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
955 Ip4FreeLinkTxToken (Token
);
961 Ip4FreeArpQue (ArpQue
, IoStatus
);
965 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
967 @param Event The Arp request event.
968 @param Context The context of the callback, a point to the ARP
980 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
982 QueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
988 Callback funtion when frame transmission is finished. It will
989 call the frame owner's callback function to tell it the result.
991 @param[in] Context Context which is point to the token.
1000 IP4_LINK_TX_TOKEN
*Token
;
1002 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
1003 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
1005 RemoveEntryList (&Token
->Link
);
1010 Token
->MnpToken
.Status
,
1015 Ip4FreeLinkTxToken (Token
);
1019 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1021 @param[in] Event The transmit token's event.
1022 @param[in] Context Context which is point to the token.
1033 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1035 QueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
1041 Send a frame from the interface. If the next hop is broadcast or
1042 multicast address, it is transmitted immediately. If the next hop
1043 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1044 If some error happened, the CallBack won't be called. So, the caller
1045 must test the return value, and take action when there is an error.
1047 @param[in] Interface The interface to send the frame from
1048 @param[in] IpInstance The IP child that request the transmission. NULL
1049 if it is the IP4 driver itself.
1050 @param[in] Packet The packet to transmit.
1051 @param[in] NextHop The immediate destination to transmit the packet
1053 @param[in] CallBack Function to call back when transmit finished.
1054 @param[in] Context Opaque parameter to the call back.
1055 @param[in] IpSb The pointer to the IP4 service binding instance.
1057 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1058 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1059 @retval EFI_SUCCESS The packet is successfully transmitted.
1060 @retval other Other error occurs.
1065 IN IP4_INTERFACE
*Interface
,
1066 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1068 IN IP4_ADDR NextHop
,
1069 IN IP4_FRAME_CALLBACK CallBack
,
1071 IN IP4_SERVICE
*IpSb
1074 IP4_LINK_TX_TOKEN
*Token
;
1076 IP4_ARP_QUE
*ArpQue
;
1077 EFI_ARP_PROTOCOL
*Arp
;
1080 ASSERT (Interface
->Configured
);
1082 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
, IpSb
);
1084 if (Token
== NULL
) {
1085 return EFI_OUT_OF_RESOURCES
;
1089 // Get the destination MAC address for multicast and broadcasts.
1090 // Don't depend on ARP to solve the address since there maybe no
1091 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1092 // all the broadcasts.
1094 if (NextHop
== IP4_ALLONE_ADDRESS
) {
1095 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
1098 } else if (IP4_IS_MULTICAST (NextHop
)) {
1100 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
1102 if (EFI_ERROR (Status
)) {
1110 // Can only send out multicast/broadcast if the IP address is zero
1112 if ((Arp
= Interface
->Arp
) == NULL
) {
1113 Status
= EFI_NO_MAPPING
;
1118 // First check whether this binding is in the ARP cache.
1120 NextHop
= HTONL (NextHop
);
1121 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1123 if (Status
== EFI_SUCCESS
) {
1126 } else if (Status
!= EFI_NOT_READY
) {
1131 // Have to do asynchronous ARP resolution. First check
1132 // whether there is already a pending request.
1136 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1137 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1139 if (ArpQue
->Ip
== NextHop
) {
1145 // Found a pending ARP request, enqueue the frame then return
1147 if (Entry
!= &Interface
->ArpQues
) {
1148 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1153 // First frame to NextHop, issue an asynchronous ARP requests
1155 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1157 if (ArpQue
== NULL
) {
1158 Status
= EFI_OUT_OF_RESOURCES
;
1162 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1164 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1165 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1169 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1170 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1175 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1176 // Remove it if the returned status is not EFI_SUCCESS.
1178 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1179 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1180 if (EFI_ERROR (Status
)) {
1181 RemoveEntryList (&Token
->Link
);
1188 Ip4FreeLinkTxToken (Token
);
1194 Call back function when the received packet is freed.
1195 Check Ip4OnFrameReceived for information.
1197 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1206 IP4_LINK_RX_TOKEN
*Frame
;
1208 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1209 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1211 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1212 Ip4FreeFrameRxToken (Frame
);
1217 Received a frame from MNP, wrap it in net buffer then deliver
1218 it to IP's input function. The ownship of the packet also
1219 transferred to IP. When Ip is finished with this packet, it
1220 will call NetbufFree to release the packet, NetbufFree will
1221 again call the Ip4RecycleFrame to signal MNP's event and free
1224 @param Context Context for the callback.
1229 Ip4OnFrameReceivedDpc (
1233 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1234 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1235 IP4_LINK_RX_TOKEN
*Token
;
1236 NET_FRAGMENT Netfrag
;
1240 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1241 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1244 // First clear the interface's receive request in case the
1245 // caller wants to call Ip4ReceiveFrame in the callback.
1247 Token
->Interface
->RecvRequest
= NULL
;
1249 MnpToken
= &Token
->MnpToken
;
1250 MnpRxData
= MnpToken
->Packet
.RxData
;
1252 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1253 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1254 Ip4FreeFrameRxToken (Token
);
1260 // Wrap the frame in a net buffer then deliever it to IP input.
1261 // IP will reassemble the packet, and deliver it to upper layer
1263 Netfrag
.Len
= MnpRxData
->DataLength
;
1264 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1266 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1268 if (Packet
== NULL
) {
1269 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1271 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1272 Ip4FreeFrameRxToken (Token
);
1277 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1278 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1279 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1281 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1285 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1287 @param Event The receive event delivered to MNP for receive.
1288 @param Context Context for the callback.
1293 Ip4OnFrameReceived (
1299 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1301 QueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1306 Request to receive the packet from the interface.
1308 @param[in] Interface The interface to receive the frames from.
1309 @param[in] IpInstance The instance that requests the receive. NULL for
1311 @param[in] CallBack Function to call when receive finished.
1312 @param[in] Context Opaque parameter to the callback.
1314 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1315 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1316 @retval EFI_SUCCESS The recieve request has been started.
1317 @retval other Other error occurs.
1322 IN IP4_INTERFACE
*Interface
,
1323 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1324 IN IP4_FRAME_CALLBACK CallBack
,
1328 IP4_LINK_RX_TOKEN
*Token
;
1331 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1333 if (Interface
->RecvRequest
!= NULL
) {
1334 return EFI_ALREADY_STARTED
;
1337 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1339 if (Token
== NULL
) {
1340 return EFI_OUT_OF_RESOURCES
;
1343 Interface
->RecvRequest
= Token
;
1344 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1345 if (EFI_ERROR (Status
)) {
1346 Interface
->RecvRequest
= NULL
;
1347 Ip4FreeFrameRxToken (Token
);