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
,
125 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
127 @param[in] Interface The interface to send out to.
128 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
129 the packet is sent by the IP4 driver itself.
130 @param[in] Packet The packet to transmit
131 @param[in] CallBack Call back function to execute if transmission
133 @param[in] Context Opaque parameter to the call back.
134 @param[in] IpSb The pointer to the IP4 service binding instance.
136 @retval Token The wrapped token if succeed
137 @retval NULL The wrapped token if NULL
142 IN IP4_INTERFACE
*Interface
,
143 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
145 IN IP4_FRAME_CALLBACK CallBack
,
150 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
151 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
152 IP4_LINK_TX_TOKEN
*Token
;
156 Token
= AllocatePool (
157 sizeof (IP4_LINK_TX_TOKEN
) + \
158 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
)
165 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
166 InitializeListHead (&Token
->Link
);
168 Token
->Interface
= Interface
;
169 Token
->IpInstance
= IpInstance
;
171 Token
->CallBack
= CallBack
;
172 Token
->Packet
= Packet
;
173 Token
->Context
= Context
;
174 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
175 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
177 MnpToken
= &(Token
->MnpToken
);
178 MnpToken
->Status
= EFI_NOT_READY
;
180 Status
= gBS
->CreateEvent (
188 if (EFI_ERROR (Status
)) {
193 MnpTxData
= &Token
->MnpTxData
;
194 MnpToken
->Packet
.TxData
= MnpTxData
;
196 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
197 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
198 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
199 MnpTxData
->DataLength
= Packet
->TotalSize
;
200 MnpTxData
->HeaderLength
= 0;
202 Count
= Packet
->BlockOpNum
;
204 NetbufBuildExt (Packet
, (NET_FRAGMENT
*)MnpTxData
->FragmentTable
, &Count
);
205 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
);
229 Create an IP_ARP_QUE structure to request ARP service.
231 @param[in] Interface The interface to send ARP from.
232 @param[in] DestIp The destination IP (host byte order) to request MAC
235 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
240 IN IP4_INTERFACE
*Interface
,
247 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
249 if (ArpQue
== NULL
) {
253 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
254 InitializeListHead (&ArpQue
->Link
);
256 InitializeListHead (&ArpQue
->Frames
);
257 ArpQue
->Interface
= Interface
;
259 Status
= gBS
->CreateEvent (
267 if (EFI_ERROR (Status
)) {
273 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
279 Remove all the transmit requests queued on the ARP queue, then free it.
281 @param[in] ArpQue Arp queue to free
282 @param[in] IoStatus The transmit status returned to transmit requests'
288 IN IP4_ARP_QUE
*ArpQue
,
289 IN EFI_STATUS IoStatus
292 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
295 // Remove all the frame waiting the ARP response
297 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
299 gBS
->CloseEvent (ArpQue
->OnResolved
);
304 Create a link layer receive token to wrap the receive request
306 @param[in] Interface The interface to receive from
307 @param[in] IpInstance The instance that request the receive (NULL for IP4
309 @param[in] CallBack Call back function to execute when finished.
310 @param[in] Context Opaque parameters to the callback
312 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
316 Ip4CreateLinkRxToken (
317 IN IP4_INTERFACE
*Interface
,
318 IN IP4_PROTOCOL
*IpInstance
,
319 IN IP4_FRAME_CALLBACK CallBack
,
323 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
324 IP4_LINK_RX_TOKEN
*Token
;
327 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
332 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
333 Token
->Interface
= Interface
;
334 Token
->IpInstance
= IpInstance
;
335 Token
->CallBack
= CallBack
;
336 Token
->Context
= Context
;
338 MnpToken
= &Token
->MnpToken
;
339 MnpToken
->Status
= EFI_NOT_READY
;
341 Status
= gBS
->CreateEvent (
349 if (EFI_ERROR (Status
)) {
354 MnpToken
->Packet
.RxData
= NULL
;
359 Free the link layer request token. It will close the event
360 then free the memory used.
362 @param[in] Token Request token to free.
366 Ip4FreeFrameRxToken (
367 IN IP4_LINK_RX_TOKEN
*Token
370 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
372 gBS
->CloseEvent (Token
->MnpToken
.Event
);
377 Remove all the frames on the ARP queue that pass the FrameToCancel,
378 that is, either FrameToCancel is NULL or it returns true for the frame.
380 @param[in] ArpQue ARP frame to remove the frames from.
381 @param[in] IoStatus The status returned to the cancelled frames'
383 @param[in] FrameToCancel Function to select which frame to cancel.
384 @param[in] Context Opaque parameter to the FrameToCancel.
389 IN IP4_ARP_QUE
*ArpQue
,
390 IN EFI_STATUS IoStatus
,
391 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
397 IP4_LINK_TX_TOKEN
*Token
;
399 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
400 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
402 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
403 RemoveEntryList (Entry
);
405 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
406 Ip4FreeLinkTxToken (Token
);
412 Remove all the frames on the interface that pass the FrameToCancel,
413 either queued on ARP queues or that have already been delivered to
414 MNP and not yet recycled.
416 @param[in] Interface Interface to remove the frames from.
417 @param[in] IoStatus The transmit status returned to the frames'
419 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
421 @param[in] Context Opaque parameters passed to FrameToCancel.
426 IN IP4_INTERFACE
*Interface
,
427 IN EFI_STATUS IoStatus
,
428 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL
,
435 IP4_LINK_TX_TOKEN
*Token
;
438 // Cancel all the pending frames on ARP requests
440 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
441 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
443 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
445 if (IsListEmpty (&ArpQue
->Frames
)) {
446 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
451 // Cancel all the frames that have been delivered to MNP
452 // but not yet recycled.
454 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
455 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
457 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
458 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
464 Create an IP4_INTERFACE. Delay the creation of ARP instance until
465 the interface is configured.
467 @param[in] Mnp The shared MNP child of this IP4 service binding
469 @param[in] Controller The controller this IP4 service binding instance
470 is installed. Most like the UNDI handle.
471 @param[in] ImageHandle This driver's image handle.
473 @return Point to the created IP4_INTERFACE, otherwise NULL.
478 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
479 IN EFI_HANDLE Controller
,
480 IN EFI_HANDLE ImageHandle
483 IP4_INTERFACE
*Interface
;
484 EFI_SIMPLE_NETWORK_MODE SnpMode
;
490 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
492 if (Interface
== NULL
) {
496 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
497 InitializeListHead (&Interface
->Link
);
498 Interface
->RefCnt
= 1;
500 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
501 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
502 Interface
->Configured
= FALSE
;
504 Interface
->Controller
= Controller
;
505 Interface
->Image
= ImageHandle
;
506 Interface
->Mnp
= Mnp
;
507 Interface
->Arp
= NULL
;
508 Interface
->ArpHandle
= NULL
;
510 InitializeListHead (&Interface
->ArpQues
);
511 InitializeListHead (&Interface
->SentFrames
);
513 Interface
->RecvRequest
= NULL
;
516 // Get the interface's Mac address and broadcast mac address from SNP
518 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
519 FreePool (Interface
);
523 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
524 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
525 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
527 InitializeListHead (&Interface
->IpInstances
);
528 Interface
->PromiscRecv
= FALSE
;
534 Set the interface's address, create and configure
535 the ARP child if necessary.
537 @param Interface The interface to set the address.
538 @param IpAddr The interface's IP address.
539 @param SubnetMask The interface's netmask.
541 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
542 and a ARP is created for it.
543 @retval Others Failed to set the interface's address.
548 IN OUT IP4_INTERFACE
*Interface
,
550 IN IP4_ADDR SubnetMask
553 EFI_ARP_CONFIG_DATA ArpConfig
;
556 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
559 // Set the ip/netmask, then compute the subnet broadcast
560 // and network broadcast for easy access. When computing
561 // network broadcast, the subnet mask is most like longer
562 // than the default netmask (not subneted) as defined in
563 // RFC793. If that isn't the case, we are aggregating the
564 // networks, use the subnet's mask instead.
566 Interface
->Ip
= IpAddr
;
567 Interface
->SubnetMask
= SubnetMask
;
568 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
569 Interface
->NetBrdcast
= (IpAddr
| ~SubnetMask
);
572 // Do clean up for Arp child
574 if (Interface
->ArpHandle
!= NULL
) {
575 if (Interface
->Arp
!= NULL
) {
577 Interface
->ArpHandle
,
578 &gEfiArpProtocolGuid
,
580 Interface
->Controller
583 Interface
->Arp
= NULL
;
586 NetLibDestroyServiceChild (
587 Interface
->Controller
,
589 &gEfiArpServiceBindingProtocolGuid
,
593 Interface
->ArpHandle
= NULL
;
597 // If the address is NOT all zero, create then configure an ARP child.
598 // Pay attention: DHCP configures its station address as 0.0.0.0/0
600 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
601 Status
= NetLibCreateServiceChild (
602 Interface
->Controller
,
604 &gEfiArpServiceBindingProtocolGuid
,
605 &Interface
->ArpHandle
608 if (EFI_ERROR (Status
)) {
612 Status
= gBS
->OpenProtocol (
613 Interface
->ArpHandle
,
614 &gEfiArpProtocolGuid
,
615 (VOID
**)&Interface
->Arp
,
617 Interface
->Controller
,
618 EFI_OPEN_PROTOCOL_BY_DRIVER
621 if (EFI_ERROR (Status
)) {
625 IpAddr
= HTONL (IpAddr
);
626 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
627 ArpConfig
.SwAddressLength
= 4;
628 ArpConfig
.StationAddress
= &IpAddr
;
629 ArpConfig
.EntryTimeOut
= 0;
630 ArpConfig
.RetryCount
= 0;
631 ArpConfig
.RetryTimeOut
= 0;
633 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
635 if (EFI_ERROR (Status
)) {
637 Interface
->ArpHandle
,
638 &gEfiArpProtocolGuid
,
640 Interface
->Controller
647 Interface
->Configured
= TRUE
;
651 NetLibDestroyServiceChild (
652 Interface
->Controller
,
654 &gEfiArpServiceBindingProtocolGuid
,
662 Filter function to cancel all the frame related to an IP instance.
664 @param[in] Frame The transmit request to test whether to cancel
665 @param[in] Context The context which is the Ip instance that issued
668 @retval TRUE The frame belongs to this instance and is to be
670 @retval FALSE The frame doesn't belong to this instance.
674 Ip4CancelInstanceFrame (
675 IN IP4_LINK_TX_TOKEN
*Frame
,
679 if (Frame
->IpInstance
== (IP4_PROTOCOL
*)Context
) {
687 If there is a pending receive request, cancel it. Don't call
688 the receive request's callback because this function can be only
689 called if the instance or driver is tearing itself down. It
690 doesn't make sense to call it back. But it is necessary to call
691 the transmit token's callback to give it a chance to free the
692 packet and update the upper layer's transmit request status, say
695 @param[in] Interface The interface used by the IpInstance
700 IN IP4_INTERFACE
*Interface
704 IP4_LINK_RX_TOKEN
*Token
;
706 if ((Token
= Interface
->RecvRequest
) != NULL
) {
707 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
709 Interface
->RecvRequest
= NULL
;
710 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
712 gBS
->RestoreTPL (OldTpl
);
717 Free the interface used by IpInstance. All the IP instance with
718 the same Ip/Netmask pair share the same interface. It is reference
719 counted. All the frames haven't been sent will be cancelled.
720 Because the IpInstance is optional, the caller must remove
721 IpInstance from the interface's instance list itself.
723 @param[in] Interface The interface used by the IpInstance.
724 @param[in] IpInstance The Ip instance that free the interface. NULL if
725 the Ip driver is releasing the default interface.
727 @retval EFI_SUCCESS The interface use IpInstance is freed.
732 IN IP4_INTERFACE
*Interface
,
733 IN IP4_PROTOCOL
*IpInstance OPTIONAL
736 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
737 ASSERT (Interface
->RefCnt
> 0);
740 // Remove all the pending transmit token related to this IP instance.
742 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
744 if (--Interface
->RefCnt
> 0) {
749 // Destroy the interface if this is the last IP instance that
750 // has the address. Remove all the system transmitted packets
751 // from this interface, cancel the receive request if there is
752 // one, and destroy the ARP requests.
754 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
755 Ip4CancelReceive (Interface
);
757 ASSERT (IsListEmpty (&Interface
->IpInstances
));
758 ASSERT (IsListEmpty (&Interface
->ArpQues
));
759 ASSERT (IsListEmpty (&Interface
->SentFrames
));
761 if (Interface
->Arp
!= NULL
) {
763 Interface
->ArpHandle
,
764 &gEfiArpProtocolGuid
,
766 Interface
->Controller
769 NetLibDestroyServiceChild (
770 Interface
->Controller
,
772 &gEfiArpServiceBindingProtocolGuid
,
777 RemoveEntryList (&Interface
->Link
);
778 FreePool (Interface
);
784 This function tries to send all the queued frames in ArpQue to the default gateway if
785 the ARP resolve for direct destination address is failed when using /32 subnet mask.
787 @param[in] ArpQue The ARP queue of a failed request.
789 @retval EFI_SUCCESS All the queued frames have been send to the default route.
790 @retval Others Failed to send the queued frames.
794 Ip4SendFrameToDefaultRoute (
795 IN IP4_ARP_QUE
*ArpQue
800 IP4_ROUTE_CACHE_ENTRY
*RtCacheEntry
;
801 IP4_LINK_TX_TOKEN
*Token
;
804 IP4_ROUTE_ENTRY
*DefaultRoute
;
807 // ARP resolve failed when using /32 subnet mask.
809 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
810 RemoveEntryList (Entry
);
811 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
812 ASSERT (Token
->Interface
->SubnetMask
== IP4_ALLONE_ADDRESS
);
814 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
817 if (Token
->IpInstance
!= NULL
) {
818 RtCacheEntry
= Ip4FindRouteCache (Token
->IpInstance
->RouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
821 if (RtCacheEntry
== NULL
) {
822 RtCacheEntry
= Ip4FindRouteCache (Token
->IpSb
->DefaultRouteTable
, NTOHL (ArpQue
->Ip
), Token
->Interface
->Ip
);
825 if (RtCacheEntry
== NULL
) {
826 Status
= EFI_NO_MAPPING
;
830 DefaultRoute
= (IP4_ROUTE_ENTRY
*)RtCacheEntry
->Tag
;
831 if (DefaultRoute
== NULL
) {
832 Status
= EFI_NO_MAPPING
;
837 // Try to send the frame to the default route.
839 Gateway
= DefaultRoute
->NextHop
;
840 if (ArpQue
->Ip
== Gateway
) {
842 // ARP resolve for the default route is failed, return error to caller.
844 Status
= EFI_NO_MAPPING
;
848 RtCacheEntry
->NextHop
= Gateway
;
849 Status
= Ip4SendFrame (Token
->Interface
, Token
->IpInstance
, Token
->Packet
, Gateway
, Token
->CallBack
, Token
->Context
, Token
->IpSb
);
850 if (EFI_ERROR (Status
)) {
851 Status
= EFI_NO_MAPPING
;
855 Ip4FreeRouteCacheEntry (RtCacheEntry
);
861 if (RtCacheEntry
!= NULL
) {
862 Ip4FreeRouteCacheEntry (RtCacheEntry
);
865 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
866 Ip4FreeLinkTxToken (Token
);
871 Callback function when ARP request are finished. It will cancel
872 all the queued frame if the ARP requests failed. Or transmit them
873 if the request succeed.
875 @param[in] Context The context of the callback, a point to the ARP
881 Ip4OnArpResolvedDpc (
888 IP4_INTERFACE
*Interface
;
889 IP4_LINK_TX_TOKEN
*Token
;
893 ArpQue
= (IP4_ARP_QUE
*)Context
;
894 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
896 RemoveEntryList (&ArpQue
->Link
);
899 // ARP resolve failed for some reason.
901 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
902 if (ArpQue
->Interface
->SubnetMask
!= IP4_ALLONE_ADDRESS
) {
904 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
907 IoStatus
= EFI_NO_MAPPING
;
910 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
913 IoStatus
= Ip4SendFrameToDefaultRoute (ArpQue
);
920 // ARP resolve succeeded, Transmit all the frame. Release the ARP
921 // queue. It isn't necessary for us to cache the ARP binding because
922 // we always check the ARP cache first before transmit.
924 IoStatus
= EFI_SUCCESS
;
925 Interface
= ArpQue
->Interface
;
927 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
928 RemoveEntryList (Entry
);
930 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
931 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
934 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
935 // may be called before Mnp->Transmit returns which will remove this tx
936 // token from the SentFrames list. Remove it from the list if the returned
937 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
938 // FrameSentDpc won't be queued.
940 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
942 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
943 if (EFI_ERROR (Status
)) {
944 RemoveEntryList (&Token
->Link
);
945 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
947 Ip4FreeLinkTxToken (Token
);
953 Ip4FreeArpQue (ArpQue
, IoStatus
);
957 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
959 @param Event The Arp request event.
960 @param Context The context of the callback, a point to the ARP
972 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
974 QueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
978 Callback function when frame transmission is finished. It will
979 call the frame owner's callback function to tell it the result.
981 @param[in] Context Context which is point to the token.
990 IP4_LINK_TX_TOKEN
*Token
;
992 Token
= (IP4_LINK_TX_TOKEN
*)Context
;
993 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
995 RemoveEntryList (&Token
->Link
);
1000 Token
->MnpToken
.Status
,
1005 Ip4FreeLinkTxToken (Token
);
1009 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1011 @param[in] Event The transmit token's event.
1012 @param[in] Context Context which is point to the token.
1023 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1025 QueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
1029 Send a frame from the interface. If the next hop is broadcast or
1030 multicast address, it is transmitted immediately. If the next hop
1031 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1032 If some error happened, the CallBack won't be called. So, the caller
1033 must test the return value, and take action when there is an error.
1035 @param[in] Interface The interface to send the frame from
1036 @param[in] IpInstance The IP child that request the transmission. NULL
1037 if it is the IP4 driver itself.
1038 @param[in] Packet The packet to transmit.
1039 @param[in] NextHop The immediate destination to transmit the packet
1041 @param[in] CallBack Function to call back when transmit finished.
1042 @param[in] Context Opaque parameter to the call back.
1043 @param[in] IpSb The pointer to the IP4 service binding instance.
1045 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1046 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1047 @retval EFI_SUCCESS The packet is successfully transmitted.
1048 @retval other Other error occurs.
1053 IN IP4_INTERFACE
*Interface
,
1054 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1056 IN IP4_ADDR NextHop
,
1057 IN IP4_FRAME_CALLBACK CallBack
,
1059 IN IP4_SERVICE
*IpSb
1062 IP4_LINK_TX_TOKEN
*Token
;
1064 IP4_ARP_QUE
*ArpQue
;
1065 EFI_ARP_PROTOCOL
*Arp
;
1068 ASSERT (Interface
->Configured
);
1070 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
, IpSb
);
1072 if (Token
== NULL
) {
1073 return EFI_OUT_OF_RESOURCES
;
1077 // Get the destination MAC address for multicast and broadcasts.
1078 // Don't depend on ARP to solve the address since there maybe no
1079 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1080 // all the broadcasts.
1082 if (NextHop
== IP4_ALLONE_ADDRESS
) {
1083 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
1085 } else if (IP4_IS_MULTICAST (NextHop
)) {
1086 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
1088 if (EFI_ERROR (Status
)) {
1096 // Can only send out multicast/broadcast if the IP address is zero
1098 if ((Arp
= Interface
->Arp
) == NULL
) {
1099 Status
= EFI_NO_MAPPING
;
1104 // First check whether this binding is in the ARP cache.
1106 NextHop
= HTONL (NextHop
);
1107 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1109 if (Status
== EFI_SUCCESS
) {
1111 } else if (Status
!= EFI_NOT_READY
) {
1116 // Have to do asynchronous ARP resolution. First check
1117 // whether there is already a pending request.
1121 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1122 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1124 if (ArpQue
->Ip
== NextHop
) {
1130 // Found a pending ARP request, enqueue the frame then return
1132 if (Entry
!= &Interface
->ArpQues
) {
1133 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1138 // First frame to NextHop, issue an asynchronous ARP requests
1140 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1142 if (ArpQue
== NULL
) {
1143 Status
= EFI_OUT_OF_RESOURCES
;
1147 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1149 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1150 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1154 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1155 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1160 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1161 // Remove it if the returned status is not EFI_SUCCESS.
1163 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1164 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1165 if (EFI_ERROR (Status
)) {
1166 RemoveEntryList (&Token
->Link
);
1173 Ip4FreeLinkTxToken (Token
);
1178 Call back function when the received packet is freed.
1179 Check Ip4OnFrameReceived for information.
1181 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1190 IP4_LINK_RX_TOKEN
*Frame
;
1192 Frame
= (IP4_LINK_RX_TOKEN
*)Context
;
1193 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1195 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1196 Ip4FreeFrameRxToken (Frame
);
1200 Received a frame from MNP, wrap it in net buffer then deliver
1201 it to IP's input function. The ownship of the packet also
1202 transferred to IP. When Ip is finished with this packet, it
1203 will call NetbufFree to release the packet, NetbufFree will
1204 again call the Ip4RecycleFrame to signal MNP's event and free
1207 @param Context Context for the callback.
1212 Ip4OnFrameReceivedDpc (
1216 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1217 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1218 IP4_LINK_RX_TOKEN
*Token
;
1219 NET_FRAGMENT Netfrag
;
1223 Token
= (IP4_LINK_RX_TOKEN
*)Context
;
1224 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1227 // First clear the interface's receive request in case the
1228 // caller wants to call Ip4ReceiveFrame in the callback.
1230 Token
->Interface
->RecvRequest
= NULL
;
1232 MnpToken
= &Token
->MnpToken
;
1233 MnpRxData
= MnpToken
->Packet
.RxData
;
1235 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1236 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1237 Ip4FreeFrameRxToken (Token
);
1243 // Wrap the frame in a net buffer then deliver it to IP input.
1244 // IP will reassemble the packet, and deliver it to upper layer
1246 Netfrag
.Len
= MnpRxData
->DataLength
;
1247 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1249 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1251 if (Packet
== NULL
) {
1252 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1254 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1255 Ip4FreeFrameRxToken (Token
);
1260 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1261 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1262 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1264 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1268 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1270 @param Event The receive event delivered to MNP for receive.
1271 @param Context Context for the callback.
1276 Ip4OnFrameReceived (
1282 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1284 QueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1288 Request to receive the packet from the interface.
1290 @param[in] Interface The interface to receive the frames from.
1291 @param[in] IpInstance The instance that requests the receive. NULL for
1293 @param[in] CallBack Function to call when receive finished.
1294 @param[in] Context Opaque parameter to the callback.
1296 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1297 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1298 @retval EFI_SUCCESS The receive request has been started.
1299 @retval other Other error occurs.
1304 IN IP4_INTERFACE
*Interface
,
1305 IN IP4_PROTOCOL
*IpInstance OPTIONAL
,
1306 IN IP4_FRAME_CALLBACK CallBack
,
1310 IP4_LINK_RX_TOKEN
*Token
;
1313 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1315 if (Interface
->RecvRequest
!= NULL
) {
1316 return EFI_ALREADY_STARTED
;
1319 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1321 if (Token
== NULL
) {
1322 return EFI_OUT_OF_RESOURCES
;
1325 Interface
->RecvRequest
= Token
;
1326 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1327 if (EFI_ERROR (Status
)) {
1328 Interface
->RecvRequest
= NULL
;
1329 Ip4FreeFrameRxToken (Token
);