]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4If.c
index 24727b0516aa620928c4d05bb2e8e56fe3bc93fe..44b8d9fc8faf64aeb736eb23e6adc366a908f3ce 100644 (file)
@@ -1,14 +1,8 @@
 /** @file\r
   Implement IP4 pesudo interface.\r
 /** @file\r
   Implement IP4 pesudo interface.\r
-  \r
-Copyright (c) 2005 - 2009, Intel Corporation.<BR>\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
 \r
 \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 \r
 **/\r
 \r
@@ -68,7 +62,7 @@ Ip4OnArpResolvedDpc (
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
-                                \r
+\r
 **/\r
 VOID\r
 EFIAPI\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -138,8 +132,9 @@ Ip4CancelFrameArp (
   @param[in]  CallBack          Call back function to execute if transmission\r
                                 finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
   @param[in]  CallBack          Call back function to execute if transmission\r
                                 finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
+  @param[in]  IpSb              The pointer to the IP4 service binding instance.\r
 \r
 \r
-  @retval   Token               The wrapped token if succeed \r
+  @retval   Token               The wrapped token if succeed\r
   @retval   NULL                The wrapped token if NULL\r
 \r
 **/\r
   @retval   NULL                The wrapped token if NULL\r
 \r
 **/\r
@@ -149,7 +144,8 @@ Ip4WrapLinkTxToken (
   IN IP4_PROTOCOL           *IpInstance     OPTIONAL,\r
   IN NET_BUF                *Packet,\r
   IN IP4_FRAME_CALLBACK     CallBack,\r
   IN IP4_PROTOCOL           *IpInstance     OPTIONAL,\r
   IN NET_BUF                *Packet,\r
   IN IP4_FRAME_CALLBACK     CallBack,\r
-  IN VOID                   *Context\r
+  IN VOID                   *Context,\r
+  IN IP4_SERVICE            *IpSb\r
   )\r
 {\r
   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *MnpToken;\r
   )\r
 {\r
   EFI_MANAGED_NETWORK_COMPLETION_TOKEN  *MnpToken;\r
@@ -170,6 +166,7 @@ Ip4WrapLinkTxToken (
 \r
   Token->Interface  = Interface;\r
   Token->IpInstance = IpInstance;\r
 \r
   Token->Interface  = Interface;\r
   Token->IpInstance = IpInstance;\r
+  Token->IpSb       = IpSb;\r
   Token->CallBack   = CallBack;\r
   Token->Packet     = Packet;\r
   Token->Context    = Context;\r
   Token->CallBack   = CallBack;\r
   Token->Packet     = Packet;\r
   Token->Context    = Context;\r
@@ -188,7 +185,7 @@ Ip4WrapLinkTxToken (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (Token);\r
+    FreePool (Token);\r
     return NULL;\r
   }\r
 \r
     return NULL;\r
   }\r
 \r
@@ -225,7 +222,7 @@ Ip4FreeLinkTxToken (
   NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
 \r
   gBS->CloseEvent (Token->MnpToken.Event);\r
   NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
 \r
   gBS->CloseEvent (Token->MnpToken.Event);\r
-  gBS->FreePool (Token);\r
+  FreePool (Token);\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -269,7 +266,7 @@ Ip4CreateArpQue (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (ArpQue);\r
+    FreePool (ArpQue);\r
     return NULL;\r
   }\r
 \r
     return NULL;\r
   }\r
 \r
@@ -302,7 +299,7 @@ Ip4FreeArpQue (
   Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);\r
 \r
   gBS->CloseEvent (ArpQue->OnResolved);\r
   Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);\r
 \r
   gBS->CloseEvent (ArpQue->OnResolved);\r
-  gBS->FreePool (ArpQue);\r
+  FreePool (ArpQue);\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -353,7 +350,7 @@ Ip4CreateLinkRxToken (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    gBS->FreePool (Token);\r
+    FreePool (Token);\r
     return NULL;\r
   }\r
 \r
     return NULL;\r
   }\r
 \r
@@ -378,7 +375,7 @@ Ip4FreeFrameRxToken (
   NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
 \r
   gBS->CloseEvent (Token->MnpToken.Event);\r
   NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
 \r
   gBS->CloseEvent (Token->MnpToken.Event);\r
-  gBS->FreePool (Token);\r
+  FreePool (Token);\r
 }\r
 \r
 \r
 }\r
 \r
 \r
@@ -423,12 +420,12 @@ Ip4CancelFrameArp (
   either queued on ARP queues or that have already been delivered to\r
   MNP and not yet recycled.\r
 \r
   either queued on ARP queues or that have already been delivered to\r
   MNP and not yet recycled.\r
 \r
-  @param[in]  Interface         Interface to remove the frames from\r
+  @param[in]  Interface         Interface to remove the frames from.\r
   @param[in]  IoStatus          The transmit status returned to the frames'\r
   @param[in]  IoStatus          The transmit status returned to the frames'\r
-                                callback\r
+                                callback.\r
   @param[in]  FrameToCancel     Function to select the frame to cancel, NULL to\r
   @param[in]  FrameToCancel     Function to select the frame to cancel, NULL to\r
-                                select all\r
-  @param[in]  Context           Opaque parameters passed to FrameToCancel\r
+                                select all.\r
+  @param[in]  Context           Opaque parameters passed to FrameToCancel.\r
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
@@ -476,10 +473,10 @@ Ip4CancelFrames (
   the interface is configured.\r
 \r
   @param[in]  Mnp               The shared MNP child of this IP4 service binding\r
   the interface is configured.\r
 \r
   @param[in]  Mnp               The shared MNP child of this IP4 service binding\r
-                                instance\r
+                                instance.\r
   @param[in]  Controller        The controller this IP4 service binding instance\r
                                 is installed. Most like the UNDI handle.\r
   @param[in]  Controller        The controller this IP4 service binding instance\r
                                 is installed. Most like the UNDI handle.\r
-  @param[in]  ImageHandle       This driver's image handle\r
+  @param[in]  ImageHandle       This driver's image handle.\r
 \r
   @return Point to the created IP4_INTERFACE, otherwise NULL.\r
 \r
 \r
   @return Point to the created IP4_INTERFACE, otherwise NULL.\r
 \r
@@ -523,7 +520,7 @@ Ip4CreateInterface (
   // Get the interface's Mac address and broadcast mac address from SNP\r
   //\r
   if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {\r
   // Get the interface's Mac address and broadcast mac address from SNP\r
   //\r
   if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {\r
-    gBS->FreePool (Interface);\r
+    FreePool (Interface);\r
     return NULL;\r
   }\r
 \r
     return NULL;\r
   }\r
 \r
@@ -542,9 +539,9 @@ Ip4CreateInterface (
   Set the interface's address, create and configure\r
   the ARP child if necessary.\r
 \r
   Set the interface's address, create and configure\r
   the ARP child if necessary.\r
 \r
-  @param  Interface         The interface to set the address\r
-  @param  IpAddr            The interface's IP address\r
-  @param  SubnetMask        The interface's netmask\r
+  @param  Interface         The interface to set the address.\r
+  @param  IpAddr            The interface's IP address.\r
+  @param  SubnetMask        The interface's netmask.\r
 \r
   @retval EFI_SUCCESS           The interface is configured with Ip/netmask pair,\r
                                 and a ARP is created for it.\r
 \r
   @retval EFI_SUCCESS           The interface is configured with Ip/netmask pair,\r
                                 and a ARP is created for it.\r
@@ -560,14 +557,9 @@ Ip4SetAddress (
 {\r
   EFI_ARP_CONFIG_DATA       ArpConfig;\r
   EFI_STATUS                Status;\r
 {\r
   EFI_ARP_CONFIG_DATA       ArpConfig;\r
   EFI_STATUS                Status;\r
-  INTN                      Type;\r
-  INTN                      Len;\r
-  IP4_ADDR                  Netmask;\r
 \r
   NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
 \r
 \r
   NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
 \r
-  ASSERT (!Interface->Configured);\r
-\r
   //\r
   // Set the ip/netmask, then compute the subnet broadcast\r
   // and network broadcast for easy access. When computing\r
   //\r
   // Set the ip/netmask, then compute the subnet broadcast\r
   // and network broadcast for easy access. When computing\r
@@ -579,19 +571,37 @@ Ip4SetAddress (
   Interface->Ip             = IpAddr;\r
   Interface->SubnetMask     = SubnetMask;\r
   Interface->SubnetBrdcast  = (IpAddr | ~SubnetMask);\r
   Interface->Ip             = IpAddr;\r
   Interface->SubnetMask     = SubnetMask;\r
   Interface->SubnetBrdcast  = (IpAddr | ~SubnetMask);\r
+  Interface->NetBrdcast     = (IpAddr | ~SubnetMask);\r
+\r
+  //\r
+  // Do clean up for Arp child\r
+  //\r
+  if (Interface->ArpHandle != NULL) {\r
+    if (Interface->Arp != NULL) {\r
+      gBS->CloseProtocol (\r
+             Interface->ArpHandle,\r
+             &gEfiArpProtocolGuid,\r
+             Interface->Image,\r
+             Interface->Controller\r
+             );\r
+\r
+      Interface->Arp = NULL;\r
+    }\r
 \r
 \r
-  Type                      = NetGetIpClass (IpAddr);\r
-  Len                       = NetGetMaskLength (SubnetMask);\r
-  Netmask                   = gIp4AllMasks[MIN ((Len - 1), Type << 3)];\r
-  Interface->NetBrdcast     = (IpAddr | ~Netmask);\r
+    NetLibDestroyServiceChild (\r
+      Interface->Controller,\r
+      Interface->Image,\r
+      &gEfiArpServiceBindingProtocolGuid,\r
+      &Interface->ArpHandle\r
+      );\r
+\r
+    Interface->ArpHandle = NULL;\r
+  }\r
 \r
   //\r
   // If the address is NOT all zero, create then configure an ARP child.\r
   // Pay attention: DHCP configures its station address as 0.0.0.0/0\r
   //\r
 \r
   //\r
   // If the address is NOT all zero, create then configure an ARP child.\r
   // Pay attention: DHCP configures its station address as 0.0.0.0/0\r
   //\r
-  Interface->Arp            = NULL;\r
-  Interface->ArpHandle      = NULL;\r
-\r
   if (IpAddr != IP4_ALLZERO_ADDRESS) {\r
     Status = NetLibCreateServiceChild (\r
                Interface->Controller,\r
   if (IpAddr != IP4_ALLZERO_ADDRESS) {\r
     Status = NetLibCreateServiceChild (\r
                Interface->Controller,\r
@@ -601,7 +611,7 @@ Ip4SetAddress (
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
-      return Status;;\r
+      return Status;\r
     }\r
 \r
     Status = gBS->OpenProtocol (\r
     }\r
 \r
     Status = gBS->OpenProtocol (\r
@@ -629,11 +639,11 @@ Ip4SetAddress (
 \r
     if (EFI_ERROR (Status)) {\r
       gBS->CloseProtocol (\r
 \r
     if (EFI_ERROR (Status)) {\r
       gBS->CloseProtocol (\r
-            Interface->ArpHandle,\r
-            &gEfiArpProtocolGuid,\r
-            Interface->Image,\r
-            Interface->Controller\r
-            );\r
+             Interface->ArpHandle,\r
+             &gEfiArpProtocolGuid,\r
+             Interface->Image,\r
+             Interface->Controller\r
+             );\r
 \r
       goto ON_ERROR;\r
     }\r
 \r
       goto ON_ERROR;\r
     }\r
@@ -719,7 +729,7 @@ Ip4CancelReceive (
   Because the IpInstance is optional, the caller must remove\r
   IpInstance from the interface's instance list itself.\r
 \r
   Because the IpInstance is optional, the caller must remove\r
   IpInstance from the interface's instance list itself.\r
 \r
-  @param[in]  Interface         The interface used by the IpInstance\r
+  @param[in]  Interface         The interface used by the IpInstance.\r
   @param[in]  IpInstance        The Ip instance that free the interface. NULL if\r
                                 the Ip driver is releasing the default interface.\r
 \r
   @param[in]  IpInstance        The Ip instance that free the interface. NULL if\r
                                 the Ip driver is releasing the default interface.\r
 \r
@@ -745,10 +755,10 @@ Ip4FreeInterface (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Destory the interface if this is the last IP instance that\r
+  // Destroy the interface if this is the last IP instance that\r
   // has the address. Remove all the system transmitted packets\r
   // from this interface, cancel the receive request if there is\r
   // has the address. Remove all the system transmitted packets\r
   // from this interface, cancel the receive request if there is\r
-  // one, and destory the ARP requests.\r
+  // one, and destroy the ARP requests.\r
   //\r
   Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);\r
   Ip4CancelReceive (Interface);\r
   //\r
   Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);\r
   Ip4CancelReceive (Interface);\r
@@ -774,14 +784,94 @@ Ip4FreeInterface (
   }\r
 \r
   RemoveEntryList (&Interface->Link);\r
   }\r
 \r
   RemoveEntryList (&Interface->Link);\r
-  gBS->FreePool (Interface);\r
+  FreePool (Interface);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  This function tries to send all the queued frames in ArpQue to the default gateway if\r
+  the ARP resolve for direct destination address is failed when using /32 subnet mask.\r
+\r
+  @param[in]   ArpQue           The ARP queue of a failed request.\r
+\r
+  @retval EFI_SUCCESS           All the queued frames have been send to the default route.\r
+  @retval Others                Failed to send the queued frames.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip4SendFrameToDefaultRoute (\r
+  IN  IP4_ARP_QUE               *ArpQue\r
+  )\r
+{\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
+  IP4_ROUTE_CACHE_ENTRY     *RtCacheEntry;\r
+  IP4_LINK_TX_TOKEN         *Token;\r
+  IP4_ADDR                  Gateway;\r
+  EFI_STATUS                Status;\r
+  IP4_ROUTE_ENTRY           *DefaultRoute;\r
+\r
+  //\r
+  // ARP resolve failed when using /32 subnet mask.\r
+  //\r
+  NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
+    RemoveEntryList (Entry);\r
+    Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
+    ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);\r
+    //\r
+    // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().\r
+    //\r
+    RtCacheEntry = NULL;\r
+    if (Token->IpInstance != NULL) {\r
+      RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
+    }\r
+    if (RtCacheEntry == NULL) {\r
+      RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
+    }\r
+    if (RtCacheEntry == NULL) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;\r
+    if (DefaultRoute == NULL) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    //\r
+    // Try to send the frame to the default route.\r
+    //\r
+    Gateway = DefaultRoute->NextHop;\r
+    if (ArpQue->Ip == Gateway) {\r
+      //\r
+      // ARP resolve for the default route is failed, return error to caller.\r
+      //\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    RtCacheEntry->NextHop = Gateway;\r
+    Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);\r
+    if (EFI_ERROR (Status)) {\r
+      Status= EFI_NO_MAPPING;\r
+      goto ON_ERROR;\r
+    }\r
+    Ip4FreeRouteCacheEntry (RtCacheEntry);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+  if (RtCacheEntry != NULL) {\r
+    Ip4FreeRouteCacheEntry (RtCacheEntry);\r
+  }\r
+  Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
+  Ip4FreeLinkTxToken (Token);\r
+  return Status;\r
+}\r
+\r
 \r
 /**\r
 \r
 /**\r
-  Callback function when ARP request are finished. It will cancelled\r
+  Callback function when ARP request are finished. It will cancel\r
   all the queued frame if the ARP requests failed. Or transmit them\r
   if the request succeed.\r
 \r
   all the queued frame if the ARP requests failed. Or transmit them\r
   if the request succeed.\r
 \r
@@ -801,6 +891,7 @@ Ip4OnArpResolvedDpc (
   IP4_INTERFACE             *Interface;\r
   IP4_LINK_TX_TOKEN         *Token;\r
   EFI_STATUS                Status;\r
   IP4_INTERFACE             *Interface;\r
   IP4_LINK_TX_TOKEN         *Token;\r
   EFI_STATUS                Status;\r
+  EFI_STATUS                IoStatus;\r
 \r
   ArpQue = (IP4_ARP_QUE *) Context;\r
   NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
 \r
   ArpQue = (IP4_ARP_QUE *) Context;\r
   NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
@@ -808,14 +899,23 @@ Ip4OnArpResolvedDpc (
   RemoveEntryList (&ArpQue->Link);\r
 \r
   //\r
   RemoveEntryList (&ArpQue->Link);\r
 \r
   //\r
-  // ARP resolve failed for some reason. Release all the frame\r
-  // and ARP queue itself. Ip4FreeArpQue will call the frame's\r
-  // owner back.\r
+  // ARP resolve failed for some reason.\r
   //\r
   if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {\r
   //\r
   if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {\r
-    Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);\r
-\r
-    return ;\r
+    if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {\r
+      //\r
+      // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's\r
+      // owner back.\r
+      //\r
+      IoStatus = EFI_NO_MAPPING;\r
+    } else {\r
+      //\r
+      // ARP resolve failed when using 32bit subnet mask, try to send the packets to the\r
+      // default route.\r
+      //\r
+      IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);\r
+    }\r
+    goto ON_EXIT;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -823,6 +923,7 @@ Ip4OnArpResolvedDpc (
   // queue. It isn't necessary for us to cache the ARP binding because\r
   // we always check the ARP cache first before transmit.\r
   //\r
   // queue. It isn't necessary for us to cache the ARP binding because\r
   // we always check the ARP cache first before transmit.\r
   //\r
+  IoStatus = EFI_SUCCESS;\r
   Interface = ArpQue->Interface;\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
   Interface = ArpQue->Interface;\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
@@ -842,7 +943,7 @@ Ip4OnArpResolvedDpc (
 \r
     Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
     if (EFI_ERROR (Status)) {\r
 \r
     Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
     if (EFI_ERROR (Status)) {\r
-      RemoveEntryList (Entry);\r
+      RemoveEntryList (&Token->Link);\r
       Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
 \r
       Ip4FreeLinkTxToken (Token);\r
       Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
 \r
       Ip4FreeLinkTxToken (Token);\r
@@ -850,7 +951,8 @@ Ip4OnArpResolvedDpc (
     }\r
   }\r
 \r
     }\r
   }\r
 \r
-  Ip4FreeArpQue (ArpQue, EFI_SUCCESS);\r
+ON_EXIT:\r
+  Ip4FreeArpQue (ArpQue, IoStatus);\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -859,7 +961,7 @@ Ip4OnArpResolvedDpc (
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
   @param  Event             The Arp request event.\r
   @param  Context           The context of the callback, a point to the ARP\r
                             queue.\r
-                                \r
+\r
 **/\r
 VOID\r
 EFIAPI\r
 **/\r
 VOID\r
 EFIAPI\r
@@ -944,6 +1046,7 @@ Ip4OnFrameSent (
                                 to.\r
   @param[in]  CallBack          Function to call back when transmit finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
                                 to.\r
   @param[in]  CallBack          Function to call back when transmit finished.\r
   @param[in]  Context           Opaque parameter to the call back.\r
+  @param[in]  IpSb              The pointer to the IP4 service binding instance.\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to send the frame\r
   @retval EFI_NO_MAPPING        Can't resolve the MAC for the nexthop\r
 \r
   @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to send the frame\r
   @retval EFI_NO_MAPPING        Can't resolve the MAC for the nexthop\r
@@ -958,7 +1061,8 @@ Ip4SendFrame (
   IN  NET_BUF               *Packet,\r
   IN  IP4_ADDR              NextHop,\r
   IN  IP4_FRAME_CALLBACK    CallBack,\r
   IN  NET_BUF               *Packet,\r
   IN  IP4_ADDR              NextHop,\r
   IN  IP4_FRAME_CALLBACK    CallBack,\r
-  IN  VOID                  *Context\r
+  IN  VOID                  *Context,\r
+  IN IP4_SERVICE            *IpSb\r
   )\r
 {\r
   IP4_LINK_TX_TOKEN         *Token;\r
   )\r
 {\r
   IP4_LINK_TX_TOKEN         *Token;\r
@@ -969,7 +1073,7 @@ Ip4SendFrame (
 \r
   ASSERT (Interface->Configured);\r
 \r
 \r
   ASSERT (Interface->Configured);\r
 \r
-  Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context);\r
+  Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);\r
 \r
   if (Token == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
 \r
   if (Token == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -1068,7 +1172,7 @@ SEND_NOW:
   InsertTailList (&Interface->SentFrames, &Token->Link);\r
   Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
   if (EFI_ERROR (Status)) {\r
   InsertTailList (&Interface->SentFrames, &Token->Link);\r
   Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
   if (EFI_ERROR (Status)) {\r
-    RemoveEntryList (&Interface->SentFrames);\r
+    RemoveEntryList (&Token->Link);\r
     goto ON_ERROR;\r
   }\r
 \r
     goto ON_ERROR;\r
   }\r
 \r
@@ -1088,6 +1192,7 @@ ON_ERROR:
 \r
 **/\r
 VOID\r
 \r
 **/\r
 VOID\r
+EFIAPI\r
 Ip4RecycleFrame (\r
   IN VOID                   *Context\r
   )\r
 Ip4RecycleFrame (\r
   IN VOID                   *Context\r
   )\r
@@ -1194,14 +1299,14 @@ Ip4OnFrameReceived (
 /**\r
   Request to receive the packet from the interface.\r
 \r
 /**\r
   Request to receive the packet from the interface.\r
 \r
-  @param[in]  Interface         The interface to receive the frames from\r
+  @param[in]  Interface         The interface to receive the frames from.\r
   @param[in]  IpInstance        The instance that requests the receive. NULL for\r
                                 the driver itself.\r
   @param[in]  CallBack          Function to call when receive finished.\r
   @param[in]  IpInstance        The instance that requests the receive. NULL for\r
                                 the driver itself.\r
   @param[in]  CallBack          Function to call when receive finished.\r
-  @param[in]  Context           Opaque parameter to the callback\r
+  @param[in]  Context           Opaque parameter to the callback.\r
 \r
   @retval EFI_ALREADY_STARTED   There is already a pending receive request.\r
 \r
   @retval EFI_ALREADY_STARTED   There is already a pending receive request.\r
-  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive\r
+  @retval EFI_OUT_OF_RESOURCES  Failed to allocate resource to receive.\r
   @retval EFI_SUCCESS           The recieve request has been started.\r
   @retval other                 Other error occurs.\r
 \r
   @retval EFI_SUCCESS           The recieve request has been started.\r
   @retval other                 Other error occurs.\r
 \r