2 Implement IP4 pesudo interface.
4 Copyright (c) 2005 - 2007, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 // Mac address with all zero, used to determine whethter the ARP
19 // resolve succeeded. Failed ARP requests zero the MAC address buffer.
21 EFI_MAC_ADDRESS mZeroMacAddress
;
24 Callback funtion when frame transmission is finished. It will
25 call the frame owner's callback function to tell it the result.
27 @param[in] Context Context which is point to the token.
37 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
39 @param[in] Event The transmit token's event.
40 @param[in] Context Context which is point to the token.
51 Callback function when ARP request are finished. It will cancelled
52 all the queued frame if the ARP requests failed. Or transmit them
53 if the request succeed.
55 @param[in] Context The context of the callback, a point to the ARP
66 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
68 @param Event The Arp request event.
69 @param Context The context of the callback, a point to the ARP
81 Received a frame from MNP, wrap it in net buffer then deliver
82 it to IP's input function. The ownship of the packet also
83 transferred to IP. When Ip is finished with this packet, it
84 will call NetbufFree to release the packet, NetbufFree will
85 again call the Ip4RecycleFrame to signal MNP's event and free
88 @param Context Context for the callback.
93 Ip4OnFrameReceivedDpc (
98 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
100 @param Event The receive event delivered to MNP for receive.
101 @param Context Context for the callback.
112 Remove all the frames on the ARP queue that pass the FrameToCancel,
113 that is, either FrameToCancel is NULL or it returns true for the frame.
115 @param[in] ArpQue ARP frame to remove the frames from.
116 @param[in] IoStatus The status returned to the cancelled frames'
118 @param[in] FrameToCancel Function to select which frame to cancel.
119 @param[in] Context Opaque parameter to the FrameToCancel.
124 IN IP4_ARP_QUE
*ArpQue
,
125 IN EFI_STATUS IoStatus
,
126 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
132 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
134 @param[in] Interface The interface to send out to.
135 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
136 the packet is sent by the IP4 driver itself.
137 @param[in] Packet The packet to transmit
138 @param[in] CallBack Call back function to execute if transmission
140 @param[in] Context Opaque parameter to the call back.
142 @retval Token The wrapped token if succeed
143 @retval NULL The wrapped token if NULL
148 IN IP4_INTERFACE
*Interface
,
149 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
151 IN IP4_FRAME_CALLBACK CallBack
,
155 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
156 EFI_MANAGED_NETWORK_TRANSMIT_DATA
*MnpTxData
;
157 IP4_LINK_TX_TOKEN
*Token
;
161 Token
= AllocatePool (sizeof (IP4_LINK_TX_TOKEN
) + \
162 (Packet
->BlockOpNum
- 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA
));
168 Token
->Signature
= IP4_FRAME_TX_SIGNATURE
;
169 InitializeListHead (&Token
->Link
);
171 Token
->Interface
= Interface
;
172 Token
->IpInstance
= IpInstance
;
173 Token
->CallBack
= CallBack
;
174 Token
->Packet
= Packet
;
175 Token
->Context
= Context
;
176 CopyMem (&Token
->DstMac
, &mZeroMacAddress
, sizeof (Token
->DstMac
));
177 CopyMem (&Token
->SrcMac
, &Interface
->Mac
, sizeof (Token
->SrcMac
));
179 MnpToken
= &(Token
->MnpToken
);
180 MnpToken
->Status
= EFI_NOT_READY
;
182 Status
= gBS
->CreateEvent (
190 if (EFI_ERROR (Status
)) {
191 gBS
->FreePool (Token
);
195 MnpTxData
= &Token
->MnpTxData
;
196 MnpToken
->Packet
.TxData
= MnpTxData
;
198 MnpTxData
->DestinationAddress
= &Token
->DstMac
;
199 MnpTxData
->SourceAddress
= &Token
->SrcMac
;
200 MnpTxData
->ProtocolType
= IP4_ETHER_PROTO
;
201 MnpTxData
->DataLength
= Packet
->TotalSize
;
202 MnpTxData
->HeaderLength
= 0;
204 Count
= Packet
->BlockOpNum
;
206 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) MnpTxData
->FragmentTable
, &Count
);
207 MnpTxData
->FragmentCount
= (UINT16
)Count
;
214 Free the link layer transmit token. It will close the event
215 then free the memory used.
217 @param[in] Token Token to free
222 IN IP4_LINK_TX_TOKEN
*Token
225 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
227 gBS
->CloseEvent (Token
->MnpToken
.Event
);
228 gBS
->FreePool (Token
);
233 Create an IP_ARP_QUE structure to request ARP service.
235 @param[in] Interface The interface to send ARP from.
236 @param[in] DestIp The destination IP (host byte order) to request MAC
239 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
244 IN IP4_INTERFACE
*Interface
,
251 ArpQue
= AllocatePool (sizeof (IP4_ARP_QUE
));
253 if (ArpQue
== NULL
) {
257 ArpQue
->Signature
= IP4_FRAME_ARP_SIGNATURE
;
258 InitializeListHead (&ArpQue
->Link
);
260 InitializeListHead (&ArpQue
->Frames
);
261 ArpQue
->Interface
= Interface
;
263 Status
= gBS
->CreateEvent (
271 if (EFI_ERROR (Status
)) {
272 gBS
->FreePool (ArpQue
);
277 CopyMem (&ArpQue
->Mac
, &mZeroMacAddress
, sizeof (ArpQue
->Mac
));
284 Remove all the transmit requests queued on the ARP queue, then free it.
286 @param[in] ArpQue Arp queue to free
287 @param[in] IoStatus The transmit status returned to transmit requests'
293 IN IP4_ARP_QUE
*ArpQue
,
294 IN EFI_STATUS IoStatus
297 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
300 // Remove all the frame waiting the ARP response
302 Ip4CancelFrameArp (ArpQue
, IoStatus
, NULL
, NULL
);
304 gBS
->CloseEvent (ArpQue
->OnResolved
);
305 gBS
->FreePool (ArpQue
);
310 Create a link layer receive token to wrap the receive request
312 @param[in] Interface The interface to receive from
313 @param[in] IpInstance The instance that request the receive (NULL for IP4
315 @param[in] CallBack Call back function to execute when finished.
316 @param[in] Context Opaque parameters to the callback
318 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
322 Ip4CreateLinkRxToken (
323 IN IP4_INTERFACE
*Interface
,
324 IN IP4_PROTOCOL
*IpInstance
,
325 IN IP4_FRAME_CALLBACK CallBack
,
329 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
330 IP4_LINK_RX_TOKEN
*Token
;
333 Token
= AllocatePool (sizeof (IP4_LINK_RX_TOKEN
));
338 Token
->Signature
= IP4_FRAME_RX_SIGNATURE
;
339 Token
->Interface
= Interface
;
340 Token
->IpInstance
= IpInstance
;
341 Token
->CallBack
= CallBack
;
342 Token
->Context
= Context
;
344 MnpToken
= &Token
->MnpToken
;
345 MnpToken
->Status
= EFI_NOT_READY
;
347 Status
= gBS
->CreateEvent (
355 if (EFI_ERROR (Status
)) {
356 gBS
->FreePool (Token
);
360 MnpToken
->Packet
.RxData
= NULL
;
366 Free the link layer request token. It will close the event
367 then free the memory used.
369 @param[in] Token Request token to free.
373 Ip4FreeFrameRxToken (
374 IN IP4_LINK_RX_TOKEN
*Token
378 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
380 gBS
->CloseEvent (Token
->MnpToken
.Event
);
381 gBS
->FreePool (Token
);
386 Remove all the frames on the ARP queue that pass the FrameToCancel,
387 that is, either FrameToCancel is NULL or it returns true for the frame.
389 @param[in] ArpQue ARP frame to remove the frames from.
390 @param[in] IoStatus The status returned to the cancelled frames'
392 @param[in] FrameToCancel Function to select which frame to cancel.
393 @param[in] Context Opaque parameter to the FrameToCancel.
398 IN IP4_ARP_QUE
*ArpQue
,
399 IN EFI_STATUS IoStatus
,
400 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
406 IP4_LINK_TX_TOKEN
*Token
;
408 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
409 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
411 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
412 RemoveEntryList (Entry
);
414 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, IoStatus
, 0, Token
->Context
);
415 Ip4FreeLinkTxToken (Token
);
422 Remove all the frames on the interface that pass the FrameToCancel,
423 either queued on ARP queues or that have already been delivered to
424 MNP and not yet recycled.
426 @param[in] Interface Interface to remove the frames from
427 @param[in] IoStatus The transmit status returned to the frames'
429 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
431 @param[in] Context Opaque parameters passed to FrameToCancel
436 IN IP4_INTERFACE
*Interface
,
437 IN EFI_STATUS IoStatus
,
438 IN IP4_FRAME_TO_CANCEL FrameToCancel
, OPTIONAL
445 IP4_LINK_TX_TOKEN
*Token
;
448 // Cancel all the pending frames on ARP requests
450 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->ArpQues
) {
451 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
453 Ip4CancelFrameArp (ArpQue
, IoStatus
, FrameToCancel
, Context
);
455 if (IsListEmpty (&ArpQue
->Frames
)) {
456 Interface
->Arp
->Cancel (Interface
->Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
);
461 // Cancel all the frames that have been delivered to MNP
462 // but not yet recycled.
464 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &Interface
->SentFrames
) {
465 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
467 if ((FrameToCancel
== NULL
) || FrameToCancel (Token
, Context
)) {
468 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
475 Create an IP4_INTERFACE. Delay the creation of ARP instance until
476 the interface is configured.
478 @param[in] Mnp The shared MNP child of this IP4 service binding
480 @param[in] Controller The controller this IP4 service binding instance
481 is installed. Most like the UNDI handle.
482 @param[in] ImageHandle This driver's image handle
484 @return Point to the created IP4_INTERFACE, otherwise NULL.
489 IN EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
,
490 IN EFI_HANDLE Controller
,
491 IN EFI_HANDLE ImageHandle
494 IP4_INTERFACE
*Interface
;
495 EFI_SIMPLE_NETWORK_MODE SnpMode
;
497 Interface
= AllocatePool (sizeof (IP4_INTERFACE
));
499 if ((Interface
== NULL
) || (Mnp
== NULL
)) {
503 Interface
->Signature
= IP4_INTERFACE_SIGNATURE
;
504 InitializeListHead (&Interface
->Link
);
505 Interface
->RefCnt
= 1;
507 Interface
->Ip
= IP4_ALLZERO_ADDRESS
;
508 Interface
->SubnetMask
= IP4_ALLZERO_ADDRESS
;
509 Interface
->Configured
= FALSE
;
511 Interface
->Controller
= Controller
;
512 Interface
->Image
= ImageHandle
;
513 Interface
->Mnp
= Mnp
;
514 Interface
->Arp
= NULL
;
515 Interface
->ArpHandle
= NULL
;
517 InitializeListHead (&Interface
->ArpQues
);
518 InitializeListHead (&Interface
->SentFrames
);
520 Interface
->RecvRequest
= NULL
;
523 // Get the interface's Mac address and broadcast mac address from SNP
525 if (EFI_ERROR (Mnp
->GetModeData (Mnp
, NULL
, &SnpMode
))) {
526 gBS
->FreePool (Interface
);
530 CopyMem (&Interface
->Mac
, &SnpMode
.CurrentAddress
, sizeof (Interface
->Mac
));
531 CopyMem (&Interface
->BroadcastMac
, &SnpMode
.BroadcastAddress
, sizeof (Interface
->BroadcastMac
));
532 Interface
->HwaddrLen
= SnpMode
.HwAddressSize
;
534 InitializeListHead (&Interface
->IpInstances
);
535 Interface
->PromiscRecv
= FALSE
;
542 Set the interface's address, create and configure
543 the ARP child if necessary.
545 @param Interface The interface to set the address
546 @param IpAddr The interface's IP address
547 @param SubnetMask The interface's netmask
549 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
550 and a ARP is created for it.
551 @retval Others Failed to set the interface's address.
556 IN OUT IP4_INTERFACE
*Interface
,
558 IN IP4_ADDR SubnetMask
561 EFI_ARP_CONFIG_DATA ArpConfig
;
567 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
569 ASSERT (!Interface
->Configured
);
572 // Set the ip/netmask, then compute the subnet broadcast
573 // and network broadcast for easy access. When computing
574 // nework broadcast, the subnet mask is most like longer
575 // than the default netmask (not subneted) as defined in
576 // RFC793. If that isn't the case, we are aggregating the
577 // networks, use the subnet's mask instead.
579 Interface
->Ip
= IpAddr
;
580 Interface
->SubnetMask
= SubnetMask
;
581 Interface
->SubnetBrdcast
= (IpAddr
| ~SubnetMask
);
583 Type
= NetGetIpClass (IpAddr
);
584 Len
= NetGetMaskLength (SubnetMask
);
585 Netmask
= gIp4AllMasks
[MIN (Len
, Type
<< 3)];
586 Interface
->NetBrdcast
= (IpAddr
| ~Netmask
);
589 // If the address is NOT all zero, create then configure an ARP child.
590 // Pay attention: DHCP configures its station address as 0.0.0.0/0
592 Interface
->Arp
= NULL
;
593 Interface
->ArpHandle
= NULL
;
595 if (IpAddr
!= IP4_ALLZERO_ADDRESS
) {
596 Status
= NetLibCreateServiceChild (
597 Interface
->Controller
,
599 &gEfiArpServiceBindingProtocolGuid
,
600 &Interface
->ArpHandle
603 if (EFI_ERROR (Status
)) {
607 Status
= gBS
->OpenProtocol (
608 Interface
->ArpHandle
,
609 &gEfiArpProtocolGuid
,
610 (VOID
**) &Interface
->Arp
,
612 Interface
->Controller
,
613 EFI_OPEN_PROTOCOL_BY_DRIVER
616 if (EFI_ERROR (Status
)) {
620 IpAddr
= HTONL (IpAddr
);
621 ArpConfig
.SwAddressType
= IP4_ETHER_PROTO
;
622 ArpConfig
.SwAddressLength
= 4;
623 ArpConfig
.StationAddress
= &IpAddr
;
624 ArpConfig
.EntryTimeOut
= 0;
625 ArpConfig
.RetryCount
= 0;
626 ArpConfig
.RetryTimeOut
= 0;
628 Status
= Interface
->Arp
->Configure (Interface
->Arp
, &ArpConfig
);
630 if (EFI_ERROR (Status
)) {
632 Interface
->ArpHandle
,
633 &gEfiArpProtocolGuid
,
635 Interface
->Controller
642 Interface
->Configured
= TRUE
;
646 NetLibDestroyServiceChild (
647 Interface
->Controller
,
649 &gEfiArpServiceBindingProtocolGuid
,
650 &Interface
->ArpHandle
658 Filter function to cancel all the frame related to an IP instance.
660 @param[in] Frame The transmit request to test whether to cancel
661 @param[in] Context The context which is the Ip instance that issued
664 @retval TRUE The frame belongs to this instance and is to be
666 @retval FALSE The frame doesn't belong to this instance.
670 Ip4CancelInstanceFrame (
671 IN IP4_LINK_TX_TOKEN
*Frame
,
675 if (Frame
->IpInstance
== (IP4_PROTOCOL
*) Context
) {
685 If there is a pending receive request, cancel it. Don't call
686 the receive request's callback because this function can be only
687 called if the instance or driver is tearing itself down. It
688 doesn't make sense to call it back. But it is necessary to call
689 the transmit token's callback to give it a chance to free the
690 packet and update the upper layer's transmit request status, say
693 @param[in] Interface The interface used by the IpInstance
698 IN IP4_INTERFACE
*Interface
702 IP4_LINK_RX_TOKEN
*Token
;
704 if ((Token
= Interface
->RecvRequest
) != NULL
) {
705 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
707 Interface
->RecvRequest
= NULL
;
708 Interface
->Mnp
->Cancel (Interface
->Mnp
, &Token
->MnpToken
);
710 gBS
->RestoreTPL (OldTpl
);
716 Free the interface used by IpInstance. All the IP instance with
717 the same Ip/Netmask pair share the same interface. It is reference
718 counted. All the frames haven't been sent will be cancelled.
719 Because the IpInstance is optional, the caller must remove
720 IpInstance from the interface's instance list itself.
722 @param[in] Interface The interface used by the IpInstance
723 @param[in] IpInstance The Ip instance that free the interface. NULL if
724 the Ip driver is releasing the default interface.
726 @retval EFI_SUCCESS The interface use IpInstance is freed.
731 IN IP4_INTERFACE
*Interface
,
732 IN IP4_PROTOCOL
*IpInstance OPTIONAL
735 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
736 ASSERT (Interface
->RefCnt
> 0);
739 // Remove all the pending transmit token related to this IP instance.
741 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, IpInstance
);
743 if (--Interface
->RefCnt
> 0) {
748 // Destory the interface if this is the last IP instance that
749 // has the address. Remove all the system transmitted packets
750 // from this interface, cancel the receive request if there is
751 // one, and destory the ARP requests.
753 Ip4CancelFrames (Interface
, EFI_ABORTED
, Ip4CancelInstanceFrame
, NULL
);
754 Ip4CancelReceive (Interface
);
756 ASSERT (IsListEmpty (&Interface
->IpInstances
));
757 ASSERT (IsListEmpty (&Interface
->ArpQues
));
758 ASSERT (IsListEmpty (&Interface
->SentFrames
));
760 if (Interface
->Arp
!= NULL
) {
762 Interface
->ArpHandle
,
763 &gEfiArpProtocolGuid
,
765 Interface
->Controller
768 NetLibDestroyServiceChild (
769 Interface
->Controller
,
771 &gEfiArpServiceBindingProtocolGuid
,
776 RemoveEntryList (&Interface
->Link
);
777 gBS
->FreePool (Interface
);
784 Callback function when ARP request are finished. It will cancelled
785 all the queued frame if the ARP requests failed. Or transmit them
786 if the request succeed.
788 @param[in] Context The context of the callback, a point to the ARP
794 Ip4OnArpResolvedDpc (
801 IP4_INTERFACE
*Interface
;
802 IP4_LINK_TX_TOKEN
*Token
;
805 ArpQue
= (IP4_ARP_QUE
*) Context
;
806 NET_CHECK_SIGNATURE (ArpQue
, IP4_FRAME_ARP_SIGNATURE
);
808 RemoveEntryList (&ArpQue
->Link
);
811 // ARP resolve failed for some reason. Release all the frame
812 // and ARP queue itself. Ip4FreeArpQue will call the frame's
815 if (NET_MAC_EQUAL (&ArpQue
->Mac
, &mZeroMacAddress
, ArpQue
->Interface
->HwaddrLen
)) {
816 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
822 // ARP resolve succeeded, Transmit all the frame. Release the ARP
823 // queue. It isn't necessary for us to cache the ARP binding because
824 // we always check the ARP cache first before transmit.
826 Interface
= ArpQue
->Interface
;
828 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &ArpQue
->Frames
) {
829 RemoveEntryList (Entry
);
831 Token
= NET_LIST_USER_STRUCT (Entry
, IP4_LINK_TX_TOKEN
, Link
);
832 CopyMem (&Token
->DstMac
, &ArpQue
->Mac
, sizeof (Token
->DstMac
));
835 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
836 // may be called before Mnp->Transmit returns which will remove this tx
837 // token from the SentFrames list. Remove it from the list if the returned
838 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
839 // FrameSentDpc won't be queued.
841 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
843 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
844 if (EFI_ERROR (Status
)) {
845 RemoveEntryList (Entry
);
846 Token
->CallBack (Token
->IpInstance
, Token
->Packet
, Status
, 0, Token
->Context
);
848 Ip4FreeLinkTxToken (Token
);
853 Ip4FreeArpQue (ArpQue
, EFI_SUCCESS
);
857 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
859 @param Event The Arp request event.
860 @param Context The context of the callback, a point to the ARP
872 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
874 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnArpResolvedDpc
, Context
);
880 Callback funtion when frame transmission is finished. It will
881 call the frame owner's callback function to tell it the result.
883 @param[in] Context Context which is point to the token.
892 IP4_LINK_TX_TOKEN
*Token
;
894 Token
= (IP4_LINK_TX_TOKEN
*) Context
;
895 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_TX_SIGNATURE
);
897 RemoveEntryList (&Token
->Link
);
902 Token
->MnpToken
.Status
,
907 Ip4FreeLinkTxToken (Token
);
911 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
913 @param[in] Event The transmit token's event.
914 @param[in] 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[in] Interface The interface to send the frame from
940 @param[in] IpInstance The IP child that request the transmission. NULL
941 if it is the IP4 driver itself.
942 @param[in] Packet The packet to transmit.
943 @param[in] NextHop The immediate destination to transmit the packet
945 @param[in] CallBack Function to call back when transmit finished.
946 @param[in] 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.
951 @retval other Other error occurs.
956 IN IP4_INTERFACE
*Interface
,
957 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
960 IN IP4_FRAME_CALLBACK CallBack
,
964 IP4_LINK_TX_TOKEN
*Token
;
967 EFI_ARP_PROTOCOL
*Arp
;
970 ASSERT (Interface
->Configured
);
972 Token
= Ip4WrapLinkTxToken (Interface
, IpInstance
, Packet
, CallBack
, Context
);
975 return EFI_OUT_OF_RESOURCES
;
979 // Get the destination MAC address for multicast and broadcasts.
980 // Don't depend on ARP to solve the address since there maybe no
981 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
982 // all the broadcasts.
984 if (NextHop
== IP4_ALLONE_ADDRESS
) {
985 CopyMem (&Token
->DstMac
, &Interface
->BroadcastMac
, sizeof (Token
->DstMac
));
988 } else if (IP4_IS_MULTICAST (NextHop
)) {
990 Status
= Ip4GetMulticastMac (Interface
->Mnp
, NextHop
, &Token
->DstMac
);
992 if (EFI_ERROR (Status
)) {
1000 // Can only send out multicast/broadcast if the IP address is zero
1002 if ((Arp
= Interface
->Arp
) == NULL
) {
1003 Status
= EFI_NO_MAPPING
;
1008 // First check whether this binding is in the ARP cache.
1010 NextHop
= HTONL (NextHop
);
1011 Status
= Arp
->Request (Arp
, &NextHop
, NULL
, &Token
->DstMac
);
1013 if (Status
== EFI_SUCCESS
) {
1016 } else if (Status
!= EFI_NOT_READY
) {
1021 // Have to do asynchronous ARP resolution. First check
1022 // whether there is already a pending request.
1026 NET_LIST_FOR_EACH (Entry
, &Interface
->ArpQues
) {
1027 ArpQue
= NET_LIST_USER_STRUCT (Entry
, IP4_ARP_QUE
, Link
);
1029 if (ArpQue
->Ip
== NextHop
) {
1035 // Found a pending ARP request, enqueue the frame then return
1037 if (Entry
!= &Interface
->ArpQues
) {
1038 InsertTailList (&ArpQue
->Frames
, &Token
->Link
);
1043 // First frame to NextHop, issue an asynchronous ARP requests
1045 ArpQue
= Ip4CreateArpQue (Interface
, NextHop
);
1047 if (ArpQue
== NULL
) {
1048 Status
= EFI_OUT_OF_RESOURCES
;
1052 Status
= Arp
->Request (Arp
, &ArpQue
->Ip
, ArpQue
->OnResolved
, ArpQue
->Mac
.Addr
);
1054 if (EFI_ERROR (Status
) && (Status
!= EFI_NOT_READY
)) {
1055 Ip4FreeArpQue (ArpQue
, EFI_NO_MAPPING
);
1059 InsertHeadList (&ArpQue
->Frames
, &Token
->Link
);
1060 InsertHeadList (&Interface
->ArpQues
, &ArpQue
->Link
);
1065 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1066 // Remove it if the returned status is not EFI_SUCCESS.
1068 InsertTailList (&Interface
->SentFrames
, &Token
->Link
);
1069 Status
= Interface
->Mnp
->Transmit (Interface
->Mnp
, &Token
->MnpToken
);
1070 if (EFI_ERROR (Status
)) {
1071 RemoveEntryList (&Interface
->SentFrames
);
1078 Ip4FreeLinkTxToken (Token
);
1084 Call back function when the received packet is freed.
1085 Check Ip4OnFrameReceived for information.
1087 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1095 IP4_LINK_RX_TOKEN
*Frame
;
1097 Frame
= (IP4_LINK_RX_TOKEN
*) Context
;
1098 NET_CHECK_SIGNATURE (Frame
, IP4_FRAME_RX_SIGNATURE
);
1100 gBS
->SignalEvent (Frame
->MnpToken
.Packet
.RxData
->RecycleEvent
);
1101 Ip4FreeFrameRxToken (Frame
);
1106 Received a frame from MNP, wrap it in net buffer then deliver
1107 it to IP's input function. The ownship of the packet also
1108 transferred to IP. When Ip is finished with this packet, it
1109 will call NetbufFree to release the packet, NetbufFree will
1110 again call the Ip4RecycleFrame to signal MNP's event and free
1113 @param Context Context for the callback.
1118 Ip4OnFrameReceivedDpc (
1122 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
1123 EFI_MANAGED_NETWORK_RECEIVE_DATA
*MnpRxData
;
1124 IP4_LINK_RX_TOKEN
*Token
;
1125 NET_FRAGMENT Netfrag
;
1129 Token
= (IP4_LINK_RX_TOKEN
*) Context
;
1130 NET_CHECK_SIGNATURE (Token
, IP4_FRAME_RX_SIGNATURE
);
1133 // First clear the interface's receive request in case the
1134 // caller wants to call Ip4ReceiveFrame in the callback.
1136 Token
->Interface
->RecvRequest
= NULL
;
1138 MnpToken
= &Token
->MnpToken
;
1139 MnpRxData
= MnpToken
->Packet
.RxData
;
1141 if (EFI_ERROR (MnpToken
->Status
) || (MnpRxData
== NULL
)) {
1142 Token
->CallBack (Token
->IpInstance
, NULL
, MnpToken
->Status
, 0, Token
->Context
);
1143 Ip4FreeFrameRxToken (Token
);
1149 // Wrap the frame in a net buffer then deliever it to IP input.
1150 // IP will reassemble the packet, and deliver it to upper layer
1152 Netfrag
.Len
= MnpRxData
->DataLength
;
1153 Netfrag
.Bulk
= MnpRxData
->PacketData
;
1155 Packet
= NetbufFromExt (&Netfrag
, 1, 0, IP4_MAX_HEADLEN
, Ip4RecycleFrame
, Token
);
1157 if (Packet
== NULL
) {
1158 gBS
->SignalEvent (MnpRxData
->RecycleEvent
);
1160 Token
->CallBack (Token
->IpInstance
, NULL
, EFI_OUT_OF_RESOURCES
, 0, Token
->Context
);
1161 Ip4FreeFrameRxToken (Token
);
1166 Flag
= (MnpRxData
->BroadcastFlag
? IP4_LINK_BROADCAST
: 0);
1167 Flag
|= (MnpRxData
->MulticastFlag
? IP4_LINK_MULTICAST
: 0);
1168 Flag
|= (MnpRxData
->PromiscuousFlag
? IP4_LINK_PROMISC
: 0);
1170 Token
->CallBack (Token
->IpInstance
, Packet
, EFI_SUCCESS
, Flag
, Token
->Context
);
1174 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1176 @param Event The receive event delivered to MNP for receive.
1177 @param Context Context for the callback.
1182 Ip4OnFrameReceived (
1188 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1190 NetLibQueueDpc (TPL_CALLBACK
, Ip4OnFrameReceivedDpc
, Context
);
1195 Request to receive the packet from the interface.
1197 @param[in] Interface The interface to receive the frames from
1198 @param[in] IpInstance The instance that requests the receive. NULL for
1200 @param[in] CallBack Function to call when receive finished.
1201 @param[in] Context Opaque parameter to the callback
1203 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1204 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive
1205 @retval EFI_SUCCESS The recieve request has been started.
1206 @retval other Other error occurs.
1211 IN IP4_INTERFACE
*Interface
,
1212 IN IP4_PROTOCOL
*IpInstance
, OPTIONAL
1213 IN IP4_FRAME_CALLBACK CallBack
,
1217 IP4_LINK_RX_TOKEN
*Token
;
1220 NET_CHECK_SIGNATURE (Interface
, IP4_INTERFACE_SIGNATURE
);
1222 if (Interface
->RecvRequest
!= NULL
) {
1223 return EFI_ALREADY_STARTED
;
1226 Token
= Ip4CreateLinkRxToken (Interface
, IpInstance
, CallBack
, Context
);
1228 if (Token
== NULL
) {
1229 return EFI_OUT_OF_RESOURCES
;
1232 Interface
->RecvRequest
= Token
;
1233 Status
= Interface
->Mnp
->Receive (Interface
->Mnp
, &Token
->MnpToken
);
1234 if (EFI_ERROR (Status
)) {
1235 Interface
->RecvRequest
= NULL
;
1236 Ip4FreeFrameRxToken (Token
);