VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/NetworkPkg/Ip4Dxe/Ip4If.c@ 80721

Last change on this file since 80721 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

  • Property svn:eol-style set to native
File size: 36.5 KB
Line 
1/** @file
2 Implement IP4 pesudo interface.
3
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "Ip4Impl.h"
10
11//
12// Mac address with all zero, used to determine whethter the ARP
13// resolve succeeded. Failed ARP requests zero the MAC address buffer.
14//
15EFI_MAC_ADDRESS mZeroMacAddress;
16
17/**
18 Callback funtion when frame transmission is finished. It will
19 call the frame owner's callback function to tell it the result.
20
21 @param[in] Context Context which is point to the token.
22
23**/
24VOID
25EFIAPI
26Ip4OnFrameSentDpc (
27 IN VOID *Context
28 );
29
30/**
31 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
32
33 @param[in] Event The transmit token's event.
34 @param[in] Context Context which is point to the token.
35
36**/
37VOID
38EFIAPI
39Ip4OnFrameSent (
40 IN EFI_EVENT Event,
41 IN VOID *Context
42 );
43
44/**
45 Callback function when ARP request are finished. It will cancelled
46 all the queued frame if the ARP requests failed. Or transmit them
47 if the request succeed.
48
49 @param[in] Context The context of the callback, a point to the ARP
50 queue
51
52**/
53VOID
54EFIAPI
55Ip4OnArpResolvedDpc (
56 IN VOID *Context
57 );
58
59/**
60 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
61
62 @param Event The Arp request event.
63 @param Context The context of the callback, a point to the ARP
64 queue.
65
66**/
67VOID
68EFIAPI
69Ip4OnArpResolved (
70 IN EFI_EVENT Event,
71 IN VOID *Context
72 );
73
74/**
75 Received a frame from MNP, wrap it in net buffer then deliver
76 it to IP's input function. The ownship of the packet also
77 transferred to IP. When Ip is finished with this packet, it
78 will call NetbufFree to release the packet, NetbufFree will
79 again call the Ip4RecycleFrame to signal MNP's event and free
80 the token used.
81
82 @param Context Context for the callback.
83
84**/
85VOID
86EFIAPI
87Ip4OnFrameReceivedDpc (
88 IN VOID *Context
89 );
90
91/**
92 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
93
94 @param Event The receive event delivered to MNP for receive.
95 @param Context Context for the callback.
96
97**/
98VOID
99EFIAPI
100Ip4OnFrameReceived (
101 IN EFI_EVENT Event,
102 IN VOID *Context
103 );
104
105/**
106 Remove all the frames on the ARP queue that pass the FrameToCancel,
107 that is, either FrameToCancel is NULL or it returns true for the frame.
108
109 @param[in] ArpQue ARP frame to remove the frames from.
110 @param[in] IoStatus The status returned to the cancelled frames'
111 callback function.
112 @param[in] FrameToCancel Function to select which frame to cancel.
113 @param[in] Context Opaque parameter to the FrameToCancel.
114
115**/
116VOID
117Ip4CancelFrameArp (
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
124
125/**
126 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
127
128 @param[in] Interface The interface to send out to.
129 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
130 the packet is sent by the IP4 driver itself.
131 @param[in] Packet The packet to transmit
132 @param[in] CallBack Call back function to execute if transmission
133 finished.
134 @param[in] Context Opaque parameter to the call back.
135 @param[in] IpSb The pointer to the IP4 service binding instance.
136
137 @retval Token The wrapped token if succeed
138 @retval NULL The wrapped token if NULL
139
140**/
141IP4_LINK_TX_TOKEN *
142Ip4WrapLinkTxToken (
143 IN IP4_INTERFACE *Interface,
144 IN IP4_PROTOCOL *IpInstance OPTIONAL,
145 IN NET_BUF *Packet,
146 IN IP4_FRAME_CALLBACK CallBack,
147 IN VOID *Context,
148 IN IP4_SERVICE *IpSb
149 )
150{
151 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
152 EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
153 IP4_LINK_TX_TOKEN *Token;
154 EFI_STATUS Status;
155 UINT32 Count;
156
157 Token = AllocatePool (sizeof (IP4_LINK_TX_TOKEN) + \
158 (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));
159
160 if (Token == NULL) {
161 return NULL;
162 }
163
164 Token->Signature = IP4_FRAME_TX_SIGNATURE;
165 InitializeListHead (&Token->Link);
166
167 Token->Interface = Interface;
168 Token->IpInstance = IpInstance;
169 Token->IpSb = IpSb;
170 Token->CallBack = CallBack;
171 Token->Packet = Packet;
172 Token->Context = Context;
173 CopyMem (&Token->DstMac, &mZeroMacAddress, sizeof (Token->DstMac));
174 CopyMem (&Token->SrcMac, &Interface->Mac, sizeof (Token->SrcMac));
175
176 MnpToken = &(Token->MnpToken);
177 MnpToken->Status = EFI_NOT_READY;
178
179 Status = gBS->CreateEvent (
180 EVT_NOTIFY_SIGNAL,
181 TPL_NOTIFY,
182 Ip4OnFrameSent,
183 Token,
184 &MnpToken->Event
185 );
186
187 if (EFI_ERROR (Status)) {
188 FreePool (Token);
189 return NULL;
190 }
191
192 MnpTxData = &Token->MnpTxData;
193 MnpToken->Packet.TxData = MnpTxData;
194
195 MnpTxData->DestinationAddress = &Token->DstMac;
196 MnpTxData->SourceAddress = &Token->SrcMac;
197 MnpTxData->ProtocolType = IP4_ETHER_PROTO;
198 MnpTxData->DataLength = Packet->TotalSize;
199 MnpTxData->HeaderLength = 0;
200
201 Count = Packet->BlockOpNum;
202
203 NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);
204 MnpTxData->FragmentCount = (UINT16)Count;
205
206 return Token;
207}
208
209
210/**
211 Free the link layer transmit token. It will close the event
212 then free the memory used.
213
214 @param[in] Token Token to free
215
216**/
217VOID
218Ip4FreeLinkTxToken (
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
228
229/**
230 Create an IP_ARP_QUE structure to request ARP service.
231
232 @param[in] Interface The interface to send ARP from.
233 @param[in] DestIp The destination IP (host byte order) to request MAC
234 for
235
236 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
237
238**/
239IP4_ARP_QUE *
240Ip4CreateArpQue (
241 IN IP4_INTERFACE *Interface,
242 IN IP4_ADDR DestIp
243 )
244{
245 IP4_ARP_QUE *ArpQue;
246 EFI_STATUS Status;
247
248 ArpQue = AllocatePool (sizeof (IP4_ARP_QUE));
249
250 if (ArpQue == NULL) {
251 return NULL;
252 }
253
254 ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;
255 InitializeListHead (&ArpQue->Link);
256
257 InitializeListHead (&ArpQue->Frames);
258 ArpQue->Interface = Interface;
259
260 Status = gBS->CreateEvent (
261 EVT_NOTIFY_SIGNAL,
262 TPL_NOTIFY,
263 Ip4OnArpResolved,
264 ArpQue,
265 &ArpQue->OnResolved
266 );
267
268 if (EFI_ERROR (Status)) {
269 FreePool (ArpQue);
270 return NULL;
271 }
272
273 ArpQue->Ip = DestIp;
274 CopyMem (&ArpQue->Mac, &mZeroMacAddress, sizeof (ArpQue->Mac));
275
276 return ArpQue;
277}
278
279
280/**
281 Remove all the transmit requests queued on the ARP queue, then free it.
282
283 @param[in] ArpQue Arp queue to free
284 @param[in] IoStatus The transmit status returned to transmit requests'
285 callback.
286
287**/
288VOID
289Ip4FreeArpQue (
290 IN IP4_ARP_QUE *ArpQue,
291 IN EFI_STATUS IoStatus
292 )
293{
294 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
295
296 //
297 // Remove all the frame waiting the ARP response
298 //
299 Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);
300
301 gBS->CloseEvent (ArpQue->OnResolved);
302 FreePool (ArpQue);
303}
304
305
306/**
307 Create a link layer receive token to wrap the receive request
308
309 @param[in] Interface The interface to receive from
310 @param[in] IpInstance The instance that request the receive (NULL for IP4
311 driver itself)
312 @param[in] CallBack Call back function to execute when finished.
313 @param[in] Context Opaque parameters to the callback
314
315 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
316
317**/
318IP4_LINK_RX_TOKEN *
319Ip4CreateLinkRxToken (
320 IN IP4_INTERFACE *Interface,
321 IN IP4_PROTOCOL *IpInstance,
322 IN IP4_FRAME_CALLBACK CallBack,
323 IN VOID *Context
324 )
325{
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
327 IP4_LINK_RX_TOKEN *Token;
328 EFI_STATUS Status;
329
330 Token = AllocatePool (sizeof (IP4_LINK_RX_TOKEN));
331 if (Token == NULL) {
332 return NULL;
333 }
334
335 Token->Signature = IP4_FRAME_RX_SIGNATURE;
336 Token->Interface = Interface;
337 Token->IpInstance = IpInstance;
338 Token->CallBack = CallBack;
339 Token->Context = Context;
340
341 MnpToken = &Token->MnpToken;
342 MnpToken->Status = EFI_NOT_READY;
343
344 Status = gBS->CreateEvent (
345 EVT_NOTIFY_SIGNAL,
346 TPL_NOTIFY,
347 Ip4OnFrameReceived,
348 Token,
349 &MnpToken->Event
350 );
351
352 if (EFI_ERROR (Status)) {
353 FreePool (Token);
354 return NULL;
355 }
356
357 MnpToken->Packet.RxData = NULL;
358 return Token;
359}
360
361
362/**
363 Free the link layer request token. It will close the event
364 then free the memory used.
365
366 @param[in] Token Request token to free.
367
368**/
369VOID
370Ip4FreeFrameRxToken (
371 IN IP4_LINK_RX_TOKEN *Token
372 )
373{
374
375 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
376
377 gBS->CloseEvent (Token->MnpToken.Event);
378 FreePool (Token);
379}
380
381
382/**
383 Remove all the frames on the ARP queue that pass the FrameToCancel,
384 that is, either FrameToCancel is NULL or it returns true for the frame.
385
386 @param[in] ArpQue ARP frame to remove the frames from.
387 @param[in] IoStatus The status returned to the cancelled frames'
388 callback function.
389 @param[in] FrameToCancel Function to select which frame to cancel.
390 @param[in] Context Opaque parameter to the FrameToCancel.
391
392**/
393VOID
394Ip4CancelFrameArp (
395 IN IP4_ARP_QUE *ArpQue,
396 IN EFI_STATUS IoStatus,
397 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
398 IN VOID *Context
399 )
400{
401 LIST_ENTRY *Entry;
402 LIST_ENTRY *Next;
403 IP4_LINK_TX_TOKEN *Token;
404
405 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
406 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
407
408 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
409 RemoveEntryList (Entry);
410
411 Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);
412 Ip4FreeLinkTxToken (Token);
413 }
414 }
415}
416
417
418/**
419 Remove all the frames on the interface that pass the FrameToCancel,
420 either queued on ARP queues or that have already been delivered to
421 MNP and not yet recycled.
422
423 @param[in] Interface Interface to remove the frames from.
424 @param[in] IoStatus The transmit status returned to the frames'
425 callback.
426 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
427 select all.
428 @param[in] Context Opaque parameters passed to FrameToCancel.
429
430**/
431VOID
432Ip4CancelFrames (
433 IN IP4_INTERFACE *Interface,
434 IN EFI_STATUS IoStatus,
435 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,
436 IN VOID *Context
437 )
438{
439 LIST_ENTRY *Entry;
440 LIST_ENTRY *Next;
441 IP4_ARP_QUE *ArpQue;
442 IP4_LINK_TX_TOKEN *Token;
443
444 //
445 // Cancel all the pending frames on ARP requests
446 //
447 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {
448 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
449
450 Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);
451
452 if (IsListEmpty (&ArpQue->Frames)) {
453 Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);
454 }
455 }
456
457 //
458 // Cancel all the frames that have been delivered to MNP
459 // but not yet recycled.
460 //
461 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {
462 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
463
464 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {
465 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
466 }
467 }
468}
469
470
471/**
472 Create an IP4_INTERFACE. Delay the creation of ARP instance until
473 the interface is configured.
474
475 @param[in] Mnp The shared MNP child of this IP4 service binding
476 instance.
477 @param[in] Controller The controller this IP4 service binding instance
478 is installed. Most like the UNDI handle.
479 @param[in] ImageHandle This driver's image handle.
480
481 @return Point to the created IP4_INTERFACE, otherwise NULL.
482
483**/
484IP4_INTERFACE *
485Ip4CreateInterface (
486 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
487 IN EFI_HANDLE Controller,
488 IN EFI_HANDLE ImageHandle
489 )
490{
491 IP4_INTERFACE *Interface;
492 EFI_SIMPLE_NETWORK_MODE SnpMode;
493
494 Interface = AllocatePool (sizeof (IP4_INTERFACE));
495
496 if ((Interface == NULL) || (Mnp == NULL)) {
497 return NULL;
498 }
499
500 Interface->Signature = IP4_INTERFACE_SIGNATURE;
501 InitializeListHead (&Interface->Link);
502 Interface->RefCnt = 1;
503
504 Interface->Ip = IP4_ALLZERO_ADDRESS;
505 Interface->SubnetMask = IP4_ALLZERO_ADDRESS;
506 Interface->Configured = FALSE;
507
508 Interface->Controller = Controller;
509 Interface->Image = ImageHandle;
510 Interface->Mnp = Mnp;
511 Interface->Arp = NULL;
512 Interface->ArpHandle = NULL;
513
514 InitializeListHead (&Interface->ArpQues);
515 InitializeListHead (&Interface->SentFrames);
516
517 Interface->RecvRequest = NULL;
518
519 //
520 // Get the interface's Mac address and broadcast mac address from SNP
521 //
522 if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {
523 FreePool (Interface);
524 return NULL;
525 }
526
527 CopyMem (&Interface->Mac, &SnpMode.CurrentAddress, sizeof (Interface->Mac));
528 CopyMem (&Interface->BroadcastMac, &SnpMode.BroadcastAddress, sizeof (Interface->BroadcastMac));
529 Interface->HwaddrLen = SnpMode.HwAddressSize;
530
531 InitializeListHead (&Interface->IpInstances);
532 Interface->PromiscRecv = FALSE;
533
534 return Interface;
535}
536
537
538/**
539 Set the interface's address, create and configure
540 the ARP child if necessary.
541
542 @param Interface The interface to set the address.
543 @param IpAddr The interface's IP address.
544 @param SubnetMask The interface's netmask.
545
546 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
547 and a ARP is created for it.
548 @retval Others Failed to set the interface's address.
549
550**/
551EFI_STATUS
552Ip4SetAddress (
553 IN OUT IP4_INTERFACE *Interface,
554 IN IP4_ADDR IpAddr,
555 IN IP4_ADDR SubnetMask
556 )
557{
558 EFI_ARP_CONFIG_DATA ArpConfig;
559 EFI_STATUS Status;
560
561 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
562
563 //
564 // Set the ip/netmask, then compute the subnet broadcast
565 // and network broadcast for easy access. When computing
566 // nework broadcast, the subnet mask is most like longer
567 // than the default netmask (not subneted) as defined in
568 // RFC793. If that isn't the case, we are aggregating the
569 // networks, use the subnet's mask instead.
570 //
571 Interface->Ip = IpAddr;
572 Interface->SubnetMask = SubnetMask;
573 Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);
574 Interface->NetBrdcast = (IpAddr | ~SubnetMask);
575
576 //
577 // Do clean up for Arp child
578 //
579 if (Interface->ArpHandle != NULL) {
580 if (Interface->Arp != NULL) {
581 gBS->CloseProtocol (
582 Interface->ArpHandle,
583 &gEfiArpProtocolGuid,
584 Interface->Image,
585 Interface->Controller
586 );
587
588 Interface->Arp = NULL;
589 }
590
591 NetLibDestroyServiceChild (
592 Interface->Controller,
593 Interface->Image,
594 &gEfiArpServiceBindingProtocolGuid,
595 &Interface->ArpHandle
596 );
597
598 Interface->ArpHandle = NULL;
599 }
600
601 //
602 // If the address is NOT all zero, create then configure an ARP child.
603 // Pay attention: DHCP configures its station address as 0.0.0.0/0
604 //
605 if (IpAddr != IP4_ALLZERO_ADDRESS) {
606 Status = NetLibCreateServiceChild (
607 Interface->Controller,
608 Interface->Image,
609 &gEfiArpServiceBindingProtocolGuid,
610 &Interface->ArpHandle
611 );
612
613 if (EFI_ERROR (Status)) {
614 return Status;
615 }
616
617 Status = gBS->OpenProtocol (
618 Interface->ArpHandle,
619 &gEfiArpProtocolGuid,
620 (VOID **) &Interface->Arp,
621 Interface->Image,
622 Interface->Controller,
623 EFI_OPEN_PROTOCOL_BY_DRIVER
624 );
625
626 if (EFI_ERROR (Status)) {
627 goto ON_ERROR;
628 }
629
630 IpAddr = HTONL (IpAddr);
631 ArpConfig.SwAddressType = IP4_ETHER_PROTO;
632 ArpConfig.SwAddressLength = 4;
633 ArpConfig.StationAddress = &IpAddr;
634 ArpConfig.EntryTimeOut = 0;
635 ArpConfig.RetryCount = 0;
636 ArpConfig.RetryTimeOut = 0;
637
638 Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);
639
640 if (EFI_ERROR (Status)) {
641 gBS->CloseProtocol (
642 Interface->ArpHandle,
643 &gEfiArpProtocolGuid,
644 Interface->Image,
645 Interface->Controller
646 );
647
648 goto ON_ERROR;
649 }
650 }
651
652 Interface->Configured = TRUE;
653 return EFI_SUCCESS;
654
655ON_ERROR:
656 NetLibDestroyServiceChild (
657 Interface->Controller,
658 Interface->Image,
659 &gEfiArpServiceBindingProtocolGuid,
660 &Interface->ArpHandle
661 );
662
663 return Status;
664}
665
666
667/**
668 Filter function to cancel all the frame related to an IP instance.
669
670 @param[in] Frame The transmit request to test whether to cancel
671 @param[in] Context The context which is the Ip instance that issued
672 the transmit.
673
674 @retval TRUE The frame belongs to this instance and is to be
675 removed
676 @retval FALSE The frame doesn't belong to this instance.
677
678**/
679BOOLEAN
680Ip4CancelInstanceFrame (
681 IN IP4_LINK_TX_TOKEN *Frame,
682 IN VOID *Context
683 )
684{
685 if (Frame->IpInstance == (IP4_PROTOCOL *) Context) {
686 return TRUE;
687 }
688
689 return FALSE;
690}
691
692
693
694/**
695 If there is a pending receive request, cancel it. Don't call
696 the receive request's callback because this function can be only
697 called if the instance or driver is tearing itself down. It
698 doesn't make sense to call it back. But it is necessary to call
699 the transmit token's callback to give it a chance to free the
700 packet and update the upper layer's transmit request status, say
701 that from the UDP.
702
703 @param[in] Interface The interface used by the IpInstance
704
705**/
706VOID
707Ip4CancelReceive (
708 IN IP4_INTERFACE *Interface
709 )
710{
711 EFI_TPL OldTpl;
712 IP4_LINK_RX_TOKEN *Token;
713
714 if ((Token = Interface->RecvRequest) != NULL) {
715 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
716
717 Interface->RecvRequest = NULL;
718 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);
719
720 gBS->RestoreTPL (OldTpl);
721 }
722}
723
724
725/**
726 Free the interface used by IpInstance. All the IP instance with
727 the same Ip/Netmask pair share the same interface. It is reference
728 counted. All the frames haven't been sent will be cancelled.
729 Because the IpInstance is optional, the caller must remove
730 IpInstance from the interface's instance list itself.
731
732 @param[in] Interface The interface used by the IpInstance.
733 @param[in] IpInstance The Ip instance that free the interface. NULL if
734 the Ip driver is releasing the default interface.
735
736 @retval EFI_SUCCESS The interface use IpInstance is freed.
737
738**/
739EFI_STATUS
740Ip4FreeInterface (
741 IN IP4_INTERFACE *Interface,
742 IN IP4_PROTOCOL *IpInstance OPTIONAL
743 )
744{
745 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
746 ASSERT (Interface->RefCnt > 0);
747
748 //
749 // Remove all the pending transmit token related to this IP instance.
750 //
751 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
752
753 if (--Interface->RefCnt > 0) {
754 return EFI_SUCCESS;
755 }
756
757 //
758 // Destroy the interface if this is the last IP instance that
759 // has the address. Remove all the system transmitted packets
760 // from this interface, cancel the receive request if there is
761 // one, and destroy the ARP requests.
762 //
763 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
764 Ip4CancelReceive (Interface);
765
766 ASSERT (IsListEmpty (&Interface->IpInstances));
767 ASSERT (IsListEmpty (&Interface->ArpQues));
768 ASSERT (IsListEmpty (&Interface->SentFrames));
769
770 if (Interface->Arp != NULL) {
771 gBS->CloseProtocol (
772 Interface->ArpHandle,
773 &gEfiArpProtocolGuid,
774 Interface->Image,
775 Interface->Controller
776 );
777
778 NetLibDestroyServiceChild (
779 Interface->Controller,
780 Interface->Image,
781 &gEfiArpServiceBindingProtocolGuid,
782 Interface->ArpHandle
783 );
784 }
785
786 RemoveEntryList (&Interface->Link);
787 FreePool (Interface);
788
789 return EFI_SUCCESS;
790}
791
792/**
793 This function tries to send all the queued frames in ArpQue to the default gateway if
794 the ARP resolve for direct destination address is failed when using /32 subnet mask.
795
796 @param[in] ArpQue The ARP queue of a failed request.
797
798 @retval EFI_SUCCESS All the queued frames have been send to the default route.
799 @retval Others Failed to send the queued frames.
800
801**/
802EFI_STATUS
803Ip4SendFrameToDefaultRoute (
804 IN IP4_ARP_QUE *ArpQue
805 )
806{
807 LIST_ENTRY *Entry;
808 LIST_ENTRY *Next;
809 IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;
810 IP4_LINK_TX_TOKEN *Token;
811 IP4_ADDR Gateway;
812 EFI_STATUS Status;
813 IP4_ROUTE_ENTRY *DefaultRoute;
814
815 //
816 // ARP resolve failed when using /32 subnet mask.
817 //
818 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
819 RemoveEntryList (Entry);
820 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
821 ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);
822 //
823 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().
824 //
825 RtCacheEntry = NULL;
826 if (Token->IpInstance != NULL) {
827 RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
828 }
829 if (RtCacheEntry == NULL) {
830 RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);
831 }
832 if (RtCacheEntry == NULL) {
833 Status= EFI_NO_MAPPING;
834 goto ON_ERROR;
835 }
836 DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;
837 if (DefaultRoute == NULL) {
838 Status= EFI_NO_MAPPING;
839 goto ON_ERROR;
840 }
841 //
842 // Try to send the frame to the default route.
843 //
844 Gateway = DefaultRoute->NextHop;
845 if (ArpQue->Ip == Gateway) {
846 //
847 // ARP resolve for the default route is failed, return error to caller.
848 //
849 Status= EFI_NO_MAPPING;
850 goto ON_ERROR;
851 }
852 RtCacheEntry->NextHop = Gateway;
853 Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);
854 if (EFI_ERROR (Status)) {
855 Status= EFI_NO_MAPPING;
856 goto ON_ERROR;
857 }
858 Ip4FreeRouteCacheEntry (RtCacheEntry);
859 }
860
861 return EFI_SUCCESS;
862
863ON_ERROR:
864 if (RtCacheEntry != NULL) {
865 Ip4FreeRouteCacheEntry (RtCacheEntry);
866 }
867 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
868 Ip4FreeLinkTxToken (Token);
869 return Status;
870}
871
872
873/**
874 Callback function when ARP request are finished. It will cancel
875 all the queued frame if the ARP requests failed. Or transmit them
876 if the request succeed.
877
878 @param[in] Context The context of the callback, a point to the ARP
879 queue
880
881**/
882VOID
883EFIAPI
884Ip4OnArpResolvedDpc (
885 IN VOID *Context
886 )
887{
888 LIST_ENTRY *Entry;
889 LIST_ENTRY *Next;
890 IP4_ARP_QUE *ArpQue;
891 IP4_INTERFACE *Interface;
892 IP4_LINK_TX_TOKEN *Token;
893 EFI_STATUS Status;
894 EFI_STATUS IoStatus;
895
896 ArpQue = (IP4_ARP_QUE *) Context;
897 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);
898
899 RemoveEntryList (&ArpQue->Link);
900
901 //
902 // ARP resolve failed for some reason.
903 //
904 if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {
905 if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {
906 //
907 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's
908 // owner back.
909 //
910 IoStatus = EFI_NO_MAPPING;
911 } else {
912 //
913 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the
914 // default route.
915 //
916 IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);
917 }
918 goto ON_EXIT;
919 }
920
921 //
922 // ARP resolve succeeded, Transmit all the frame. Release the ARP
923 // queue. It isn't necessary for us to cache the ARP binding because
924 // we always check the ARP cache first before transmit.
925 //
926 IoStatus = EFI_SUCCESS;
927 Interface = ArpQue->Interface;
928
929 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {
930 RemoveEntryList (Entry);
931
932 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);
933 CopyMem (&Token->DstMac, &ArpQue->Mac, sizeof (Token->DstMac));
934
935 //
936 // Insert the tx token before transmitting it via MNP as the FrameSentDpc
937 // may be called before Mnp->Transmit returns which will remove this tx
938 // token from the SentFrames list. Remove it from the list if the returned
939 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the
940 // FrameSentDpc won't be queued.
941 //
942 InsertTailList (&Interface->SentFrames, &Token->Link);
943
944 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
945 if (EFI_ERROR (Status)) {
946 RemoveEntryList (&Token->Link);
947 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);
948
949 Ip4FreeLinkTxToken (Token);
950 continue;
951 }
952 }
953
954ON_EXIT:
955 Ip4FreeArpQue (ArpQue, IoStatus);
956}
957
958/**
959 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
960
961 @param Event The Arp request event.
962 @param Context The context of the callback, a point to the ARP
963 queue.
964
965**/
966VOID
967EFIAPI
968Ip4OnArpResolved (
969 IN EFI_EVENT Event,
970 IN VOID *Context
971 )
972{
973 //
974 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK
975 //
976 QueueDpc (TPL_CALLBACK, Ip4OnArpResolvedDpc, Context);
977}
978
979
980
981/**
982 Callback funtion when frame transmission is finished. It will
983 call the frame owner's callback function to tell it the result.
984
985 @param[in] Context Context which is point to the token.
986
987**/
988VOID
989EFIAPI
990Ip4OnFrameSentDpc (
991 IN VOID *Context
992 )
993{
994 IP4_LINK_TX_TOKEN *Token;
995
996 Token = (IP4_LINK_TX_TOKEN *) Context;
997 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);
998
999 RemoveEntryList (&Token->Link);
1000
1001 Token->CallBack (
1002 Token->IpInstance,
1003 Token->Packet,
1004 Token->MnpToken.Status,
1005 0,
1006 Token->Context
1007 );
1008
1009 Ip4FreeLinkTxToken (Token);
1010}
1011
1012/**
1013 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1014
1015 @param[in] Event The transmit token's event.
1016 @param[in] Context Context which is point to the token.
1017
1018**/
1019VOID
1020EFIAPI
1021Ip4OnFrameSent (
1022 IN EFI_EVENT Event,
1023 IN VOID *Context
1024 )
1025{
1026 //
1027 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK
1028 //
1029 QueueDpc (TPL_CALLBACK, Ip4OnFrameSentDpc, Context);
1030}
1031
1032
1033
1034/**
1035 Send a frame from the interface. If the next hop is broadcast or
1036 multicast address, it is transmitted immediately. If the next hop
1037 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1038 If some error happened, the CallBack won't be called. So, the caller
1039 must test the return value, and take action when there is an error.
1040
1041 @param[in] Interface The interface to send the frame from
1042 @param[in] IpInstance The IP child that request the transmission. NULL
1043 if it is the IP4 driver itself.
1044 @param[in] Packet The packet to transmit.
1045 @param[in] NextHop The immediate destination to transmit the packet
1046 to.
1047 @param[in] CallBack Function to call back when transmit finished.
1048 @param[in] Context Opaque parameter to the call back.
1049 @param[in] IpSb The pointer to the IP4 service binding instance.
1050
1051 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1052 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1053 @retval EFI_SUCCESS The packet is successfully transmitted.
1054 @retval other Other error occurs.
1055
1056**/
1057EFI_STATUS
1058Ip4SendFrame (
1059 IN IP4_INTERFACE *Interface,
1060 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1061 IN NET_BUF *Packet,
1062 IN IP4_ADDR NextHop,
1063 IN IP4_FRAME_CALLBACK CallBack,
1064 IN VOID *Context,
1065 IN IP4_SERVICE *IpSb
1066 )
1067{
1068 IP4_LINK_TX_TOKEN *Token;
1069 LIST_ENTRY *Entry;
1070 IP4_ARP_QUE *ArpQue;
1071 EFI_ARP_PROTOCOL *Arp;
1072 EFI_STATUS Status;
1073
1074 ASSERT (Interface->Configured);
1075
1076 Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);
1077
1078 if (Token == NULL) {
1079 return EFI_OUT_OF_RESOURCES;
1080 }
1081
1082 //
1083 // Get the destination MAC address for multicast and broadcasts.
1084 // Don't depend on ARP to solve the address since there maybe no
1085 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for
1086 // all the broadcasts.
1087 //
1088 if (NextHop == IP4_ALLONE_ADDRESS) {
1089 CopyMem (&Token->DstMac, &Interface->BroadcastMac, sizeof (Token->DstMac));
1090 goto SEND_NOW;
1091
1092 } else if (IP4_IS_MULTICAST (NextHop)) {
1093
1094 Status = Ip4GetMulticastMac (Interface->Mnp, NextHop, &Token->DstMac);
1095
1096 if (EFI_ERROR (Status)) {
1097 goto ON_ERROR;
1098 }
1099
1100 goto SEND_NOW;
1101 }
1102
1103 //
1104 // Can only send out multicast/broadcast if the IP address is zero
1105 //
1106 if ((Arp = Interface->Arp) == NULL) {
1107 Status = EFI_NO_MAPPING;
1108 goto ON_ERROR;
1109 }
1110
1111 //
1112 // First check whether this binding is in the ARP cache.
1113 //
1114 NextHop = HTONL (NextHop);
1115 Status = Arp->Request (Arp, &NextHop, NULL, &Token->DstMac);
1116
1117 if (Status == EFI_SUCCESS) {
1118 goto SEND_NOW;
1119
1120 } else if (Status != EFI_NOT_READY) {
1121 goto ON_ERROR;
1122 }
1123
1124 //
1125 // Have to do asynchronous ARP resolution. First check
1126 // whether there is already a pending request.
1127 //
1128 ArpQue = NULL;
1129
1130 NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {
1131 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);
1132
1133 if (ArpQue->Ip == NextHop) {
1134 break;
1135 }
1136 }
1137
1138 //
1139 // Found a pending ARP request, enqueue the frame then return
1140 //
1141 if (Entry != &Interface->ArpQues) {
1142 InsertTailList (&ArpQue->Frames, &Token->Link);
1143 return EFI_SUCCESS;
1144 }
1145
1146 //
1147 // First frame to NextHop, issue an asynchronous ARP requests
1148 //
1149 ArpQue = Ip4CreateArpQue (Interface, NextHop);
1150
1151 if (ArpQue == NULL) {
1152 Status = EFI_OUT_OF_RESOURCES;
1153 goto ON_ERROR;
1154 }
1155
1156 Status = Arp->Request (Arp, &ArpQue->Ip, ArpQue->OnResolved, ArpQue->Mac.Addr);
1157
1158 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
1159 Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);
1160 goto ON_ERROR;
1161 }
1162
1163 InsertHeadList (&ArpQue->Frames, &Token->Link);
1164 InsertHeadList (&Interface->ArpQues, &ArpQue->Link);
1165 return EFI_SUCCESS;
1166
1167SEND_NOW:
1168 //
1169 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.
1170 // Remove it if the returned status is not EFI_SUCCESS.
1171 //
1172 InsertTailList (&Interface->SentFrames, &Token->Link);
1173 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);
1174 if (EFI_ERROR (Status)) {
1175 RemoveEntryList (&Token->Link);
1176 goto ON_ERROR;
1177 }
1178
1179 return EFI_SUCCESS;
1180
1181ON_ERROR:
1182 Ip4FreeLinkTxToken (Token);
1183 return Status;
1184}
1185
1186
1187/**
1188 Call back function when the received packet is freed.
1189 Check Ip4OnFrameReceived for information.
1190
1191 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1192
1193**/
1194VOID
1195EFIAPI
1196Ip4RecycleFrame (
1197 IN VOID *Context
1198 )
1199{
1200 IP4_LINK_RX_TOKEN *Frame;
1201
1202 Frame = (IP4_LINK_RX_TOKEN *) Context;
1203 NET_CHECK_SIGNATURE (Frame, IP4_FRAME_RX_SIGNATURE);
1204
1205 gBS->SignalEvent (Frame->MnpToken.Packet.RxData->RecycleEvent);
1206 Ip4FreeFrameRxToken (Frame);
1207}
1208
1209
1210/**
1211 Received a frame from MNP, wrap it in net buffer then deliver
1212 it to IP's input function. The ownship of the packet also
1213 transferred to IP. When Ip is finished with this packet, it
1214 will call NetbufFree to release the packet, NetbufFree will
1215 again call the Ip4RecycleFrame to signal MNP's event and free
1216 the token used.
1217
1218 @param Context Context for the callback.
1219
1220**/
1221VOID
1222EFIAPI
1223Ip4OnFrameReceivedDpc (
1224 IN VOID *Context
1225 )
1226{
1227 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
1228 EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
1229 IP4_LINK_RX_TOKEN *Token;
1230 NET_FRAGMENT Netfrag;
1231 NET_BUF *Packet;
1232 UINT32 Flag;
1233
1234 Token = (IP4_LINK_RX_TOKEN *) Context;
1235 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);
1236
1237 //
1238 // First clear the interface's receive request in case the
1239 // caller wants to call Ip4ReceiveFrame in the callback.
1240 //
1241 Token->Interface->RecvRequest = NULL;
1242
1243 MnpToken = &Token->MnpToken;
1244 MnpRxData = MnpToken->Packet.RxData;
1245
1246 if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {
1247 Token->CallBack (Token->IpInstance, NULL, MnpToken->Status, 0, Token->Context);
1248 Ip4FreeFrameRxToken (Token);
1249
1250 return ;
1251 }
1252
1253 //
1254 // Wrap the frame in a net buffer then deliever it to IP input.
1255 // IP will reassemble the packet, and deliver it to upper layer
1256 //
1257 Netfrag.Len = MnpRxData->DataLength;
1258 Netfrag.Bulk = MnpRxData->PacketData;
1259
1260 Packet = NetbufFromExt (&Netfrag, 1, 0, IP4_MAX_HEADLEN, Ip4RecycleFrame, Token);
1261
1262 if (Packet == NULL) {
1263 gBS->SignalEvent (MnpRxData->RecycleEvent);
1264
1265 Token->CallBack (Token->IpInstance, NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);
1266 Ip4FreeFrameRxToken (Token);
1267
1268 return ;
1269 }
1270
1271 Flag = (MnpRxData->BroadcastFlag ? IP4_LINK_BROADCAST : 0);
1272 Flag |= (MnpRxData->MulticastFlag ? IP4_LINK_MULTICAST : 0);
1273 Flag |= (MnpRxData->PromiscuousFlag ? IP4_LINK_PROMISC : 0);
1274
1275 Token->CallBack (Token->IpInstance, Packet, EFI_SUCCESS, Flag, Token->Context);
1276}
1277
1278/**
1279 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1280
1281 @param Event The receive event delivered to MNP for receive.
1282 @param Context Context for the callback.
1283
1284**/
1285VOID
1286EFIAPI
1287Ip4OnFrameReceived (
1288 IN EFI_EVENT Event,
1289 IN VOID *Context
1290 )
1291{
1292 //
1293 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK
1294 //
1295 QueueDpc (TPL_CALLBACK, Ip4OnFrameReceivedDpc, Context);
1296}
1297
1298
1299/**
1300 Request to receive the packet from the interface.
1301
1302 @param[in] Interface The interface to receive the frames from.
1303 @param[in] IpInstance The instance that requests the receive. NULL for
1304 the driver itself.
1305 @param[in] CallBack Function to call when receive finished.
1306 @param[in] Context Opaque parameter to the callback.
1307
1308 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1309 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1310 @retval EFI_SUCCESS The recieve request has been started.
1311 @retval other Other error occurs.
1312
1313**/
1314EFI_STATUS
1315Ip4ReceiveFrame (
1316 IN IP4_INTERFACE *Interface,
1317 IN IP4_PROTOCOL *IpInstance OPTIONAL,
1318 IN IP4_FRAME_CALLBACK CallBack,
1319 IN VOID *Context
1320 )
1321{
1322 IP4_LINK_RX_TOKEN *Token;
1323 EFI_STATUS Status;
1324
1325 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);
1326
1327 if (Interface->RecvRequest != NULL) {
1328 return EFI_ALREADY_STARTED;
1329 }
1330
1331 Token = Ip4CreateLinkRxToken (Interface, IpInstance, CallBack, Context);
1332
1333 if (Token == NULL) {
1334 return EFI_OUT_OF_RESOURCES;
1335 }
1336
1337 Interface->RecvRequest = Token;
1338 Status = Interface->Mnp->Receive (Interface->Mnp, &Token->MnpToken);
1339 if (EFI_ERROR (Status)) {
1340 Interface->RecvRequest = NULL;
1341 Ip4FreeFrameRxToken (Token);
1342 return Status;
1343 }
1344 return EFI_SUCCESS;
1345}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette