Remove duplicate DAD entry in IP6 driver to fix DAD fail issue.
authorFu Siyuan <siyuan.fu@intel.com>
Wed, 29 Apr 2015 05:47:03 +0000 (05:47 +0000)
committersfu5 <sfu5@Edk2>
Wed, 29 Apr 2015 05:47:03 +0000 (05:47 +0000)
The IP6 driver may create duplicate IP6_DAD_ENTRY in DupAddrDetectList in some situation like:
1. Address policy switch but not clear the delay node list, OR
2. Set manual address repeatedly before the previous DAD is finished.
The NS sent out by duplicate DAD entry will mix up with the loop back multicast packet, result in DAD fail.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Fu Siyuan <siyuan.fu@intel.com>
Reviewed-by: Ye Ting <ting.ye@intel.com>
Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17263 6f19259b-4bc3-4df7-8a09-765794883524

NetworkPkg/Ip6Dxe/Ip6ConfigImpl.c
NetworkPkg/Ip6Dxe/Ip6Nd.c

index 9a1e3d076f6a021829a8b28310a5ae828fca7be3..75d4f23fb003068d78e8584deb3b60eee0a4b889 100644 (file)
@@ -52,7 +52,8 @@ Ip6ConfigOnPolicyChanged (
   LIST_ENTRY      *Next;\r
   IP6_INTERFACE   *IpIf;\r
   IP6_DAD_ENTRY   *DadEntry;\r
-\r
+  IP6_DELAY_JOIN_LIST       *DelayNode;\r
+  \r
   //\r
   // Currently there are only two policies: Manual and Automatic. Regardless of\r
   // what transition is going on, i.e., Manual -> Automatic and Automatic ->\r
@@ -94,10 +95,18 @@ Ip6ConfigOnPolicyChanged (
 \r
   NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
     //\r
-    // remove all pending DAD entries for the global addresses.\r
+    // remove all pending delay node and DAD entries for the global addresses.\r
     //\r
     IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
 \r
+    NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DelayJoinList) {\r
+      DelayNode = NET_LIST_USER_STRUCT (Entry2, IP6_DELAY_JOIN_LIST, Link);\r
+      if (!NetIp6IsLinkLocalAddr (&DelayNode->AddressInfo->Address)) {\r
+        RemoveEntryList (&DelayNode->Link);\r
+        FreePool (DelayNode);\r
+      }\r
+    }\r
+\r
     NET_LIST_FOR_EACH_SAFE (Entry2, Next, &IpIf->DupAddrDetectList) {\r
       DadEntry = NET_LIST_USER_STRUCT_S (Entry2, IP6_DAD_ENTRY, Link, IP6_DAD_ENTRY_SIGNATURE);\r
 \r
index 9f30f9b20e05545d5d640bf607ec0bdec9359dc3..2c8be42f093f63e0961f62d3a0aa0c9930b567cc 100644 (file)
@@ -982,6 +982,13 @@ Ip6InitDADProcess (
   NET_CHECK_SIGNATURE (IpIf, IP6_INTERFACE_SIGNATURE);\r
   ASSERT (AddressInfo != NULL);\r
 \r
+  //\r
+  // Do nothing if we have already started DAD on the address.\r
+  //\r
+  if (Ip6FindDADEntry (IpIf->Service, &AddressInfo->Address, NULL) != NULL) {\r
+    return EFI_SUCCESS;\r
+  }\r
+  \r
   Status   = EFI_SUCCESS;\r
   IpSb     = IpIf->Service;\r
   DadXmits = &IpSb->Ip6ConfigInstance.DadXmits;\r
@@ -1577,16 +1584,6 @@ Ip6ProcessNeighborSolicit (
   if (IsDAD && !IsMaintained) {\r
     DupAddrDetect = Ip6FindDADEntry (IpSb, &Target, &IpIf);\r
     if (DupAddrDetect != NULL) {\r
-      if (DupAddrDetect->Transmit == 0) {\r
-        //\r
-        // The NS is from another node to performing DAD on the same address since\r
-        // we haven't send out any NS yet. Fail DAD for the tentative address.\r
-        //\r
-        Ip6OnDADFinished (FALSE, IpIf, DupAddrDetect);\r
-        Status = EFI_ICMP_ERROR;\r
-        goto Exit;\r
-      }\r
-\r
       //\r
       // Check the MAC address of the incoming packet.\r
       //\r
@@ -2863,7 +2860,7 @@ Ip6NdFasterTimerTicking (
           //\r
           Flag = FALSE;\r
           if ((DupAddrDetect->Receive == 0) ||\r
-              (DupAddrDetect->Transmit == DupAddrDetect->Receive)) {\r
+              (DupAddrDetect->Transmit <= DupAddrDetect->Receive)) {\r
             Flag = TRUE;\r
           }\r
 \r