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