TianoCore EDK2 master
Loading...
Searching...
No Matches
Ip4If.c
Go to the documentation of this file.
1
9#include "Ip4Impl.h"
10
11//
12// Mac address with all zero, used to determine whether the ARP
13// resolve succeeded. Failed ARP requests zero the MAC address buffer.
14//
15EFI_MAC_ADDRESS mZeroMacAddress;
16
24VOID
25EFIAPI
27 IN VOID *Context
28 );
29
37VOID
38EFIAPI
40 IN EFI_EVENT Event,
41 IN VOID *Context
42 );
43
53VOID
54EFIAPI
56 IN VOID *Context
57 );
58
67VOID
68EFIAPI
70 IN EFI_EVENT Event,
71 IN VOID *Context
72 );
73
85VOID
86EFIAPI
88 IN VOID *Context
89 );
90
98VOID
99EFIAPI
101 IN EFI_EVENT Event,
102 IN VOID *Context
103 );
104
116VOID
118 IN IP4_ARP_QUE *ArpQue,
119 IN EFI_STATUS IoStatus,
120 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
121 IN VOID *Context
122 );
123
142 IN IP4_INTERFACE *Interface,
143 IN IP4_PROTOCOL *IpInstance OPTIONAL,
144 IN NET_BUF *Packet,
145 IN IP4_FRAME_CALLBACK CallBack,
146 IN VOID *Context,
147 IN IP4_SERVICE *IpSb
148 )
149{
152 IP4_LINK_TX_TOKEN *Token;
153 EFI_STATUS Status;
154 UINT32 Count;
155
156 Token = AllocatePool (
157 sizeof (IP4_LINK_TX_TOKEN) + \
158 (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA)
159 );
160
161 if (Token == NULL) {
162 return NULL;
163 }
164
165 Token->Signature = IP4_FRAME_TX_SIGNATURE;
166 InitializeListHead (&Token->Link);
167
168 Token->Interface = Interface;
169 Token->IpInstance = IpInstance;
170 Token->IpSb = IpSb;
171 Token->CallBack = CallBack;
172 Token->Packet = Packet;
173 Token->Context = Context;
174 CopyMem (&Token->DstMac, &mZeroMacAddress, sizeof (Token->DstMac));
175 CopyMem (&Token->SrcMac, &Interface->Mac, sizeof (Token->SrcMac));
176
177 MnpToken = &(Token->MnpToken);
178 MnpToken->Status = EFI_NOT_READY;
179
180 Status = gBS->CreateEvent (
181 EVT_NOTIFY_SIGNAL,
182 TPL_NOTIFY,
184 Token,
185 &MnpToken->Event
186 );
187
188 if (EFI_ERROR (Status)) {
189 FreePool (Token);
190 return NULL;
191 }
192
193 MnpTxData = &Token->MnpTxData;
194 MnpToken->Packet.TxData = MnpTxData;
195
196 MnpTxData->DestinationAddress = &Token->DstMac;
197 MnpTxData->SourceAddress = &Token->SrcMac;
198 MnpTxData->ProtocolType = IP4_ETHER_PROTO;
199 MnpTxData->DataLength = Packet->TotalSize;
200 MnpTxData->HeaderLength = 0;
201
202 Count = Packet->BlockOpNum;
203
204 NetbufBuildExt (Packet, (NET_FRAGMENT *)MnpTxData->FragmentTable, &Count);
205 MnpTxData->FragmentCount = (UINT16)Count;
206
207 return Token;
208}
209
217VOID
219 IN IP4_LINK_TX_TOKEN *Token
220 )
221{
222 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);
223
224 gBS->CloseEvent (Token->MnpToken.Event);
225 FreePool (Token);
226}
227
240 IN IP4_INTERFACE *Interface,
241 IN IP4_ADDR DestIp
242 )
243{
244 IP4_ARP_QUE *ArpQue;
245 EFI_STATUS Status;
246
247 ArpQue = AllocatePool (sizeof (IP4_ARP_QUE));
248
249 if (ArpQue == NULL) {
250 return NULL;
251 }
252
253 ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;
254 InitializeListHead (&ArpQue->Link);
255
256 InitializeListHead (&ArpQue->Frames);
257 ArpQue->Interface = Interface;
258
259 Status = gBS->CreateEvent (
260 EVT_NOTIFY_SIGNAL,
261 TPL_NOTIFY,
263 ArpQue,
264 &ArpQue->OnResolved
265 );
266
267 if (EFI_ERROR (Status)) {
268 FreePool (ArpQue);
269 return NULL;
270 }
271
272 ArpQue->Ip = DestIp;
273 CopyMem (&ArpQue->Mac, &mZeroMacAddress, sizeof (ArpQue->Mac));
274
275 return ArpQue;
276}
277
286VOID
288 IN IP4_ARP_QUE *ArpQue,
289 IN EFI_STATUS IoStatus
290 )
291{
292 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
293
294 //
295 // Remove all the frame waiting the ARP response
296 //
297 Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);
298
299 gBS->CloseEvent (ArpQue->OnResolved);
300 FreePool (ArpQue);
301}
302
317 IN IP4_INTERFACE *Interface,
318 IN IP4_PROTOCOL *IpInstance,
319 IN IP4_FRAME_CALLBACK CallBack,
320 IN VOID *Context
321 )
322{
324 IP4_LINK_RX_TOKEN *Token;
325 EFI_STATUS Status;
326
327 Token = AllocatePool (sizeof (IP4_LINK_RX_TOKEN));
328 if (Token == NULL) {
329 return NULL;
330 }
331
332 Token->Signature = IP4_FRAME_RX_SIGNATURE;
333 Token->Interface = Interface;
334 Token->IpInstance = IpInstance;
335 Token->CallBack = CallBack;
336 Token->Context = Context;
337
338 MnpToken = &Token->MnpToken;
339 MnpToken->Status = EFI_NOT_READY;
340
341 Status = gBS->CreateEvent (
342 EVT_NOTIFY_SIGNAL,
343 TPL_NOTIFY,
345 Token,
346 &MnpToken->Event
347 );
348
349 if (EFI_ERROR (Status)) {
350 FreePool (Token);
351 return NULL;
352 }
353
354 MnpToken->Packet.RxData = NULL;
355 return Token;
356}
357
365VOID
367 IN IP4_LINK_RX_TOKEN *Token
368 )
369{
370 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
371
372 gBS->CloseEvent (Token->MnpToken.Event);
373 FreePool (Token);
374}
375
387VOID
389 IN IP4_ARP_QUE *ArpQue,
390 IN EFI_STATUS IoStatus,
391 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
392 IN VOID *Context
393 )
394{
395 LIST_ENTRY *Entry;
396 LIST_ENTRY *Next;
397 IP4_LINK_TX_TOKEN *Token;
398
399 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
400 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
401
402 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
403 RemoveEntryList (Entry);
404
405 Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);
406 Ip4FreeLinkTxToken (Token);
407 }
408 }
409}
410
424VOID
426 IN IP4_INTERFACE *Interface,
427 IN EFI_STATUS IoStatus,
428 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
429 IN VOID *Context
430 )
431{
432 LIST_ENTRY *Entry;
433 LIST_ENTRY *Next;
434 IP4_ARP_QUE *ArpQue;
435 IP4_LINK_TX_TOKEN *Token;
436
437 //
438 // Cancel all the pending frames on ARP requests
439 //
440 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
441 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
442
443 Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);
444
445 if (IsListEmpty (&ArpQue->Frames)) {
446 Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);
447 }
448 }
449
450 //
451 // Cancel all the frames that have been delivered to MNP
452 // but not yet recycled.
453 //
454 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
455 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
456
457 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
458 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
459 }
460 }
461}
462
479 IN EFI_HANDLE Controller,
480 IN EFI_HANDLE ImageHandle
481 )
482{
483 IP4_INTERFACE *Interface;
485
486 if (Mnp == NULL) {
487 return NULL;
488 }
489
490 Interface = AllocatePool (sizeof (IP4_INTERFACE));
491
492 if (Interface == NULL) {
493 return NULL;
494 }
495
496 Interface->Signature = IP4_INTERFACE_SIGNATURE;
497 InitializeListHead (&Interface->Link);
498 Interface->RefCnt = 1;
499
500 Interface->Ip = IP4_ALLZERO_ADDRESS;
501 Interface->SubnetMask = IP4_ALLZERO_ADDRESS;
502 Interface->Configured = FALSE;
503
504 Interface->Controller = Controller;
505 Interface->Image = ImageHandle;
506 Interface->Mnp = Mnp;
507 Interface->Arp = NULL;
508 Interface->ArpHandle = NULL;
509
510 InitializeListHead (&Interface->ArpQues);
511 InitializeListHead (&Interface->SentFrames);
512
513 Interface->RecvRequest = NULL;
514
515 //
516 // Get the interface's Mac address and broadcast mac address from SNP
517 //
518 if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {
519 FreePool (Interface);
520 return NULL;
521 }
522
523 CopyMem (&Interface->Mac, &SnpMode.CurrentAddress, sizeof (Interface->Mac));
524 CopyMem (&Interface->BroadcastMac, &SnpMode.BroadcastAddress, sizeof (Interface->BroadcastMac));
525 Interface->HwaddrLen = SnpMode.HwAddressSize;
526
527 InitializeListHead (&Interface->IpInstances);
528 Interface->PromiscRecv = FALSE;
529
530 return Interface;
531}
532
548 IN OUT IP4_INTERFACE *Interface,
549 IN IP4_ADDR IpAddr,
550 IN IP4_ADDR SubnetMask
551 )
552{
553 EFI_ARP_CONFIG_DATA ArpConfig;
554 EFI_STATUS Status;
555
556 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
557
558 //
559 // Set the ip/netmask, then compute the subnet broadcast
560 // and network broadcast for easy access. When computing
561 // network broadcast, the subnet mask is most like longer
562 // than the default netmask (not subneted) as defined in
563 // RFC793. If that isn't the case, we are aggregating the
564 // networks, use the subnet's mask instead.
565 //
566 Interface->Ip = IpAddr;
567 Interface->SubnetMask = SubnetMask;
568 Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);
569 Interface->NetBrdcast = (IpAddr | ~SubnetMask);
570
571 //
572 // Do clean up for Arp child
573 //
574 if (Interface->ArpHandle != NULL) {
575 if (Interface->Arp != NULL) {
576 gBS->CloseProtocol (
577 Interface->ArpHandle,
578 &gEfiArpProtocolGuid,
579 Interface->Image,
580 Interface->Controller
581 );
582
583 Interface->Arp = NULL;
584 }
585
587 Interface->Controller,
588 Interface->Image,
589 &gEfiArpServiceBindingProtocolGuid,
590 Interface->ArpHandle
591 );
592
593 Interface->ArpHandle = NULL;
594 }
595
596 //
597 // If the address is NOT all zero, create then configure an ARP child.
598 // Pay attention: DHCP configures its station address as 0.0.0.0/0
599 //
600 if (IpAddr != IP4_ALLZERO_ADDRESS) {
601 Status = NetLibCreateServiceChild (
602 Interface->Controller,
603 Interface->Image,
604 &gEfiArpServiceBindingProtocolGuid,
605 &Interface->ArpHandle
606 );
607
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611
612 Status = gBS->OpenProtocol (
613 Interface->ArpHandle,
614 &gEfiArpProtocolGuid,
615 (VOID **)&Interface->Arp,
616 Interface->Image,
617 Interface->Controller,
618 EFI_OPEN_PROTOCOL_BY_DRIVER
619 );
620
621 if (EFI_ERROR (Status)) {
622 goto ON_ERROR;
623 }
624
625 IpAddr = HTONL (IpAddr);
626 ArpConfig.SwAddressType = IP4_ETHER_PROTO;
627 ArpConfig.SwAddressLength = 4;
628 ArpConfig.StationAddress = &IpAddr;
629 ArpConfig.EntryTimeOut = 0;
630 ArpConfig.RetryCount = 0;
631 ArpConfig.RetryTimeOut = 0;
632
633 Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);
634
635 if (EFI_ERROR (Status)) {
636 gBS->CloseProtocol (
637 Interface->ArpHandle,
638 &gEfiArpProtocolGuid,
639 Interface->Image,
640 Interface->Controller
641 );
642
643 goto ON_ERROR;
644 }
645 }
646
647 Interface->Configured = TRUE;
648 return EFI_SUCCESS;
649
650ON_ERROR:
652 Interface->Controller,
653 Interface->Image,
654 &gEfiArpServiceBindingProtocolGuid,
655 Interface->ArpHandle
656 );
657
658 return Status;
659}
660
673BOOLEAN
675 IN IP4_LINK_TX_TOKEN *Frame,
676 IN VOID *Context
677 )
678{
679 if (Frame->IpInstance == (IP4_PROTOCOL *)Context) {
680 return TRUE;
681 }
682
683 return FALSE;
684}
685
698VOID
700 IN IP4_INTERFACE *Interface
701 )
702{
703 EFI_TPL OldTpl;
704 IP4_LINK_RX_TOKEN *Token;
705
706 if ((Token = Interface->RecvRequest) != NULL) {
707 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
708
709 Interface->RecvRequest = NULL;
710 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
711
712 gBS->RestoreTPL (OldTpl);
713 }
714}
715
732 IN IP4_INTERFACE *Interface,
733 IN IP4_PROTOCOL *IpInstance OPTIONAL
734 )
735{
736 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
737 ASSERT (Interface->RefCnt > 0);
738
739 //
740 // Remove all the pending transmit token related to this IP instance.
741 //
742 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
743
744 if (--Interface->RefCnt > 0) {
745 return EFI_SUCCESS;
746 }
747
748 //
749 // Destroy the interface if this is the last IP instance that
750 // has the address. Remove all the system transmitted packets
751 // from this interface, cancel the receive request if there is
752 // one, and destroy the ARP requests.
753 //
754 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
755 Ip4CancelReceive (Interface);
756
757 ASSERT (IsListEmpty (&Interface->IpInstances));
758 ASSERT (IsListEmpty (&Interface->ArpQues));
759 ASSERT (IsListEmpty (&Interface->SentFrames));
760
761 if (Interface->Arp != NULL) {
762 gBS->CloseProtocol (
763 Interface->ArpHandle,
764 &gEfiArpProtocolGuid,
765 Interface->Image,
766 Interface->Controller
767 );
768
770 Interface->Controller,
771 Interface->Image,
772 &gEfiArpServiceBindingProtocolGuid,
773 Interface->ArpHandle
774 );
775 }
776
777 RemoveEntryList (&Interface->Link);
778 FreePool (Interface);
779
780 return EFI_SUCCESS;
781}
782
795 IN IP4_ARP_QUE *ArpQue
796 )
797{
798 LIST_ENTRY *Entry;
799 LIST_ENTRY *Next;
800 IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
801 IP4_LINK_TX_TOKEN *Token;
802 IP4_ADDR Gateway;
803 EFI_STATUS Status;
804 IP4_ROUTE_ENTRY *DefaultRoute;
805
806 //
807 // ARP resolve failed when using /32 subnet mask.
808 //
809 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
810 RemoveEntryList (Entry);
811 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
812 ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);
813 //
814 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
815 //
816 RtCacheEntry = NULL;
817 if (Token->IpInstance != NULL) {
818 RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
819 }
820
821 if (RtCacheEntry == NULL) {
822 RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
823 }
824
825 if (RtCacheEntry == NULL) {
826 Status = EFI_NO_MAPPING;
827 goto ON_ERROR;
828 }
829
830 DefaultRoute = (IP4_ROUTE_ENTRY *)RtCacheEntry->Tag;
831 if (DefaultRoute == NULL) {
832 Status = EFI_NO_MAPPING;
833 goto ON_ERROR;
834 }
835
836 //
837 // Try to send the frame to the default route.
838 //
839 Gateway = DefaultRoute->NextHop;
840 if (ArpQue->Ip == Gateway) {
841 //
842 // ARP resolve for the default route is failed, return error to caller.
843 //
844 Status = EFI_NO_MAPPING;
845 goto ON_ERROR;
846 }
847
848 RtCacheEntry->NextHop = Gateway;
849 Status = Ip4SendFrame (Token->Interface, Token->IpInstance, Token->Packet, Gateway, Token->CallBack, Token->Context, Token->IpSb);
850 if (EFI_ERROR (Status)) {
851 Status = EFI_NO_MAPPING;
852 goto ON_ERROR;
853 }
854
855 Ip4FreeRouteCacheEntry (RtCacheEntry);
856 }
857
858 return EFI_SUCCESS;
859
860ON_ERROR:
861 if (RtCacheEntry != NULL) {
862 Ip4FreeRouteCacheEntry (RtCacheEntry);
863 }
864
865 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
866 Ip4FreeLinkTxToken (Token);
867 return Status;
868}
869
879VOID
880EFIAPI
882 IN VOID *Context
883 )
884{
885 LIST_ENTRY *Entry;
886 LIST_ENTRY *Next;
887 IP4_ARP_QUE *ArpQue;
888 IP4_INTERFACE *Interface;
889 IP4_LINK_TX_TOKEN *Token;
890 EFI_STATUS Status;
891 EFI_STATUS IoStatus;
892
893 ArpQue = (IP4_ARP_QUE *)Context;
894 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
895
896 RemoveEntryList (&ArpQue->Link);
897
898 //
899 // ARP resolve failed for some reason.
900 //
901 if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {
902 if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {
903 //
904 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
905 // owner back.
906 //
907 IoStatus = EFI_NO_MAPPING;
908 } else {
909 //
910 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
911 // default route.
912 //
913 IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);
914 }
915
916 goto ON_EXIT;
917 }
918
919 //
920 // ARP resolve succeeded, Transmit all the frame. Release the ARP
921 // queue. It isn't necessary for us to cache the ARP binding because
922 // we always check the ARP cache first before transmit.
923 //
924 IoStatus = EFI_SUCCESS;
925 Interface = ArpQue->Interface;
926
927 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
928 RemoveEntryList (Entry);
929
930 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
931 CopyMem (&Token->DstMac, &ArpQue->Mac, sizeof (Token->DstMac));
932
933 //
934 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
935 // may be called before Mnp->Transmit returns which will remove this tx
936 // token from the SentFrames list. Remove it from the list if the returned
937 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
938 // FrameSentDpc won't be queued.
939 //
940 InsertTailList (&Interface->SentFrames, &Token->Link);
941
942 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
943 if (EFI_ERROR (Status)) {
944 RemoveEntryList (&Token->Link);
945 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
946
947 Ip4FreeLinkTxToken (Token);
948 continue;
949 }
950 }
951
952ON_EXIT:
953 Ip4FreeArpQue (ArpQue, IoStatus);
954}
955
964VOID
965EFIAPI
967 IN EFI_EVENT Event,
968 IN VOID *Context
969 )
970{
971 //
972 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
973 //
974 QueueDpc (TPL_CALLBACK, Ip4OnArpResolvedDpc, Context);
975}
976
984VOID
985EFIAPI
987 IN VOID *Context
988 )
989{
990 IP4_LINK_TX_TOKEN *Token;
991
992 Token = (IP4_LINK_TX_TOKEN *)Context;
993 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);
994
995 RemoveEntryList (&Token->Link);
996
997 Token->CallBack (
998 Token->IpInstance,
999 Token->Packet,
1000 Token->MnpToken.Status,
1001 0,
1002 Token->Context
1003 );
1004
1005 Ip4FreeLinkTxToken (Token);
1006}
1007
1015VOID
1016EFIAPI
1018 IN EFI_EVENT Event,
1019 IN VOID *Context
1020 )
1021{
1022 //
1023 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1024 //
1025 QueueDpc (TPL_CALLBACK, Ip4OnFrameSentDpc, Context);
1026}
1027
1053 IN IP4_INTERFACE *Interface,
1054 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1055 IN NET_BUF *Packet,
1056 IN IP4_ADDR NextHop,
1057 IN IP4_FRAME_CALLBACK CallBack,
1058 IN VOID *Context,
1059 IN IP4_SERVICE *IpSb
1060 )
1061{
1062 IP4_LINK_TX_TOKEN *Token;
1063 LIST_ENTRY *Entry;
1064 IP4_ARP_QUE *ArpQue;
1065 EFI_ARP_PROTOCOL *Arp;
1066 EFI_STATUS Status;
1067
1068 ASSERT (Interface->Configured);
1069
1070 Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);
1071
1072 if (Token == NULL) {
1073 return EFI_OUT_OF_RESOURCES;
1074 }
1075
1076 //
1077 // Get the destination MAC address for multicast and broadcasts.
1078 // Don't depend on ARP to solve the address since there maybe no
1079 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1080 // all the broadcasts.
1081 //
1082 if (NextHop == IP4_ALLONE_ADDRESS) {
1083 CopyMem (&Token->DstMac, &Interface->BroadcastMac, sizeof (Token->DstMac));
1084 goto SEND_NOW;
1085 } else if (IP4_IS_MULTICAST (NextHop)) {
1086 Status = Ip4GetMulticastMac (Interface->Mnp, NextHop, &Token->DstMac);
1087
1088 if (EFI_ERROR (Status)) {
1089 goto ON_ERROR;
1090 }
1091
1092 goto SEND_NOW;
1093 }
1094
1095 //
1096 // Can only send out multicast/broadcast if the IP address is zero
1097 //
1098 if ((Arp = Interface->Arp) == NULL) {
1099 Status = EFI_NO_MAPPING;
1100 goto ON_ERROR;
1101 }
1102
1103 //
1104 // First check whether this binding is in the ARP cache.
1105 //
1106 NextHop = HTONL (NextHop);
1107 Status = Arp->Request (Arp, &NextHop, NULL, &Token->DstMac);
1108
1109 if (Status == EFI_SUCCESS) {
1110 goto SEND_NOW;
1111 } else if (Status != EFI_NOT_READY) {
1112 goto ON_ERROR;
1113 }
1114
1115 //
1116 // Have to do asynchronous ARP resolution. First check
1117 // whether there is already a pending request.
1118 //
1119 ArpQue = NULL;
1120
1121 NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
1122 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
1123
1124 if (ArpQue->Ip == NextHop) {
1125 break;
1126 }
1127 }
1128
1129 //
1130 // Found a pending ARP request, enqueue the frame then return
1131 //
1132 if (Entry != &Interface->ArpQues) {
1133 InsertTailList (&ArpQue->Frames, &Token->Link);
1134 return EFI_SUCCESS;
1135 }
1136
1137 //
1138 // First frame to NextHop, issue an asynchronous ARP requests
1139 //
1140 ArpQue = Ip4CreateArpQue (Interface, NextHop);
1141
1142 if (ArpQue == NULL) {
1143 Status = EFI_OUT_OF_RESOURCES;
1144 goto ON_ERROR;
1145 }
1146
1147 Status = Arp->Request (Arp, &ArpQue->Ip, ArpQue->OnResolved, ArpQue->Mac.Addr);
1148
1149 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
1150 Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);
1151 goto ON_ERROR;
1152 }
1153
1154 InsertHeadList (&ArpQue->Frames, &Token->Link);
1155 InsertHeadList (&Interface->ArpQues, &ArpQue->Link);
1156 return EFI_SUCCESS;
1157
1158SEND_NOW:
1159 //
1160 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1161 // Remove it if the returned status is not EFI_SUCCESS.
1162 //
1163 InsertTailList (&Interface->SentFrames, &Token->Link);
1164 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
1165 if (EFI_ERROR (Status)) {
1166 RemoveEntryList (&Token->Link);
1167 goto ON_ERROR;
1168 }
1169
1170 return EFI_SUCCESS;
1171
1172ON_ERROR:
1173 Ip4FreeLinkTxToken (Token);
1174 return Status;
1175}
1176
1184VOID
1185EFIAPI
1187 IN VOID *Context
1188 )
1189{
1190 IP4_LINK_RX_TOKEN *Frame;
1191
1192 Frame = (IP4_LINK_RX_TOKEN *)Context;
1193 NET_CHECK_SIGNATURE (Frame, IP4_FRAME_RX_SIGNATURE);
1194
1195 gBS->SignalEvent (Frame->MnpToken.Packet.RxData->RecycleEvent);
1196 Ip4FreeFrameRxToken (Frame);
1197}
1198
1210VOID
1211EFIAPI
1213 IN VOID *Context
1214 )
1215{
1218 IP4_LINK_RX_TOKEN *Token;
1219 NET_FRAGMENT Netfrag;
1220 NET_BUF *Packet;
1221 UINT32 Flag;
1222
1223 Token = (IP4_LINK_RX_TOKEN *)Context;
1224 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
1225
1226 //
1227 // First clear the interface's receive request in case the
1228 // caller wants to call Ip4ReceiveFrame in the callback.
1229 //
1230 Token->Interface->RecvRequest = NULL;
1231
1232 MnpToken = &Token->MnpToken;
1233 MnpRxData = MnpToken->Packet.RxData;
1234
1235 if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
1236 Token->CallBack (Token->IpInstance, NULL, MnpToken->Status, 0, Token->Context);
1237 Ip4FreeFrameRxToken (Token);
1238
1239 return;
1240 }
1241
1242 //
1243 // Wrap the frame in a net buffer then deliver it to IP input.
1244 // IP will reassemble the packet, and deliver it to upper layer
1245 //
1246 Netfrag.Len = MnpRxData->DataLength;
1247 Netfrag.Bulk = MnpRxData->PacketData;
1248
1249 Packet = NetbufFromExt (&Netfrag, 1, 0, IP4_MAX_HEADLEN, Ip4RecycleFrame, Token);
1250
1251 if (Packet == NULL) {
1252 gBS->SignalEvent (MnpRxData->RecycleEvent);
1253
1254 Token->CallBack (Token->IpInstance, NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
1255 Ip4FreeFrameRxToken (Token);
1256
1257 return;
1258 }
1259
1260 Flag = (MnpRxData->BroadcastFlag ? IP4_LINK_BROADCAST : 0);
1261 Flag |= (MnpRxData->MulticastFlag ? IP4_LINK_MULTICAST : 0);
1262 Flag |= (MnpRxData->PromiscuousFlag ? IP4_LINK_PROMISC : 0);
1263
1264 Token->CallBack (Token->IpInstance, Packet, EFI_SUCCESS, Flag, Token->Context);
1265}
1266
1274VOID
1275EFIAPI
1277 IN EFI_EVENT Event,
1278 IN VOID *Context
1279 )
1280{
1281 //
1282 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1283 //
1284 QueueDpc (TPL_CALLBACK, Ip4OnFrameReceivedDpc, Context);
1285}
1286
1304 IN IP4_INTERFACE *Interface,
1305 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1306 IN IP4_FRAME_CALLBACK CallBack,
1307 IN VOID *Context
1308 )
1309{
1310 IP4_LINK_RX_TOKEN *Token;
1311 EFI_STATUS Status;
1312
1313 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
1314
1315 if (Interface->RecvRequest != NULL) {
1316 return EFI_ALREADY_STARTED;
1317 }
1318
1319 Token = Ip4CreateLinkRxToken (Interface, IpInstance, CallBack, Context);
1320
1321 if (Token == NULL) {
1322 return EFI_OUT_OF_RESOURCES;
1323 }
1324
1325 Interface->RecvRequest = Token;
1326 Status = Interface->Mnp->Receive (Interface->Mnp, &Token->MnpToken);
1327 if (EFI_ERROR (Status)) {
1328 Interface->RecvRequest = NULL;
1329 Ip4FreeFrameRxToken (Token);
1330 return Status;
1331 }
1332
1333 return EFI_SUCCESS;
1334}
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI InsertHeadList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:218
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
EFI_STATUS EFIAPI QueueDpc(IN EFI_TPL DpcTpl, IN EFI_DPC_PROCEDURE DpcProcedure, IN VOID *DpcContext OPTIONAL)
Definition: DpcLib.c:62
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS Ip4GetMulticastMac(IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp, IN IP4_ADDR Multicast, OUT EFI_MAC_ADDRESS *Mac)
Definition: Ip4Common.c:218
EFI_STATUS Ip4FreeInterface(IN IP4_INTERFACE *Interface, IN IP4_PROTOCOL *IpInstance OPTIONAL)
Definition: Ip4If.c:731
BOOLEAN Ip4CancelInstanceFrame(IN IP4_LINK_TX_TOKEN *Frame, IN VOID *Context)
Definition: Ip4If.c:674
VOID EFIAPI Ip4OnFrameReceived(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip4If.c:1276
EFI_STATUS Ip4SendFrameToDefaultRoute(IN IP4_ARP_QUE *ArpQue)
Definition: Ip4If.c:794
VOID EFIAPI Ip4OnArpResolvedDpc(IN VOID *Context)
Definition: Ip4If.c:881
VOID Ip4FreeLinkTxToken(IN IP4_LINK_TX_TOKEN *Token)
Definition: Ip4If.c:218
VOID EFIAPI Ip4OnFrameReceivedDpc(IN VOID *Context)
Definition: Ip4If.c:1212
VOID EFIAPI Ip4OnFrameSentDpc(IN VOID *Context)
Definition: Ip4If.c:986
EFI_STATUS Ip4ReceiveFrame(IN IP4_INTERFACE *Interface, IN IP4_PROTOCOL *IpInstance OPTIONAL, IN IP4_FRAME_CALLBACK CallBack, IN VOID *Context)
Definition: Ip4If.c:1303
IP4_INTERFACE * Ip4CreateInterface(IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp, IN EFI_HANDLE Controller, IN EFI_HANDLE ImageHandle)
Definition: Ip4If.c:477
IP4_LINK_RX_TOKEN * Ip4CreateLinkRxToken(IN IP4_INTERFACE *Interface, IN IP4_PROTOCOL *IpInstance, IN IP4_FRAME_CALLBACK CallBack, IN VOID *Context)
Definition: Ip4If.c:316
EFI_STATUS Ip4SetAddress(IN OUT IP4_INTERFACE *Interface, IN IP4_ADDR IpAddr, IN IP4_ADDR SubnetMask)
Definition: Ip4If.c:547
IP4_LINK_TX_TOKEN * Ip4WrapLinkTxToken(IN IP4_INTERFACE *Interface, IN IP4_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN IP4_FRAME_CALLBACK CallBack, IN VOID *Context, IN IP4_SERVICE *IpSb)
Definition: Ip4If.c:141
VOID Ip4FreeArpQue(IN IP4_ARP_QUE *ArpQue, IN EFI_STATUS IoStatus)
Definition: Ip4If.c:287
EFI_STATUS Ip4SendFrame(IN IP4_INTERFACE *Interface, IN IP4_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN IP4_ADDR NextHop, IN IP4_FRAME_CALLBACK CallBack, IN VOID *Context, IN IP4_SERVICE *IpSb)
Definition: Ip4If.c:1052
VOID Ip4CancelFrames(IN IP4_INTERFACE *Interface, IN EFI_STATUS IoStatus, IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL, IN VOID *Context)
Definition: Ip4If.c:425
VOID EFIAPI Ip4OnFrameSent(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip4If.c:1017
IP4_ARP_QUE * Ip4CreateArpQue(IN IP4_INTERFACE *Interface, IN IP4_ADDR DestIp)
Definition: Ip4If.c:239
VOID EFIAPI Ip4RecycleFrame(IN VOID *Context)
Definition: Ip4If.c:1186
VOID Ip4FreeFrameRxToken(IN IP4_LINK_RX_TOKEN *Token)
Definition: Ip4If.c:366
VOID Ip4CancelReceive(IN IP4_INTERFACE *Interface)
Definition: Ip4If.c:699
VOID EFIAPI Ip4OnArpResolved(IN EFI_EVENT Event, IN VOID *Context)
Definition: Ip4If.c:966
VOID Ip4CancelFrameArp(IN IP4_ARP_QUE *ArpQue, IN EFI_STATUS IoStatus, IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL, IN VOID *Context)
Definition: Ip4If.c:388
VOID(* IP4_FRAME_CALLBACK)(IN IP4_PROTOCOL *IpInstance OPTIONAL, IN NET_BUF *Packet, IN EFI_STATUS IoStatus, IN UINT32 LinkFlag, IN VOID *Context)
Definition: Ip4If.h:42
BOOLEAN(* IP4_FRAME_TO_CANCEL)(IP4_LINK_TX_TOKEN *Frame, VOID *Context)
Definition: Ip4If.h:123
IP4_ROUTE_CACHE_ENTRY * Ip4FindRouteCache(IN IP4_ROUTE_TABLE *RtTable, IN IP4_ADDR Dest, IN IP4_ADDR Src)
Definition: Ip4Route.c:397
VOID Ip4FreeRouteCacheEntry(IN IP4_ROUTE_CACHE_ENTRY *RtCacheEntry)
Definition: Ip4Route.c:113
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
EFI_STATUS EFIAPI NetbufBuildExt(IN NET_BUF *Nbuf, IN OUT NET_FRAGMENT *ExtFragment, IN OUT UINT32 *ExtNum)
Definition: NetBuffer.c:866
EFI_STATUS EFIAPI NetLibCreateServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN OUT EFI_HANDLE *ChildHandle)
Definition: DxeNetLib.c:1967
EFI_STATUS EFIAPI NetLibDestroyServiceChild(IN EFI_HANDLE Controller, IN EFI_HANDLE Image, IN EFI_GUID *ServiceBindingGuid, IN EFI_HANDLE ChildHandle)
Definition: DxeNetLib.c:2020
NET_BUF *EFIAPI NetbufFromExt(IN NET_FRAGMENT *ExtFragment, IN UINT32 ExtNum, IN UINT32 HeadSpace, IN UINT32 HeadLen, IN NET_VECTOR_EXT_FREE ExtFree, IN VOID *Arg OPTIONAL)
Definition: NetBuffer.c:693
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
UINTN EFI_TPL
Definition: UefiBaseType.h:41
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
UINT32 RetryCount
Definition: Arp.h:102
UINT32 RetryTimeOut
Definition: Arp.h:109
UINT16 SwAddressType
Definition: Arp.h:76
VOID * StationAddress
Definition: Arp.h:89
UINT8 SwAddressLength
Definition: Arp.h:81
UINT32 EntryTimeOut
Definition: Arp.h:96
EFI_MANAGED_NETWORK_RECEIVE_DATA * RxData
EFI_MANAGED_NETWORK_TRANSMIT_DATA * TxData
EFI_MAC_ADDRESS CurrentAddress
EFI_MAC_ADDRESS BroadcastAddress