summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>2013-03-11 08:04:39 +0000
committersfu5 <sfu5@6f19259b-4bc3-4df7-8a09-765794883524>2013-03-11 08:04:39 +0000
commitf14912942917a885d9ae74bafdcafc387d517aca (patch)
tree1d5d1cb26ced520deb9cba8ba92ff19d98d930fe
parentb9f256bbe900626f0dd695ea2ccae21956564b88 (diff)
downloadedk2-platforms-f14912942917a885d9ae74bafdcafc387d517aca.tar.xz
Fix a bug in IP4 driver which may cause “reconnect –r” hang.
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Ye Ting <ting.ye@intel.com> Reviewed-by: Ouyang Qian <qian.ouyang@intel.com> git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@14170 6f19259b-4bc3-4df7-8a09-765794883524
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c38
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c29
2 files changed, 48 insertions, 19 deletions
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
index 224244164e..6711636333 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4If.c
@@ -1,7 +1,7 @@
/** @file
Implement IP4 pesudo interface.
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -740,24 +740,11 @@ Ip4FreeInterface (
//
Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);
- if (--Interface->RefCnt > 0) {
- return EFI_SUCCESS;
- }
-
//
- // Destroy the interface if this is the last IP instance that
- // has the address. Remove all the system transmitted packets
- // from this interface, cancel the receive request if there is
- // one, and destroy the ARP requests.
+ // Destroy the ARP instance if this is the last IP instance that
+ // has the address.
//
- Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
- Ip4CancelReceive (Interface);
-
- ASSERT (IsListEmpty (&Interface->IpInstances));
- ASSERT (IsListEmpty (&Interface->ArpQues));
- ASSERT (IsListEmpty (&Interface->SentFrames));
-
- if (Interface->Arp != NULL) {
+ if (Interface->Arp != NULL && IsListEmpty (&Interface->IpInstances)) {
gBS->CloseProtocol (
Interface->ArpHandle,
&gEfiArpProtocolGuid,
@@ -771,8 +758,25 @@ Ip4FreeInterface (
&gEfiArpServiceBindingProtocolGuid,
Interface->ArpHandle
);
+ Interface->Arp = NULL;
+ }
+
+ if (--Interface->RefCnt > 0) {
+ return EFI_SUCCESS;
}
+ //
+ // Destroy the interface if it is not referenced by any IP instance (for common Interface)
+ // or the IP service (for the DefaultInterface). Remove all the system transmitted packets
+ // from this interface, cancel the receive request if there is one.
+ //
+ Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);
+ Ip4CancelReceive (Interface);
+
+ ASSERT (IsListEmpty (&Interface->IpInstances));
+ ASSERT (IsListEmpty (&Interface->ArpQues));
+ ASSERT (IsListEmpty (&Interface->SentFrames));
+
RemoveEntryList (&Interface->Link);
FreePool (Interface);
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
index 74bf7f76eb..29f07ce4a3 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c
@@ -1,6 +1,6 @@
/** @file
-Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2005 - 2013, Intel Corporation. All rights reserved.<BR>
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
@@ -562,6 +562,9 @@ Ip4AutoConfigCallBackDpc (
IP4_ADDR SubnetMask;
IP4_ADDR SubnetAddress;
IP4_ADDR GatewayAddress;
+ IP4_PROTOCOL *Ip4Instance;
+ EFI_ARP_PROTOCOL *Arp;
+ LIST_ENTRY *Entry;
IpSb = (IP4_SERVICE *) Context;
NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);
@@ -650,11 +653,33 @@ Ip4AutoConfigCallBackDpc (
StationAddress = EFI_NTOHL (Data->StationAddress);
SubnetMask = EFI_NTOHL (Data->SubnetMask);
Status = Ip4SetAddress (IpIf, StationAddress, SubnetMask);
-
if (EFI_ERROR (Status)) {
goto ON_EXIT;
}
+ if (IpIf->Arp != NULL) {
+ //
+ // A non-NULL IpIf->Arp here means a new ARP child is created when setting default address,
+ // but some IP children may have referenced the default interface before it is configured,
+ // these IP instances also consume this ARP protocol so they need to open it BY_CHILD_CONTROLLER.
+ //
+ Arp = NULL;
+ NET_LIST_FOR_EACH (Entry, &IpIf->IpInstances) {
+ Ip4Instance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, AddrLink, IP4_PROTOCOL_SIGNATURE);
+ Status = gBS->OpenProtocol (
+ IpIf->ArpHandle,
+ &gEfiArpProtocolGuid,
+ (VOID **) &Arp,
+ gIp4DriverBinding.DriverBindingHandle,
+ Ip4Instance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+ }
+ }
+
Ip4AddRoute (
IpSb->DefaultRouteTable,
StationAddress,