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