Implement IP4 pesudo interface.\r
\r
Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
-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
-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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\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
@retval Token The wrapped token if succeed\r
@retval NULL The wrapped token if NULL\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
Token->Interface = Interface;\r
Token->IpInstance = IpInstance;\r
+ Token->IpSb = IpSb;\r
Token->CallBack = CallBack;\r
Token->Packet = Packet;\r
Token->Context = Context;\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
- 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
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
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
- 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
// 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
}\r
}\r
\r
- Ip4FreeArpQue (ArpQue, EFI_SUCCESS);\r
+ON_EXIT:\r
+ Ip4FreeArpQue (ArpQue, IoStatus);\r
}\r
\r
/**\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
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
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