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 EFI_MAC_ADDRESS mZeroMacAddress
;
60 Ip4OnFrameReceivedDpc (
73 IN IP4_ARP_QUE
*ArpQue
,
74 IN EFI_STATUS IoStatus
,
75 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
81 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
83 @param Interface The interface to send out to.
84 @param IpInstance The IpInstance that transmit the packet. NULL if
85 the packet is sent by the IP4 driver itself.
86 @param Packet The packet to transmit
87 @param CallBack Call back function to execute if transmission
89 @param Context Opaque parameter to the call back.
91 @return The wrapped token if succeed or NULL
96 IN IP4_INTERFACE
*Interface
,
97 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
99 IN IP4_FRAME_CALLBACK CallBack
,
103 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
104 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
105 IP4_LINK_TX_TOKEN
*Token
;
109 Token
= AllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
110 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
116 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
117 InitializeListHead (&Token
->Link
);
119 Token
->Interface
= Interface
;
120 Token
->IpInstance
= IpInstance
;
121 Token
->CallBack
= CallBack
;
122 Token
->Packet
= Packet
;
123 Token
->Context
= Context
;
124 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
125 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
127 MnpToken
= &(Token
->MnpToken
);
128 MnpToken
->Status
= EFI_NOT_READY
;
130 Status
= gBS
->CreateEvent (
138 if (EFI_ERROR (Status
)) {
139 gBS
->FreePool (Token
);
143 MnpTxData
= &Token
->MnpTxData
;
144 MnpToken
->Packet
.TxData
= MnpTxData
;
146 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
147 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
148 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
149 MnpTxData
->DataLength
= Packet
->TotalSize
;
150 MnpTxData
->HeaderLength
= 0;
152 Count
= Packet
->BlockOpNum
;
154 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
155 MnpTxData
->FragmentCount
= (UINT16
)Count
;
162 Free the link layer transmit token. It will close the event
163 then free the memory used.
165 @param Token Token to free
172 IN IP4_LINK_TX_TOKEN
*Token
175 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
177 gBS
->CloseEvent (Token
->MnpToken
.Event
);
178 gBS
->FreePool (Token
);
183 Create an IP_ARP_QUE structure to request ARP service.
185 @param Interface The interface to send ARP from.
186 @param DestIp The destination IP (host byte order) to request MAC
189 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
194 IN IP4_INTERFACE
*Interface
,
201 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
203 if (ArpQue
== NULL
) {
207 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
208 InitializeListHead (&ArpQue
->Link
);
210 InitializeListHead (&ArpQue
->Frames
);
211 ArpQue
->Interface
= Interface
;
213 Status
= gBS
->CreateEvent (
221 if (EFI_ERROR (Status
)) {
222 gBS
->FreePool (ArpQue
);
227 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
234 Remove all the transmit requests queued on the ARP queue, then free it.
236 @param ArpQue Arp queue to free
237 @param IoStatus The transmit status returned to transmit requests'
245 IN IP4_ARP_QUE
*ArpQue
,
246 IN EFI_STATUS IoStatus
249 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
252 // Remove all the frame waiting the ARP response
254 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
256 gBS
->CloseEvent (ArpQue
->OnResolved
);
257 gBS
->FreePool (ArpQue
);
262 Create a link layer receive token to wrap the receive request
264 @param Interface The interface to receive from
265 @param IpInstance The instance that request the receive (NULL for IP4
267 @param CallBack Call back function to execute when finished.
268 @param Context Opaque parameters to the callback
270 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
274 Ip4CreateLinkRxToken (
275 IN IP4_INTERFACE
*Interface
,
276 IN IP4_PROTOCOL
*IpInstance
,
277 IN IP4_FRAME_CALLBACK CallBack
,
281 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
282 IP4_LINK_RX_TOKEN
*Token
;
285 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
290 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
291 Token
->Interface
= Interface
;
292 Token
->IpInstance
= IpInstance
;
293 Token
->CallBack
= CallBack
;
294 Token
->Context
= Context
;
296 MnpToken
= &Token
->MnpToken
;
297 MnpToken
->Status
= EFI_NOT_READY
;
299 Status
= gBS
->CreateEvent (
307 if (EFI_ERROR (Status
)) {
308 gBS
->FreePool (Token
);
312 MnpToken
->Packet
.RxData
= NULL
;
318 Free the link layer request token. It will close the event
319 then free the memory used.
321 @param Token Request token to free
327 Ip4FreeFrameRxToken (
328 IN IP4_LINK_RX_TOKEN
*Token
332 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
334 gBS
->CloseEvent (Token
->MnpToken
.Event
);
335 gBS
->FreePool (Token
);
340 Remove all the frames on the ARP queue that pass the FrameToCancel,
341 that is, either FrameToCancel is NULL or it returns true for the frame.
343 @param ArpQue ARP frame to remove the frames from.
344 @param IoStatus The status returned to the cancelled frames'
346 @param FrameToCancel Function to select which frame to cancel.
347 @param Context Opaque parameter to the FrameToCancel.
354 IN IP4_ARP_QUE
*ArpQue
,
355 IN EFI_STATUS IoStatus
,
356 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
362 IP4_LINK_TX_TOKEN
*Token
;
364 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
365 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
367 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
368 RemoveEntryList (Entry
);
370 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
371 Ip4FreeLinkTxToken (Token
);
378 Remove all the frames on the interface that pass the FrameToCancel,
379 either queued on ARP queues or that have already been delivered to
380 MNP and not yet recycled.
382 @param Interface Interface to remove the frames from
383 @param IoStatus The transmit status returned to the frames'
385 @param FrameToCancel Function to select the frame to cancel, NULL to
387 @param Context Opaque parameters passed to FrameToCancel
394 IN IP4_INTERFACE
*Interface
,
395 IN EFI_STATUS IoStatus
,
396 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
403 IP4_LINK_TX_TOKEN
*Token
;
406 // Cancel all the pending frames on ARP requests
408 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
409 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
411 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
413 if (IsListEmpty (&ArpQue
->Frames
)) {
414 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
419 // Cancel all the frames that have been delivered to MNP
420 // but not yet recycled.
422 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
423 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
425 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
426 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
433 Create an IP4_INTERFACE. Delay the creation of ARP instance until
434 the interface is configured.
436 @param Mnp The shared MNP child of this IP4 service binding
438 @param Controller The controller this IP4 service binding instance
439 is installed. Most like the UNDI handle.
440 @param ImageHandle This driver's image handle
442 @return Point to the created IP4_INTERFACE, otherwise NULL.
447 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
448 IN EFI_HANDLE Controller
,
449 IN EFI_HANDLE ImageHandle
452 IP4_INTERFACE
*Interface
;
453 EFI_SIMPLE_NETWORK_MODE SnpMode
;
455 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
457 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
461 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
462 InitializeListHead (&Interface
->Link
);
463 Interface
->RefCnt
= 1;
465 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
466 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
467 Interface
->Configured
= FALSE
;
469 Interface
->Controller
= Controller
;
470 Interface
->Image
= ImageHandle
;
471 Interface
->Mnp
= Mnp
;
472 Interface
->Arp
= NULL
;
473 Interface
->ArpHandle
= NULL
;
475 InitializeListHead (&Interface
->ArpQues
);
476 InitializeListHead (&Interface
->SentFrames
);
478 Interface
->RecvRequest
= NULL
;
481 // Get the interface's Mac address and broadcast mac address from SNP
483 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
484 gBS
->FreePool (Interface
);
488 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
489 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
490 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
492 InitializeListHead (&Interface
->IpInstances
);
493 Interface
->PromiscRecv
= FALSE
;
500 Set the interface's address, create and configure
501 the ARP child if necessary.
503 @param Interface The interface to set the address
504 @param IpAddr The interface's IP address
505 @param SubnetMask The interface's netmask
507 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
508 and a ARP is created for it.
509 @retval Others Failed to set the interface's address.
514 IN OUT IP4_INTERFACE
*Interface
,
516 IN IP4_ADDR SubnetMask
519 EFI_ARP_CONFIG_DATA ArpConfig
;
525 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
527 ASSERT (!Interface
->Configured
);
530 // Set the ip/netmask, then compute the subnet broadcast
531 // and network broadcast for easy access. When computing
532 // nework broadcast, the subnet mask is most like longer
533 // than the default netmask (not subneted) as defined in
534 // RFC793. If that isn't the case, we are aggregating the
535 // networks, use the subnet's mask instead.
537 Interface
->Ip
= IpAddr
;
538 Interface
->SubnetMask
= SubnetMask
;
539 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
541 Type
= NetGetIpClass (IpAddr
);
542 Len
= NetGetMaskLength (SubnetMask
);
543 Netmask
= gIp4AllMasks
[MIN (Len
, Type
<< 3)];
544 Interface
->NetBrdcast
= (IpAddr
| ~Netmask
);
547 // If the address is NOT all zero, create then configure an ARP child.
548 // Pay attention: DHCP configures its station address as 0.0.0.0/0
550 Interface
->Arp
= NULL
;
551 Interface
->ArpHandle
= NULL
;
553 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
554 Status
= NetLibCreateServiceChild (
555 Interface
->Controller
,
557 &gEfiArpServiceBindingProtocolGuid
,
558 &Interface
->ArpHandle
561 if (EFI_ERROR (Status
)) {
565 Status
= gBS
->OpenProtocol (
566 Interface
->ArpHandle
,
567 &gEfiArpProtocolGuid
,
568 (VOID
**) &Interface
->Arp
,
570 Interface
->Controller
,
571 EFI_OPEN_PROTOCOL_BY_DRIVER
574 if (EFI_ERROR (Status
)) {
578 IpAddr
= HTONL (IpAddr
);
579 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
580 ArpConfig
.SwAddressLength
= 4;
581 ArpConfig
.StationAddress
= &IpAddr
;
582 ArpConfig
.EntryTimeOut
= 0;
583 ArpConfig
.RetryCount
= 0;
584 ArpConfig
.RetryTimeOut
= 0;
586 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
588 if (EFI_ERROR (Status
)) {
590 Interface
->ArpHandle
,
591 &gEfiArpProtocolGuid
,
593 Interface
->Controller
600 Interface
->Configured
= TRUE
;
604 NetLibDestroyServiceChild (
605 Interface
->Controller
,
607 &gEfiArpServiceBindingProtocolGuid
,
608 &Interface
->ArpHandle
616 Filter function to cancel all the frame related to an IP instance.
618 @param Frame The transmit request to test whether to cancel
619 @param Context The context which is the Ip instance that issued
622 @retval TRUE The frame belongs to this instance and is to be
624 @retval FALSE The frame doesn't belong to this instance.
628 Ip4CancelInstanceFrame (
629 IN IP4_LINK_TX_TOKEN
*Frame
,
633 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
643 If there is a pending receive request, cancel it. Don't call
644 the receive request's callback because this function can be only
645 called if the instance or driver is tearing itself down. It
646 doesn't make sense to call it back. But it is necessary to call
647 the transmit token's callback to give it a chance to free the
648 packet and update the upper layer's transmit request status, say
651 @param Interface The interface used by the IpInstance
658 IN IP4_INTERFACE
*Interface
662 IP4_LINK_RX_TOKEN
*Token
;
664 if ((Token
= Interface
->RecvRequest
) != NULL
) {
665 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
667 Interface
->RecvRequest
= NULL
;
668 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
670 gBS
->RestoreTPL (OldTpl
);
676 Free the interface used by IpInstance. All the IP instance with
677 the same Ip/Netmask pair share the same interface. It is reference
678 counted. All the frames haven't been sent will be cancelled.
679 Because the IpInstance is optional, the caller must remove
680 IpInstance from the interface's instance list itself.
682 @param Interface The interface used by the IpInstance
683 @param IpInstance The Ip instance that free the interface. NULL if
684 the Ip driver is releasing the default interface.
686 @retval EFI_SUCCESS The interface use IpInstance is freed.
691 IN IP4_INTERFACE
*Interface
,
692 IN IP4_PROTOCOL
*IpInstance OPTIONAL
695 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
696 ASSERT (Interface
->RefCnt
> 0);
699 // Remove all the pending transmit token related to this IP instance.
701 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
703 if (--Interface
->RefCnt
> 0) {
708 // Destory the interface if this is the last IP instance that
709 // has the address. Remove all the system transmitted packets
710 // from this interface, cancel the receive request if there is
711 // one, and destory the ARP requests.
713 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
714 Ip4CancelReceive (Interface
);
716 ASSERT (IsListEmpty (&Interface
->IpInstances
));
717 ASSERT (IsListEmpty (&Interface
->ArpQues
));
718 ASSERT (IsListEmpty (&Interface
->SentFrames
));
720 if (Interface
->Arp
!= NULL
) {
722 Interface
->ArpHandle
,
723 &gEfiArpProtocolGuid
,
725 Interface
->Controller
728 NetLibDestroyServiceChild (
729 Interface
->Controller
,
731 &gEfiArpServiceBindingProtocolGuid
,
736 RemoveEntryList (&Interface
->Link
);
737 gBS
->FreePool (Interface
);
744 Callback function when ARP request are finished. It will cancelled
745 all the queued frame if the ARP requests failed. Or transmit them
746 if the request succeed.
748 @param Context The context of the callback, a point to the ARP
756 Ip4OnArpResolvedDpc (
763 IP4_INTERFACE
*Interface
;
764 IP4_LINK_TX_TOKEN
*Token
;
767 ArpQue
= (IP4_ARP_QUE
*) Context
;
768 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
770 RemoveEntryList (&ArpQue
->Link
);
773 // ARP resolve failed for some reason. Release all the frame
774 // and ARP queue itself. Ip4FreeArpQue will call the frame's
777 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
778 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
784 // ARP resolve succeeded, Transmit all the frame. Release the ARP
785 // queue. It isn't necessary for us to cache the ARP binding because
786 // we always check the ARP cache first before transmit.
788 Interface
= ArpQue
->Interface
;
790 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
791 RemoveEntryList (Entry
);
793 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
794 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
797 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
798 // may be called before Mnp->Transmit returns which will remove this tx
799 // token from the SentFrames list. Remove it from the list if the returned
800 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
801 // FrameSentDpc won't be queued.
803 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
805 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
806 if (EFI_ERROR (Status
)) {
807 RemoveEntryList (Entry
);
808 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
810 Ip4FreeLinkTxToken (Token
);
815 Ip4FreeArpQue (ArpQue
, EFI_SUCCESS
);
819 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
821 @param Event The Arp request event.
822 @param Context The context of the callback, a point to the ARP
836 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
838 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
844 Callback funtion when frame transmission is finished. It will
845 call the frame owner's callback function to tell it the result.
847 @param Context Context which is point to the token.
858 IP4_LINK_TX_TOKEN
*Token
;
860 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
861 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
863 RemoveEntryList (&Token
->Link
);
868 Token
->MnpToken
.Status
,
873 Ip4FreeLinkTxToken (Token
);
877 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
879 @param Event The transmit token's event.
880 @param Context Context which is point to the token.
893 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
895 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
901 Send a frame from the interface. If the next hop is broadcast or
902 multicast address, it is transmitted immediately. If the next hop
903 is a unicast, it will consult ARP to resolve the NextHop's MAC.
904 If some error happened, the CallBack won't be called. So, the caller
905 must test the return value, and take action when there is an error.
907 @param Interface The interface to send the frame from
908 @param IpInstance The IP child that request the transmission. NULL
909 if it is the IP4 driver itself.
910 @param Packet The packet to transmit.
911 @param NextHop The immediate destination to transmit the packet
913 @param CallBack Function to call back when transmit finished.
914 @param Context Opaque parameter to the call back.
916 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
917 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
918 @retval EFI_SUCCESS The packet is successfully transmitted.
919 @retval other Other error occurs.
924 IN IP4_INTERFACE
*Interface
,
925 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
928 IN IP4_FRAME_CALLBACK CallBack
,
932 IP4_LINK_TX_TOKEN
*Token
;
935 EFI_ARP_PROTOCOL
*Arp
;
938 ASSERT (Interface
->Configured
);
940 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
);
943 return EFI_OUT_OF_RESOURCES
;
947 // Get the destination MAC address for multicast and broadcasts.
948 // Don't depend on ARP to solve the address since there maybe no
949 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
950 // all the broadcasts.
952 if (NextHop
== IP4_ALLONE_ADDRESS
) {
953 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
956 } else if (IP4_IS_MULTICAST (NextHop
)) {
958 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
960 if (EFI_ERROR (Status
)) {
968 // Can only send out multicast/broadcast if the IP address is zero
970 if ((Arp
= Interface
->Arp
) == NULL
) {
971 Status
= EFI_NO_MAPPING
;
976 // First check whether this binding is in the ARP cache.
978 NextHop
= HTONL (NextHop
);
979 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
981 if (Status
== EFI_SUCCESS
) {
984 } else if (Status
!= EFI_NOT_READY
) {
989 // Have to do asynchronous ARP resolution. First check
990 // whether there is already a pending request.
994 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
995 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
997 if (ArpQue
->Ip
== NextHop
) {
1003 // Found a pending ARP request, enqueue the frame then return
1005 if (Entry
!= &Interface
->ArpQues
) {
1006 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1011 // First frame to NextHop, issue an asynchronous ARP requests
1013 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1015 if (ArpQue
== NULL
) {
1016 Status
= EFI_OUT_OF_RESOURCES
;
1020 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1022 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1023 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1027 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1028 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1033 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1034 // Remove it if the returned status is not EFI_SUCCESS.
1036 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1037 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1038 if (EFI_ERROR (Status
)) {
1039 RemoveEntryList (&Interface
->SentFrames
);
1046 Ip4FreeLinkTxToken (Token
);
1052 Call back function when the received packet is freed.
1053 Check Ip4OnFrameReceived for information.
1055 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1065 IP4_LINK_RX_TOKEN
*Frame
;
1067 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1068 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1070 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1071 Ip4FreeFrameRxToken (Frame
);
1076 Received a frame from MNP, wrap it in net buffer then deliver
1077 it to IP's input function. The ownship of the packet also
1078 transferred to IP. When Ip is finished with this packet, it
1079 will call NetbufFree to release the packet, NetbufFree will
1080 again call the Ip4RecycleFrame to signal MNP's event and free
1083 @param Context Context for the callback.
1090 Ip4OnFrameReceivedDpc (
1094 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1095 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1096 IP4_LINK_RX_TOKEN
*Token
;
1097 NET_FRAGMENT Netfrag
;
1101 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1102 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1105 // First clear the interface's receive request in case the
1106 // caller wants to call Ip4ReceiveFrame in the callback.
1108 Token
->Interface
->RecvRequest
= NULL
;
1110 MnpToken
= &Token
->MnpToken
;
1111 MnpRxData
= MnpToken
->Packet
.RxData
;
1113 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1114 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1115 Ip4FreeFrameRxToken (Token
);
1121 // Wrap the frame in a net buffer then deliever it to IP input.
1122 // IP will reassemble the packet, and deliver it to upper layer
1124 Netfrag
.Len
= MnpRxData
->DataLength
;
1125 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1127 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1129 if (Packet
== NULL
) {
1130 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1132 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1133 Ip4FreeFrameRxToken (Token
);
1138 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1139 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1140 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1142 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1147 Ip4OnFrameReceived (
1153 Routine Description:
1155 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1159 Event - The receive event delivered to MNP for receive.
1160 Context - Context for the callback.
1169 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1171 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1176 Request to receive the packet from the interface.
1178 @param Interface The interface to receive the frames from
1179 @param IpInstance The instance that requests the receive. NULL for
1181 @param CallBack Function to call when receive finished.
1182 @param Context Opaque parameter to the callback
1184 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1185 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive
1186 @retval EFI_SUCCESS The recieve request has been started.
1187 @retval other Other error occurs.
1192 IN IP4_INTERFACE
*Interface
,
1193 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
1194 IN IP4_FRAME_CALLBACK CallBack
,
1198 IP4_LINK_RX_TOKEN
*Token
;
1201 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1203 if (Interface
->RecvRequest
!= NULL
) {
1204 return EFI_ALREADY_STARTED
;
1207 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1209 if (Token
== NULL
) {
1210 return EFI_OUT_OF_RESOURCES
;
1213 Interface
->RecvRequest
= Token
;
1214 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1215 if (EFI_ERROR (Status
)) {
1216 Interface
->RecvRequest
= NULL
;
1217 Ip4FreeFrameRxToken (Token
);