3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Implement IP4 pesudo interface.
27 // Mac address with all zero, used to determine whethter the ARP
28 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
30 STATIC EFI_MAC_ADDRESS mZeroMacAddress
;
65 Ip4OnFrameReceivedDpc (
80 IN IP4_ARP_QUE
*ArpQue
,
81 IN EFI_STATUS IoStatus
,
82 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
88 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
90 @param Interface The interface to send out from
91 @param IpInstance The IpInstance that transmit the packet. NULL if
92 the packet is sent by the IP4 driver itself.
93 @param Packet The packet to transmit
94 @param CallBack Call back function to execute if transmission
96 @param Context Opaque parameter to the call back.
98 @return The wrapped token if succeed or NULL
104 IN IP4_INTERFACE
*Interface
,
105 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
107 IN IP4_FRAME_CALLBACK CallBack
,
111 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
112 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
113 IP4_LINK_TX_TOKEN
*Token
;
117 Token
= NetAllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
118 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
124 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
125 NetListInit (&Token
->Link
);
127 Token
->Interface
= Interface
;
128 Token
->IpInstance
= IpInstance
;
129 Token
->CallBack
= CallBack
;
130 Token
->Packet
= Packet
;
131 Token
->Context
= Context
;
132 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
133 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
135 MnpToken
= &(Token
->MnpToken
);
136 MnpToken
->Status
= EFI_NOT_READY
;
138 Status
= gBS
->CreateEvent (
146 if (EFI_ERROR (Status
)) {
151 MnpTxData
= &Token
->MnpTxData
;
152 MnpToken
->Packet
.TxData
= MnpTxData
;
154 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
155 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
156 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
157 MnpTxData
->DataLength
= Packet
->TotalSize
;
158 MnpTxData
->HeaderLength
= 0;
160 Count
= Packet
->BlockOpNum
;
162 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
163 MnpTxData
->FragmentCount
= (UINT16
)Count
;
170 Free the link layer transmit token. It will close the event
171 then free the memory used.
173 @param Token Token to free
181 IN IP4_LINK_TX_TOKEN
*Token
184 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
186 gBS
->CloseEvent (Token
->MnpToken
.Event
);
192 Create an IP_ARP_QUE structure to request ARP service.
194 @param Interface The interface to send ARP from.
195 @param DestIp The destination IP (host byte order) to request MAC
198 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
204 IN IP4_INTERFACE
*Interface
,
211 ArpQue
= NetAllocatePool (sizeof (IP4_ARP_QUE
));
213 if (ArpQue
== NULL
) {
217 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
218 NetListInit (&ArpQue
->Link
);
220 NetListInit (&ArpQue
->Frames
);
221 ArpQue
->Interface
= Interface
;
223 Status
= gBS
->CreateEvent (
231 if (EFI_ERROR (Status
)) {
232 NetFreePool (ArpQue
);
237 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
244 Remove all the transmit requests queued on the ARP queue, then free it.
246 @param ArpQue Arp queue to free
247 @param IoStatus The transmit status returned to transmit requests'
256 IN IP4_ARP_QUE
*ArpQue
,
257 IN EFI_STATUS IoStatus
260 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
263 // Remove all the frame waiting the ARP response
265 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
267 gBS
->CloseEvent (ArpQue
->OnResolved
);
268 NetFreePool (ArpQue
);
273 Create a link layer receive token to wrap the receive request
275 @param Interface The interface to receive from
276 @param IpInstance The instance that request the receive (NULL for IP4
278 @param CallBack Call back function to execute when finished.
279 @param Context Opaque parameters to the callback
281 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
286 Ip4CreateLinkRxToken (
287 IN IP4_INTERFACE
*Interface
,
288 IN IP4_PROTOCOL
*IpInstance
,
289 IN IP4_FRAME_CALLBACK CallBack
,
293 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
294 IP4_LINK_RX_TOKEN
*Token
;
297 Token
= NetAllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
302 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
303 Token
->Interface
= Interface
;
304 Token
->IpInstance
= IpInstance
;
305 Token
->CallBack
= CallBack
;
306 Token
->Context
= Context
;
308 MnpToken
= &Token
->MnpToken
;
309 MnpToken
->Status
= EFI_NOT_READY
;
311 Status
= gBS
->CreateEvent (
319 if (EFI_ERROR (Status
)) {
324 MnpToken
->Packet
.RxData
= NULL
;
330 Free the link layer request token. It will close the event
331 then free the memory used.
333 @param Token Request token to free
340 Ip4FreeFrameRxToken (
341 IN IP4_LINK_RX_TOKEN
*Token
345 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
347 gBS
->CloseEvent (Token
->MnpToken
.Event
);
353 Remove all the frames on the ARP queue that pass the FrameToCancel,
354 that is, either FrameToCancel is NULL or it returns true for the frame.
356 @param ArpQue ARP frame to remove the frames from.
357 @param IoStatus The status returned to the cancelled frames'
359 @param FrameToCancel Function to select which frame to cancel.
360 @param Context Opaque parameter to the FrameToCancel.
368 IN IP4_ARP_QUE
*ArpQue
,
369 IN EFI_STATUS IoStatus
,
370 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
374 NET_LIST_ENTRY
*Entry
;
375 NET_LIST_ENTRY
*Next
;
376 IP4_LINK_TX_TOKEN
*Token
;
378 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
379 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
381 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
382 NetListRemoveEntry (Entry
);
384 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
385 Ip4FreeLinkTxToken (Token
);
392 Remove all the frames on the interface that pass the FrameToCancel,
393 either queued on ARP queues or that have already been delivered to
394 MNP and not yet recycled.
396 @param Interface Interface to remove the frames from
397 @param IoStatus The transmit status returned to the frames'
399 @param FrameToCancel Function to select the frame to cancel, NULL to
401 @param Context Opaque parameters passed to FrameToCancel
408 IN IP4_INTERFACE
*Interface
,
409 IN EFI_STATUS IoStatus
,
410 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
414 NET_LIST_ENTRY
*Entry
;
415 NET_LIST_ENTRY
*Next
;
417 IP4_LINK_TX_TOKEN
*Token
;
420 // Cancel all the pending frames on ARP requests
422 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
423 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
425 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
427 if (NetListIsEmpty (&ArpQue
->Frames
)) {
428 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
433 // Cancel all the frames that have been delivered to MNP
434 // but not yet recycled.
436 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
437 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
439 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
440 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
447 Create an IP4_INTERFACE. Delay the creation of ARP instance until
448 the interface is configured.
450 @param Mnp The shared MNP child of this IP4 service binding
452 @param Controller The controller this IP4 service binding instance
453 is installed. Most like the UNDI handle.
454 @param ImageHandle This driver's image handle
456 @return Point to the created IP4_INTERFACE, otherwise NULL.
461 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
462 IN EFI_HANDLE Controller
,
463 IN EFI_HANDLE ImageHandle
466 IP4_INTERFACE
*Interface
;
467 EFI_SIMPLE_NETWORK_MODE SnpMode
;
469 Interface
= NetAllocatePool (sizeof (IP4_INTERFACE
));
471 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
475 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
476 NetListInit (&Interface
->Link
);
477 Interface
->RefCnt
= 1;
479 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
480 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
481 Interface
->Configured
= FALSE
;
483 Interface
->Controller
= Controller
;
484 Interface
->Image
= ImageHandle
;
485 Interface
->Mnp
= Mnp
;
486 Interface
->Arp
= NULL
;
487 Interface
->ArpHandle
= NULL
;
489 NetListInit (&Interface
->ArpQues
);
490 NetListInit (&Interface
->SentFrames
);
492 Interface
->RecvRequest
= NULL
;
495 // Get the interface's Mac address and broadcast mac address from SNP
497 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
498 NetFreePool (Interface
);
502 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
503 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
504 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
506 NetListInit (&Interface
->IpInstances
);
507 Interface
->PromiscRecv
= FALSE
;
514 Set the interface's address, create and configure
515 the ARP child if necessary.
517 @param Interface The interface to set the address
518 @param IpAddr The interface's IP address
519 @param SubnetMask The interface's netmask
521 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
522 and a ARP is created for it.
523 @retval Others Failed to set the interface's address.
528 IN IP4_INTERFACE
*Interface
,
530 IN IP4_ADDR SubnetMask
533 EFI_ARP_CONFIG_DATA ArpConfig
;
539 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
541 ASSERT (!Interface
->Configured
);
544 // Set the ip/netmask, then compute the subnet broadcast
545 // and network broadcast for easy access. When computing
546 // nework broadcast, the subnet mask is most like longer
547 // than the default netmask (not subneted) as defined in
548 // RFC793. If that isn't the case, we are aggregating the
549 // networks, use the subnet's mask instead.
551 Interface
->Ip
= IpAddr
;
552 Interface
->SubnetMask
= SubnetMask
;
553 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
555 Type
= NetGetIpClass (IpAddr
);
556 Len
= NetGetMaskLength (SubnetMask
);
557 Netmask
= mIp4AllMasks
[MIN (Len
, Type
<< 3)];
558 Interface
->NetBrdcast
= (IpAddr
| ~Netmask
);
561 // If the address is NOT all zero, create then configure an ARP child.
562 // Pay attention: DHCP configures its station address as 0.0.0.0/0
564 Interface
->Arp
= NULL
;
565 Interface
->ArpHandle
= NULL
;
567 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
568 Status
= NetLibCreateServiceChild (
569 Interface
->Controller
,
571 &gEfiArpServiceBindingProtocolGuid
,
572 &Interface
->ArpHandle
575 if (EFI_ERROR (Status
)) {
579 Status
= gBS
->OpenProtocol (
580 Interface
->ArpHandle
,
581 &gEfiArpProtocolGuid
,
582 (VOID
**) &Interface
->Arp
,
584 Interface
->Controller
,
585 EFI_OPEN_PROTOCOL_BY_DRIVER
588 if (EFI_ERROR (Status
)) {
592 IpAddr
= HTONL (IpAddr
);
593 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
594 ArpConfig
.SwAddressLength
= 4;
595 ArpConfig
.StationAddress
= &IpAddr
;
596 ArpConfig
.EntryTimeOut
= 0;
597 ArpConfig
.RetryCount
= 0;
598 ArpConfig
.RetryTimeOut
= 0;
600 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
602 if (EFI_ERROR (Status
)) {
604 Interface
->ArpHandle
,
605 &gEfiArpProtocolGuid
,
607 Interface
->Controller
614 Interface
->Configured
= TRUE
;
618 NetLibDestroyServiceChild (
619 Interface
->Controller
,
621 &gEfiArpServiceBindingProtocolGuid
,
622 &Interface
->ArpHandle
630 Fileter function to cancel all the frame related to an IP instance.
632 @param Frame The transmit request to test whether to cancel
633 @param Context The context which is the Ip instance that issued
636 @retval TRUE The frame belongs to this instance and is to be
638 @retval FALSE The frame doesn't belong to this instance.
643 Ip4CancelInstanceFrame (
644 IN IP4_LINK_TX_TOKEN
*Frame
,
648 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
658 If there is a pending receive request, cancel it. Don't call
659 the receive request's callback because this function can be only
660 called if the instance or driver is tearing itself down. It
661 doesn't make sense to call it back. But it is necessary to call
662 the transmit token's callback to give it a chance to free the
663 packet and update the upper layer's transmit request status, say
666 @param Interface The interface used by the IpInstance
673 IN IP4_INTERFACE
*Interface
677 IP4_LINK_RX_TOKEN
*Token
;
679 if ((Token
= Interface
->RecvRequest
) != NULL
) {
680 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
682 Interface
->RecvRequest
= NULL
;
683 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
685 NET_RESTORE_TPL (OldTpl
);
691 Free the interface used by IpInstance. All the IP instance with
692 the same Ip/Netmask pair share the same interface. It is reference
693 counted. All the frames haven't been sent will be cancelled.
694 Because the IpInstance is optional, the caller must remove
695 IpInstance from the interface's instance list itself.
697 @param Interface The interface used by the IpInstance
698 @param IpInstance The Ip instance that free the interface. NULL if
699 the Ip driver is releasing the default interface.
701 @retval EFI_SUCCESS The interface use IpInstance is freed.
706 IN IP4_INTERFACE
*Interface
,
707 IN IP4_PROTOCOL
*IpInstance OPTIONAL
710 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
711 ASSERT (Interface
->RefCnt
> 0);
714 // Remove all the pending transmit token related to this IP instance.
716 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
718 if (--Interface
->RefCnt
> 0) {
723 // Destory the interface if this is the last IP instance that
724 // has the address. Remove all the system transmitted packets
725 // from this interface, cancel the receive request if there is
726 // one, and destory the ARP requests.
728 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
729 Ip4CancelReceive (Interface
);
731 ASSERT (NetListIsEmpty (&Interface
->IpInstances
));
732 ASSERT (NetListIsEmpty (&Interface
->ArpQues
));
733 ASSERT (NetListIsEmpty (&Interface
->SentFrames
));
735 if (Interface
->Arp
!= NULL
) {
737 Interface
->ArpHandle
,
738 &gEfiArpProtocolGuid
,
740 Interface
->Controller
743 NetLibDestroyServiceChild (
744 Interface
->Controller
,
746 &gEfiArpServiceBindingProtocolGuid
,
751 NetListRemoveEntry (&Interface
->Link
);
752 NetFreePool (Interface
);
759 Callback function when ARP request are finished. It will cancelled
760 all the queued frame if the ARP requests failed. Or transmit them
761 if the request succeed.
763 @param Context The context of the callback, a point to the ARP
772 Ip4OnArpResolvedDpc (
776 NET_LIST_ENTRY
*Entry
;
777 NET_LIST_ENTRY
*Next
;
779 IP4_INTERFACE
*Interface
;
780 IP4_LINK_TX_TOKEN
*Token
;
783 ArpQue
= (IP4_ARP_QUE
*) Context
;
784 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
786 NetListRemoveEntry (&ArpQue
->Link
);
789 // ARP resolve failed for some reason. Release all the frame
790 // and ARP queue itself. Ip4FreeArpQue will call the frame's
793 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
794 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
800 // ARP resolve succeeded, Transmit all the frame. Release the ARP
801 // queue. It isn't necessary for us to cache the ARP binding because
802 // we always check the ARP cache first before transmit.
804 Interface
= ArpQue
->Interface
;
806 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
807 NetListRemoveEntry (Entry
);
809 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
810 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
813 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
814 // may be called before Mnp->Transmit returns which will remove this tx
815 // token from the SentFrames list. Remove it from the list if the returned
816 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
817 // FrameSentDpc won't be queued.
819 NetListInsertTail (&Interface
->SentFrames
, &Token
->Link
);
821 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
822 if (EFI_ERROR (Status
)) {
823 NetListRemoveEntry (Entry
);
824 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
826 Ip4FreeLinkTxToken (Token
);
831 Ip4FreeArpQue (ArpQue
, EFI_SUCCESS
);
845 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
849 Event - The Arp request event
850 Context - The context of the callback, a point to the ARP queue
859 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
861 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
867 Callback funtion when frame transmission is finished. It will
868 call the frame owner's callback function to tell it the result.
870 @param Context Context which is point to the token.
882 IP4_LINK_TX_TOKEN
*Token
;
884 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
885 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
887 NetListRemoveEntry (&Token
->Link
);
892 Token
->MnpToken
.Status
,
897 Ip4FreeLinkTxToken (Token
);
911 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
915 Event - The transmit token's event
916 Context - Context which is point to the token.
925 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
927 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
933 Send a frame from the interface. If the next hop is broadcast or
934 multicast address, it is transmitted immediately. If the next hop
935 is a unicast, it will consult ARP to resolve the NextHop's MAC.
936 If some error happened, the CallBack won't be called. So, the caller
937 must test the return value, and take action when there is an error.
939 @param Interface The interface to send the frame from
940 @param IpInstance The IP child that request the transmission. NULL
941 if it is the IP4 driver itself.
942 @param Packet The packet to transmit.
943 @param NextHop The immediate destination to transmit the packet
945 @param CallBack Function to call back when transmit finished.
946 @param Context Opaque parameter to the call back.
948 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
949 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
950 @retval EFI_SUCCESS The packet is successfully transmitted.
955 IN IP4_INTERFACE
*Interface
,
956 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
959 IN IP4_FRAME_CALLBACK CallBack
,
963 IP4_LINK_TX_TOKEN
*Token
;
964 NET_LIST_ENTRY
*Entry
;
966 EFI_ARP_PROTOCOL
*Arp
;
969 ASSERT (Interface
->Configured
);
971 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
);
974 return EFI_OUT_OF_RESOURCES
;
978 // Get the destination MAC address for multicast and broadcasts.
979 // Don't depend on ARP to solve the address since there maybe no
980 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
981 // all the broadcasts.
983 if (NextHop
== IP4_ALLONE_ADDRESS
) {
984 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
987 } else if (IP4_IS_MULTICAST (NextHop
)) {
989 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
991 if (EFI_ERROR (Status
)) {
999 // Can only send out multicast/broadcast if the IP address is zero
1001 if ((Arp
= Interface
->Arp
) == NULL
) {
1002 Status
= EFI_NO_MAPPING
;
1007 // First check whether this binding is in the ARP cache.
1009 NextHop
= HTONL (NextHop
);
1010 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1012 if (Status
== EFI_SUCCESS
) {
1015 } else if (Status
!= EFI_NOT_READY
) {
1020 // Have to do asynchronous ARP resolution. First check
1021 // whether there is already a pending request.
1025 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1026 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1028 if (ArpQue
->Ip
== NextHop
) {
1034 // Found a pending ARP request, enqueue the frame then return
1036 if (Entry
!= &Interface
->ArpQues
) {
1037 NetListInsertTail (&ArpQue
->Frames
, &Token
->Link
);
1042 // First frame to NextHop, issue an asynchronous ARP requests
1044 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1046 if (ArpQue
== NULL
) {
1047 Status
= EFI_OUT_OF_RESOURCES
;
1051 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1053 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1054 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1058 NetListInsertHead (&ArpQue
->Frames
, &Token
->Link
);
1059 NetListInsertHead (&Interface
->ArpQues
, &ArpQue
->Link
);
1064 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1065 // Remove it if the returned status is not EFI_SUCCESS.
1067 NetListInsertTail (&Interface
->SentFrames
, &Token
->Link
);
1068 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1069 if (EFI_ERROR (Status
)) {
1070 NetListRemoveEntry (&Interface
->SentFrames
);
1077 Ip4FreeLinkTxToken (Token
);
1083 Call back function when the received packet is freed.
1084 Check Ip4OnFrameReceived for information.
1086 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1097 IP4_LINK_RX_TOKEN
*Frame
;
1099 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1100 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1102 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1103 Ip4FreeFrameRxToken (Frame
);
1108 Received a frame from MNP, wrap it in net buffer then deliver
1109 it to IP's input function. The ownship of the packet also
1110 transferred to IP. When Ip is finished with this packet, it
1111 will call NetbufFree to release the packet, NetbufFree will
1112 again call the Ip4RecycleFrame to signal MNP's event and free
1115 @param Context Context for the callback.
1123 Ip4OnFrameReceivedDpc (
1127 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1128 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1129 IP4_LINK_RX_TOKEN
*Token
;
1130 NET_FRAGMENT Netfrag
;
1134 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1135 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1138 // First clear the interface's receive request in case the
1139 // caller wants to call Ip4ReceiveFrame in the callback.
1141 Token
->Interface
->RecvRequest
= NULL
;
1143 MnpToken
= &Token
->MnpToken
;
1144 MnpRxData
= MnpToken
->Packet
.RxData
;
1146 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1147 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1148 Ip4FreeFrameRxToken (Token
);
1154 // Wrap the frame in a net buffer then deliever it to IP input.
1155 // IP will reassemble the packet, and deliver it to upper layer
1157 Netfrag
.Len
= MnpRxData
->DataLength
;
1158 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1160 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1162 if (Packet
== NULL
) {
1163 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1165 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1166 Ip4FreeFrameRxToken (Token
);
1171 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1172 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1173 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1175 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1181 Ip4OnFrameReceived (
1187 Routine Description:
1189 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1193 Event - The receive event delivered to MNP for receive.
1194 Context - Context for the callback.
1203 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1205 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1210 Request to receive the packet from the interface.
1212 @param Interface The interface to receive the frames from
1213 @param IpInstance The instance that requests the receive. NULL for
1215 @param CallBack Function to call when receive finished.
1216 @param Context Opaque parameter to the callback
1218 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1219 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive
1220 @retval EFI_SUCCESS The recieve request has been started.
1225 IN IP4_INTERFACE
*Interface
,
1226 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
1227 IN IP4_FRAME_CALLBACK CallBack
,
1231 IP4_LINK_RX_TOKEN
*Token
;
1234 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1236 if (Interface
->RecvRequest
!= NULL
) {
1237 return EFI_ALREADY_STARTED
;
1240 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1242 if (Token
== NULL
) {
1243 return EFI_OUT_OF_RESOURCES
;
1246 Interface
->RecvRequest
= Token
;
1247 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1248 if (EFI_ERROR (Status
)) {
1249 Interface
->RecvRequest
= NULL
;
1250 Ip4FreeFrameRxToken (Token
);