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