]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/Ip4Dxe/Ip4If.c
NetworkPkg: Apply uncrustify changes
[mirror_edk2.git] / NetworkPkg / Ip4Dxe / Ip4If.c
1 /** @file
2 Implement IP4 pseudo interface.
3
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
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 //
15 EFI_MAC_ADDRESS mZeroMacAddress;
16
17 /**
18 Callback function 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 **/
24 VOID
25 EFIAPI
26 Ip4OnFrameSentDpc (
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 **/
37 VOID
38 EFIAPI
39 Ip4OnFrameSent (
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 **/
53 VOID
54 EFIAPI
55 Ip4OnArpResolvedDpc (
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 **/
67 VOID
68 EFIAPI
69 Ip4OnArpResolved (
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 **/
85 VOID
86 EFIAPI
87 Ip4OnFrameReceivedDpc (
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 **/
98 VOID
99 EFIAPI
100 Ip4OnFrameReceived (
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 **/
116 VOID
117 Ip4CancelFrameArp (
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 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.
126
127 @param[in] Interface The interface to send out to.
128 @param[in] IpInstance The IpInstance that transmit the packet. NULL if
129 the packet is sent by the IP4 driver itself.
130 @param[in] Packet The packet to transmit
131 @param[in] CallBack Call back function to execute if transmission
132 finished.
133 @param[in] Context Opaque parameter to the call back.
134 @param[in] IpSb The pointer to the IP4 service binding instance.
135
136 @retval Token The wrapped token if succeed
137 @retval NULL The wrapped token if NULL
138
139 **/
140 IP4_LINK_TX_TOKEN *
141 Ip4WrapLinkTxToken (
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 {
150 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
151 EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;
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,
183 Ip4OnFrameSent,
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
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 **/
217 VOID
218 Ip4FreeLinkTxToken (
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 Create an IP_ARP_QUE structure to request ARP service.
230
231 @param[in] Interface The interface to send ARP from.
232 @param[in] DestIp The destination IP (host byte order) to request MAC
233 for
234
235 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.
236
237 **/
238 IP4_ARP_QUE *
239 Ip4CreateArpQue (
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,
262 Ip4OnArpResolved,
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
278 /**
279 Remove all the transmit requests queued on the ARP queue, then free it.
280
281 @param[in] ArpQue Arp queue to free
282 @param[in] IoStatus The transmit status returned to transmit requests'
283 callback.
284
285 **/
286 VOID
287 Ip4FreeArpQue (
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
303 /**
304 Create a link layer receive token to wrap the receive request
305
306 @param[in] Interface The interface to receive from
307 @param[in] IpInstance The instance that request the receive (NULL for IP4
308 driver itself)
309 @param[in] CallBack Call back function to execute when finished.
310 @param[in] Context Opaque parameters to the callback
311
312 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.
313
314 **/
315 IP4_LINK_RX_TOKEN *
316 Ip4CreateLinkRxToken (
317 IN IP4_INTERFACE *Interface,
318 IN IP4_PROTOCOL *IpInstance,
319 IN IP4_FRAME_CALLBACK CallBack,
320 IN VOID *Context
321 )
322 {
323 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
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,
344 Ip4OnFrameReceived,
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
358 /**
359 Free the link layer request token. It will close the event
360 then free the memory used.
361
362 @param[in] Token Request token to free.
363
364 **/
365 VOID
366 Ip4FreeFrameRxToken (
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
376 /**
377 Remove all the frames on the ARP queue that pass the FrameToCancel,
378 that is, either FrameToCancel is NULL or it returns true for the frame.
379
380 @param[in] ArpQue ARP frame to remove the frames from.
381 @param[in] IoStatus The status returned to the cancelled frames'
382 callback function.
383 @param[in] FrameToCancel Function to select which frame to cancel.
384 @param[in] Context Opaque parameter to the FrameToCancel.
385
386 **/
387 VOID
388 Ip4CancelFrameArp (
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
411 /**
412 Remove all the frames on the interface that pass the FrameToCancel,
413 either queued on ARP queues or that have already been delivered to
414 MNP and not yet recycled.
415
416 @param[in] Interface Interface to remove the frames from.
417 @param[in] IoStatus The transmit status returned to the frames'
418 callback.
419 @param[in] FrameToCancel Function to select the frame to cancel, NULL to
420 select all.
421 @param[in] Context Opaque parameters passed to FrameToCancel.
422
423 **/
424 VOID
425 Ip4CancelFrames (
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
463 /**
464 Create an IP4_INTERFACE. Delay the creation of ARP instance until
465 the interface is configured.
466
467 @param[in] Mnp The shared MNP child of this IP4 service binding
468 instance.
469 @param[in] Controller The controller this IP4 service binding instance
470 is installed. Most like the UNDI handle.
471 @param[in] ImageHandle This driver's image handle.
472
473 @return Point to the created IP4_INTERFACE, otherwise NULL.
474
475 **/
476 IP4_INTERFACE *
477 Ip4CreateInterface (
478 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,
479 IN EFI_HANDLE Controller,
480 IN EFI_HANDLE ImageHandle
481 )
482 {
483 IP4_INTERFACE *Interface;
484 EFI_SIMPLE_NETWORK_MODE SnpMode;
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
533 /**
534 Set the interface's address, create and configure
535 the ARP child if necessary.
536
537 @param Interface The interface to set the address.
538 @param IpAddr The interface's IP address.
539 @param SubnetMask The interface's netmask.
540
541 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,
542 and a ARP is created for it.
543 @retval Others Failed to set the interface's address.
544
545 **/
546 EFI_STATUS
547 Ip4SetAddress (
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
586 NetLibDestroyServiceChild (
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
650 ON_ERROR:
651 NetLibDestroyServiceChild (
652 Interface->Controller,
653 Interface->Image,
654 &gEfiArpServiceBindingProtocolGuid,
655 Interface->ArpHandle
656 );
657
658 return Status;
659 }
660
661 /**
662 Filter function to cancel all the frame related to an IP instance.
663
664 @param[in] Frame The transmit request to test whether to cancel
665 @param[in] Context The context which is the Ip instance that issued
666 the transmit.
667
668 @retval TRUE The frame belongs to this instance and is to be
669 removed
670 @retval FALSE The frame doesn't belong to this instance.
671
672 **/
673 BOOLEAN
674 Ip4CancelInstanceFrame (
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
686 /**
687 If there is a pending receive request, cancel it. Don't call
688 the receive request's callback because this function can be only
689 called if the instance or driver is tearing itself down. It
690 doesn't make sense to call it back. But it is necessary to call
691 the transmit token's callback to give it a chance to free the
692 packet and update the upper layer's transmit request status, say
693 that from the UDP.
694
695 @param[in] Interface The interface used by the IpInstance
696
697 **/
698 VOID
699 Ip4CancelReceive (
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
716 /**
717 Free the interface used by IpInstance. All the IP instance with
718 the same Ip/Netmask pair share the same interface. It is reference
719 counted. All the frames haven't been sent will be cancelled.
720 Because the IpInstance is optional, the caller must remove
721 IpInstance from the interface's instance list itself.
722
723 @param[in] Interface The interface used by the IpInstance.
724 @param[in] IpInstance The Ip instance that free the interface. NULL if
725 the Ip driver is releasing the default interface.
726
727 @retval EFI_SUCCESS The interface use IpInstance is freed.
728
729 **/
730 EFI_STATUS
731 Ip4FreeInterface (
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
769 NetLibDestroyServiceChild (
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
783 /**
784 This function tries to send all the queued frames in ArpQue to the default gateway if
785 the ARP resolve for direct destination address is failed when using /32 subnet mask.
786
787 @param[in] ArpQue The ARP queue of a failed request.
788
789 @retval EFI_SUCCESS All the queued frames have been send to the default route.
790 @retval Others Failed to send the queued frames.
791
792 **/
793 EFI_STATUS
794 Ip4SendFrameToDefaultRoute (
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
860 ON_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
870 /**
871 Callback function when ARP request are finished. It will cancel
872 all the queued frame if the ARP requests failed. Or transmit them
873 if the request succeed.
874
875 @param[in] Context The context of the callback, a point to the ARP
876 queue
877
878 **/
879 VOID
880 EFIAPI
881 Ip4OnArpResolvedDpc (
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
952 ON_EXIT:
953 Ip4FreeArpQue (ArpQue, IoStatus);
954 }
955
956 /**
957 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.
958
959 @param Event The Arp request event.
960 @param Context The context of the callback, a point to the ARP
961 queue.
962
963 **/
964 VOID
965 EFIAPI
966 Ip4OnArpResolved (
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
977 /**
978 Callback function when frame transmission is finished. It will
979 call the frame owner's callback function to tell it the result.
980
981 @param[in] Context Context which is point to the token.
982
983 **/
984 VOID
985 EFIAPI
986 Ip4OnFrameSentDpc (
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
1008 /**
1009 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.
1010
1011 @param[in] Event The transmit token's event.
1012 @param[in] Context Context which is point to the token.
1013
1014 **/
1015 VOID
1016 EFIAPI
1017 Ip4OnFrameSent (
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
1028 /**
1029 Send a frame from the interface. If the next hop is broadcast or
1030 multicast address, it is transmitted immediately. If the next hop
1031 is a unicast, it will consult ARP to resolve the NextHop's MAC.
1032 If some error happened, the CallBack won't be called. So, the caller
1033 must test the return value, and take action when there is an error.
1034
1035 @param[in] Interface The interface to send the frame from
1036 @param[in] IpInstance The IP child that request the transmission. NULL
1037 if it is the IP4 driver itself.
1038 @param[in] Packet The packet to transmit.
1039 @param[in] NextHop The immediate destination to transmit the packet
1040 to.
1041 @param[in] CallBack Function to call back when transmit finished.
1042 @param[in] Context Opaque parameter to the call back.
1043 @param[in] IpSb The pointer to the IP4 service binding instance.
1044
1045 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame
1046 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop
1047 @retval EFI_SUCCESS The packet is successfully transmitted.
1048 @retval other Other error occurs.
1049
1050 **/
1051 EFI_STATUS
1052 Ip4SendFrame (
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
1158 SEND_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
1172 ON_ERROR:
1173 Ip4FreeLinkTxToken (Token);
1174 return Status;
1175 }
1176
1177 /**
1178 Call back function when the received packet is freed.
1179 Check Ip4OnFrameReceived for information.
1180
1181 @param Context Context, which is the IP4_LINK_RX_TOKEN.
1182
1183 **/
1184 VOID
1185 EFIAPI
1186 Ip4RecycleFrame (
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
1199 /**
1200 Received a frame from MNP, wrap it in net buffer then deliver
1201 it to IP's input function. The ownship of the packet also
1202 transferred to IP. When Ip is finished with this packet, it
1203 will call NetbufFree to release the packet, NetbufFree will
1204 again call the Ip4RecycleFrame to signal MNP's event and free
1205 the token used.
1206
1207 @param Context Context for the callback.
1208
1209 **/
1210 VOID
1211 EFIAPI
1212 Ip4OnFrameReceivedDpc (
1213 IN VOID *Context
1214 )
1215 {
1216 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;
1217 EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;
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
1267 /**
1268 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.
1269
1270 @param Event The receive event delivered to MNP for receive.
1271 @param Context Context for the callback.
1272
1273 **/
1274 VOID
1275 EFIAPI
1276 Ip4OnFrameReceived (
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
1287 /**
1288 Request to receive the packet from the interface.
1289
1290 @param[in] Interface The interface to receive the frames from.
1291 @param[in] IpInstance The instance that requests the receive. NULL for
1292 the driver itself.
1293 @param[in] CallBack Function to call when receive finished.
1294 @param[in] Context Opaque parameter to the callback.
1295
1296 @retval EFI_ALREADY_STARTED There is already a pending receive request.
1297 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.
1298 @retval EFI_SUCCESS The receive request has been started.
1299 @retval other Other error occurs.
1300
1301 **/
1302 EFI_STATUS
1303 Ip4ReceiveFrame (
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 }