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
;
33 Callback funtion when frame transmission is finished. It will
34 call the frame owner's callback function to tell it the result.
36 @param Context Context which is point to the token.
48 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
50 @param Event The transmit token's event.
51 @param Context Context which is point to the token.
64 Callback function when ARP request are finished. It will cancelled
65 all the queued frame if the ARP requests failed. Or transmit them
66 if the request succeed.
68 @param Context The context of the callback, a point to the ARP
81 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
83 @param Event The Arp request event.
84 @param Context The context of the callback, a point to the ARP
98 Received a frame from MNP, wrap it in net buffer then deliver
99 it to IP's input function. The ownship of the packet also
100 transferred to IP. When Ip is finished with this packet, it
101 will call NetbufFree to release the packet, NetbufFree will
102 again call the Ip4RecycleFrame to signal MNP's event and free
105 @param Context Context for the callback.
112 Ip4OnFrameReceivedDpc (
118 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
120 @param Event The receive event delivered to MNP for receive.
121 @param Context Context for the callback.
134 Remove all the frames on the ARP queue that pass the FrameToCancel,
135 that is, either FrameToCancel is NULL or it returns true for the frame.
137 @param ArpQue ARP frame to remove the frames from.
138 @param IoStatus The status returned to the cancelled frames'
140 @param FrameToCancel Function to select which frame to cancel.
141 @param Context Opaque parameter to the FrameToCancel.
148 IN IP4_ARP_QUE
*ArpQue
,
149 IN EFI_STATUS IoStatus
,
150 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
156 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
158 @param Interface The interface to send out to.
159 @param IpInstance The IpInstance that transmit the packet. NULL if
160 the packet is sent by the IP4 driver itself.
161 @param Packet The packet to transmit
162 @param CallBack Call back function to execute if transmission
164 @param Context Opaque parameter to the call back.
166 @return The wrapped token if succeed or NULL
171 IN IP4_INTERFACE
*Interface
,
172 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
174 IN IP4_FRAME_CALLBACK CallBack
,
178 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
179 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
180 IP4_LINK_TX_TOKEN
*Token
;
184 Token
= AllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
185 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
191 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
192 InitializeListHead (&Token
->Link
);
194 Token
->Interface
= Interface
;
195 Token
->IpInstance
= IpInstance
;
196 Token
->CallBack
= CallBack
;
197 Token
->Packet
= Packet
;
198 Token
->Context
= Context
;
199 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
200 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
202 MnpToken
= &(Token
->MnpToken
);
203 MnpToken
->Status
= EFI_NOT_READY
;
205 Status
= gBS
->CreateEvent (
213 if (EFI_ERROR (Status
)) {
214 gBS
->FreePool (Token
);
218 MnpTxData
= &Token
->MnpTxData
;
219 MnpToken
->Packet
.TxData
= MnpTxData
;
221 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
222 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
223 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
224 MnpTxData
->DataLength
= Packet
->TotalSize
;
225 MnpTxData
->HeaderLength
= 0;
227 Count
= Packet
->BlockOpNum
;
229 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
230 MnpTxData
->FragmentCount
= (UINT16
)Count
;
237 Free the link layer transmit token. It will close the event
238 then free the memory used.
240 @param Token Token to free
247 IN IP4_LINK_TX_TOKEN
*Token
250 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
252 gBS
->CloseEvent (Token
->MnpToken
.Event
);
253 gBS
->FreePool (Token
);
258 Create an IP_ARP_QUE structure to request ARP service.
260 @param Interface The interface to send ARP from.
261 @param DestIp The destination IP (host byte order) to request MAC
264 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
269 IN IP4_INTERFACE
*Interface
,
276 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
278 if (ArpQue
== NULL
) {
282 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
283 InitializeListHead (&ArpQue
->Link
);
285 InitializeListHead (&ArpQue
->Frames
);
286 ArpQue
->Interface
= Interface
;
288 Status
= gBS
->CreateEvent (
296 if (EFI_ERROR (Status
)) {
297 gBS
->FreePool (ArpQue
);
302 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
309 Remove all the transmit requests queued on the ARP queue, then free it.
311 @param ArpQue Arp queue to free
312 @param IoStatus The transmit status returned to transmit requests'
320 IN IP4_ARP_QUE
*ArpQue
,
321 IN EFI_STATUS IoStatus
324 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
327 // Remove all the frame waiting the ARP response
329 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
331 gBS
->CloseEvent (ArpQue
->OnResolved
);
332 gBS
->FreePool (ArpQue
);
337 Create a link layer receive token to wrap the receive request
339 @param Interface The interface to receive from
340 @param IpInstance The instance that request the receive (NULL for IP4
342 @param CallBack Call back function to execute when finished.
343 @param Context Opaque parameters to the callback
345 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
349 Ip4CreateLinkRxToken (
350 IN IP4_INTERFACE
*Interface
,
351 IN IP4_PROTOCOL
*IpInstance
,
352 IN IP4_FRAME_CALLBACK CallBack
,
356 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
357 IP4_LINK_RX_TOKEN
*Token
;
360 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
365 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
366 Token
->Interface
= Interface
;
367 Token
->IpInstance
= IpInstance
;
368 Token
->CallBack
= CallBack
;
369 Token
->Context
= Context
;
371 MnpToken
= &Token
->MnpToken
;
372 MnpToken
->Status
= EFI_NOT_READY
;
374 Status
= gBS
->CreateEvent (
382 if (EFI_ERROR (Status
)) {
383 gBS
->FreePool (Token
);
387 MnpToken
->Packet
.RxData
= NULL
;
393 Free the link layer request token. It will close the event
394 then free the memory used.
396 @param Token Request token to free
402 Ip4FreeFrameRxToken (
403 IN IP4_LINK_RX_TOKEN
*Token
407 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
409 gBS
->CloseEvent (Token
->MnpToken
.Event
);
410 gBS
->FreePool (Token
);
415 Remove all the frames on the ARP queue that pass the FrameToCancel,
416 that is, either FrameToCancel is NULL or it returns true for the frame.
418 @param ArpQue ARP frame to remove the frames from.
419 @param IoStatus The status returned to the cancelled frames'
421 @param FrameToCancel Function to select which frame to cancel.
422 @param Context Opaque parameter to the FrameToCancel.
429 IN IP4_ARP_QUE
*ArpQue
,
430 IN EFI_STATUS IoStatus
,
431 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
437 IP4_LINK_TX_TOKEN
*Token
;
439 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
440 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
442 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
443 RemoveEntryList (Entry
);
445 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
446 Ip4FreeLinkTxToken (Token
);
453 Remove all the frames on the interface that pass the FrameToCancel,
454 either queued on ARP queues or that have already been delivered to
455 MNP and not yet recycled.
457 @param Interface Interface to remove the frames from
458 @param IoStatus The transmit status returned to the frames'
460 @param FrameToCancel Function to select the frame to cancel, NULL to
462 @param Context Opaque parameters passed to FrameToCancel
469 IN IP4_INTERFACE
*Interface
,
470 IN EFI_STATUS IoStatus
,
471 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
478 IP4_LINK_TX_TOKEN
*Token
;
481 // Cancel all the pending frames on ARP requests
483 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
484 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
486 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
488 if (IsListEmpty (&ArpQue
->Frames
)) {
489 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
494 // Cancel all the frames that have been delivered to MNP
495 // but not yet recycled.
497 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
498 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
500 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
501 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
508 Create an IP4_INTERFACE. Delay the creation of ARP instance until
509 the interface is configured.
511 @param Mnp The shared MNP child of this IP4 service binding
513 @param Controller The controller this IP4 service binding instance
514 is installed. Most like the UNDI handle.
515 @param ImageHandle This driver's image handle
517 @return Point to the created IP4_INTERFACE, otherwise NULL.
522 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
523 IN EFI_HANDLE Controller
,
524 IN EFI_HANDLE ImageHandle
527 IP4_INTERFACE
*Interface
;
528 EFI_SIMPLE_NETWORK_MODE SnpMode
;
530 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
532 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
536 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
537 InitializeListHead (&Interface
->Link
);
538 Interface
->RefCnt
= 1;
540 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
541 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
542 Interface
->Configured
= FALSE
;
544 Interface
->Controller
= Controller
;
545 Interface
->Image
= ImageHandle
;
546 Interface
->Mnp
= Mnp
;
547 Interface
->Arp
= NULL
;
548 Interface
->ArpHandle
= NULL
;
550 InitializeListHead (&Interface
->ArpQues
);
551 InitializeListHead (&Interface
->SentFrames
);
553 Interface
->RecvRequest
= NULL
;
556 // Get the interface's Mac address and broadcast mac address from SNP
558 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
559 gBS
->FreePool (Interface
);
563 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
564 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
565 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
567 InitializeListHead (&Interface
->IpInstances
);
568 Interface
->PromiscRecv
= FALSE
;
575 Set the interface's address, create and configure
576 the ARP child if necessary.
578 @param Interface The interface to set the address
579 @param IpAddr The interface's IP address
580 @param SubnetMask The interface's netmask
582 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
583 and a ARP is created for it.
584 @retval Others Failed to set the interface's address.
589 IN OUT IP4_INTERFACE
*Interface
,
591 IN IP4_ADDR SubnetMask
594 EFI_ARP_CONFIG_DATA ArpConfig
;
600 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
602 ASSERT (!Interface
->Configured
);
605 // Set the ip/netmask, then compute the subnet broadcast
606 // and network broadcast for easy access. When computing
607 // nework broadcast, the subnet mask is most like longer
608 // than the default netmask (not subneted) as defined in
609 // RFC793. If that isn't the case, we are aggregating the
610 // networks, use the subnet's mask instead.
612 Interface
->Ip
= IpAddr
;
613 Interface
->SubnetMask
= SubnetMask
;
614 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
616 Type
= NetGetIpClass (IpAddr
);
617 Len
= NetGetMaskLength (SubnetMask
);
618 Netmask
= gIp4AllMasks
[MIN (Len
, Type
<< 3)];
619 Interface
->NetBrdcast
= (IpAddr
| ~Netmask
);
622 // If the address is NOT all zero, create then configure an ARP child.
623 // Pay attention: DHCP configures its station address as 0.0.0.0/0
625 Interface
->Arp
= NULL
;
626 Interface
->ArpHandle
= NULL
;
628 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
629 Status
= NetLibCreateServiceChild (
630 Interface
->Controller
,
632 &gEfiArpServiceBindingProtocolGuid
,
633 &Interface
->ArpHandle
636 if (EFI_ERROR (Status
)) {
640 Status
= gBS
->OpenProtocol (
641 Interface
->ArpHandle
,
642 &gEfiArpProtocolGuid
,
643 (VOID
**) &Interface
->Arp
,
645 Interface
->Controller
,
646 EFI_OPEN_PROTOCOL_BY_DRIVER
649 if (EFI_ERROR (Status
)) {
653 IpAddr
= HTONL (IpAddr
);
654 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
655 ArpConfig
.SwAddressLength
= 4;
656 ArpConfig
.StationAddress
= &IpAddr
;
657 ArpConfig
.EntryTimeOut
= 0;
658 ArpConfig
.RetryCount
= 0;
659 ArpConfig
.RetryTimeOut
= 0;
661 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
663 if (EFI_ERROR (Status
)) {
665 Interface
->ArpHandle
,
666 &gEfiArpProtocolGuid
,
668 Interface
->Controller
675 Interface
->Configured
= TRUE
;
679 NetLibDestroyServiceChild (
680 Interface
->Controller
,
682 &gEfiArpServiceBindingProtocolGuid
,
683 &Interface
->ArpHandle
691 Filter function to cancel all the frame related to an IP instance.
693 @param Frame The transmit request to test whether to cancel
694 @param Context The context which is the Ip instance that issued
697 @retval TRUE The frame belongs to this instance and is to be
699 @retval FALSE The frame doesn't belong to this instance.
703 Ip4CancelInstanceFrame (
704 IN IP4_LINK_TX_TOKEN
*Frame
,
708 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
718 If there is a pending receive request, cancel it. Don't call
719 the receive request's callback because this function can be only
720 called if the instance or driver is tearing itself down. It
721 doesn't make sense to call it back. But it is necessary to call
722 the transmit token's callback to give it a chance to free the
723 packet and update the upper layer's transmit request status, say
726 @param Interface The interface used by the IpInstance
733 IN IP4_INTERFACE
*Interface
737 IP4_LINK_RX_TOKEN
*Token
;
739 if ((Token
= Interface
->RecvRequest
) != NULL
) {
740 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
742 Interface
->RecvRequest
= NULL
;
743 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
745 gBS
->RestoreTPL (OldTpl
);
751 Free the interface used by IpInstance. All the IP instance with
752 the same Ip/Netmask pair share the same interface. It is reference
753 counted. All the frames haven't been sent will be cancelled.
754 Because the IpInstance is optional, the caller must remove
755 IpInstance from the interface's instance list itself.
757 @param Interface The interface used by the IpInstance
758 @param IpInstance The Ip instance that free the interface. NULL if
759 the Ip driver is releasing the default interface.
761 @retval EFI_SUCCESS The interface use IpInstance is freed.
766 IN IP4_INTERFACE
*Interface
,
767 IN IP4_PROTOCOL
*IpInstance OPTIONAL
770 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
771 ASSERT (Interface
->RefCnt
> 0);
774 // Remove all the pending transmit token related to this IP instance.
776 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
778 if (--Interface
->RefCnt
> 0) {
783 // Destory the interface if this is the last IP instance that
784 // has the address. Remove all the system transmitted packets
785 // from this interface, cancel the receive request if there is
786 // one, and destory the ARP requests.
788 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
789 Ip4CancelReceive (Interface
);
791 ASSERT (IsListEmpty (&Interface
->IpInstances
));
792 ASSERT (IsListEmpty (&Interface
->ArpQues
));
793 ASSERT (IsListEmpty (&Interface
->SentFrames
));
795 if (Interface
->Arp
!= NULL
) {
797 Interface
->ArpHandle
,
798 &gEfiArpProtocolGuid
,
800 Interface
->Controller
803 NetLibDestroyServiceChild (
804 Interface
->Controller
,
806 &gEfiArpServiceBindingProtocolGuid
,
811 RemoveEntryList (&Interface
->Link
);
812 gBS
->FreePool (Interface
);
819 Callback function when ARP request are finished. It will cancelled
820 all the queued frame if the ARP requests failed. Or transmit them
821 if the request succeed.
823 @param Context The context of the callback, a point to the ARP
831 Ip4OnArpResolvedDpc (
838 IP4_INTERFACE
*Interface
;
839 IP4_LINK_TX_TOKEN
*Token
;
842 ArpQue
= (IP4_ARP_QUE
*) Context
;
843 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
845 RemoveEntryList (&ArpQue
->Link
);
848 // ARP resolve failed for some reason. Release all the frame
849 // and ARP queue itself. Ip4FreeArpQue will call the frame's
852 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
853 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
859 // ARP resolve succeeded, Transmit all the frame. Release the ARP
860 // queue. It isn't necessary for us to cache the ARP binding because
861 // we always check the ARP cache first before transmit.
863 Interface
= ArpQue
->Interface
;
865 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
866 RemoveEntryList (Entry
);
868 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
869 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
872 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
873 // may be called before Mnp->Transmit returns which will remove this tx
874 // token from the SentFrames list. Remove it from the list if the returned
875 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
876 // FrameSentDpc won't be queued.
878 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
880 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
881 if (EFI_ERROR (Status
)) {
882 RemoveEntryList (Entry
);
883 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
885 Ip4FreeLinkTxToken (Token
);
890 Ip4FreeArpQue (ArpQue
, EFI_SUCCESS
);
894 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
896 @param Event The Arp request event.
897 @param Context The context of the callback, a point to the ARP
911 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
913 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
919 Callback funtion when frame transmission is finished. It will
920 call the frame owner's callback function to tell it the result.
922 @param Context Context which is point to the token.
933 IP4_LINK_TX_TOKEN
*Token
;
935 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
936 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
938 RemoveEntryList (&Token
->Link
);
943 Token
->MnpToken
.Status
,
948 Ip4FreeLinkTxToken (Token
);
952 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
954 @param Event The transmit token's event.
955 @param Context Context which is point to the token.
968 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
970 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameSentDpc
, Context
);
976 Send a frame from the interface. If the next hop is broadcast or
977 multicast address, it is transmitted immediately. If the next hop
978 is a unicast, it will consult ARP to resolve the NextHop's MAC.
979 If some error happened, the CallBack won't be called. So, the caller
980 must test the return value, and take action when there is an error.
982 @param Interface The interface to send the frame from
983 @param IpInstance The IP child that request the transmission. NULL
984 if it is the IP4 driver itself.
985 @param Packet The packet to transmit.
986 @param NextHop The immediate destination to transmit the packet
988 @param CallBack Function to call back when transmit finished.
989 @param Context Opaque parameter to the call back.
991 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
992 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
993 @retval EFI_SUCCESS The packet is successfully transmitted.
994 @retval other Other error occurs.
999 IN IP4_INTERFACE
*Interface
,
1000 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
1002 IN IP4_ADDR NextHop
,
1003 IN IP4_FRAME_CALLBACK CallBack
,
1007 IP4_LINK_TX_TOKEN
*Token
;
1009 IP4_ARP_QUE
*ArpQue
;
1010 EFI_ARP_PROTOCOL
*Arp
;
1013 ASSERT (Interface
->Configured
);
1015 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
);
1017 if (Token
== NULL
) {
1018 return EFI_OUT_OF_RESOURCES
;
1022 // Get the destination MAC address for multicast and broadcasts.
1023 // Don't depend on ARP to solve the address since there maybe no
1024 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1025 // all the broadcasts.
1027 if (NextHop
== IP4_ALLONE_ADDRESS
) {
1028 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
1031 } else if (IP4_IS_MULTICAST (NextHop
)) {
1033 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
1035 if (EFI_ERROR (Status
)) {
1043 // Can only send out multicast/broadcast if the IP address is zero
1045 if ((Arp
= Interface
->Arp
) == NULL
) {
1046 Status
= EFI_NO_MAPPING
;
1051 // First check whether this binding is in the ARP cache.
1053 NextHop
= HTONL (NextHop
);
1054 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1056 if (Status
== EFI_SUCCESS
) {
1059 } else if (Status
!= EFI_NOT_READY
) {
1064 // Have to do asynchronous ARP resolution. First check
1065 // whether there is already a pending request.
1069 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1070 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1072 if (ArpQue
->Ip
== NextHop
) {
1078 // Found a pending ARP request, enqueue the frame then return
1080 if (Entry
!= &Interface
->ArpQues
) {
1081 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1086 // First frame to NextHop, issue an asynchronous ARP requests
1088 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1090 if (ArpQue
== NULL
) {
1091 Status
= EFI_OUT_OF_RESOURCES
;
1095 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1097 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1098 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1102 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1103 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1108 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1109 // Remove it if the returned status is not EFI_SUCCESS.
1111 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1112 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1113 if (EFI_ERROR (Status
)) {
1114 RemoveEntryList (&Interface
->SentFrames
);
1121 Ip4FreeLinkTxToken (Token
);
1127 Call back function when the received packet is freed.
1128 Check Ip4OnFrameReceived for information.
1130 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1140 IP4_LINK_RX_TOKEN
*Frame
;
1142 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1143 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1145 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1146 Ip4FreeFrameRxToken (Frame
);
1151 Received a frame from MNP, wrap it in net buffer then deliver
1152 it to IP's input function. The ownship of the packet also
1153 transferred to IP. When Ip is finished with this packet, it
1154 will call NetbufFree to release the packet, NetbufFree will
1155 again call the Ip4RecycleFrame to signal MNP's event and free
1158 @param Context Context for the callback.
1165 Ip4OnFrameReceivedDpc (
1169 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1170 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1171 IP4_LINK_RX_TOKEN
*Token
;
1172 NET_FRAGMENT Netfrag
;
1176 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1177 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1180 // First clear the interface's receive request in case the
1181 // caller wants to call Ip4ReceiveFrame in the callback.
1183 Token
->Interface
->RecvRequest
= NULL
;
1185 MnpToken
= &Token
->MnpToken
;
1186 MnpRxData
= MnpToken
->Packet
.RxData
;
1188 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1189 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1190 Ip4FreeFrameRxToken (Token
);
1196 // Wrap the frame in a net buffer then deliever it to IP input.
1197 // IP will reassemble the packet, and deliver it to upper layer
1199 Netfrag
.Len
= MnpRxData
->DataLength
;
1200 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1202 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1204 if (Packet
== NULL
) {
1205 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1207 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1208 Ip4FreeFrameRxToken (Token
);
1213 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1214 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1215 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1217 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1222 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1224 @param Event The receive event delivered to MNP for receive.
1225 @param Context Context for the callback.
1232 Ip4OnFrameReceived (
1238 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1240 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1245 Request to receive the packet from the interface.
1247 @param Interface The interface to receive the frames from
1248 @param IpInstance The instance that requests the receive. NULL for
1250 @param CallBack Function to call when receive finished.
1251 @param Context Opaque parameter to the callback
1253 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1254 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive
1255 @retval EFI_SUCCESS The recieve request has been started.
1256 @retval other Other error occurs.
1261 IN IP4_INTERFACE
*Interface
,
1262 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
1263 IN IP4_FRAME_CALLBACK CallBack
,
1267 IP4_LINK_RX_TOKEN
*Token
;
1270 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1272 if (Interface
->RecvRequest
!= NULL
) {
1273 return EFI_ALREADY_STARTED
;
1276 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1278 if (Token
== NULL
) {
1279 return EFI_OUT_OF_RESOURCES
;
1282 Interface
->RecvRequest
= Token
;
1283 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1284 if (EFI_ERROR (Status
)) {
1285 Interface
->RecvRequest
= NULL
;
1286 Ip4FreeFrameRxToken (Token
);