diff --git a/CHANGES.md b/CHANGES.md index c11b1e6f8..68ccb5390 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -27,6 +27,7 @@ The wimax module was removed and moved to the ns-3 App Store. * (antenna) Reformatted documentation. * (documentation) Improve models documentation look and feel * (internet) Added check for longest prefix match in GlobalRouting. +* (internet) ArpCache::Flush() and NdiscCache::Flush() no longer remove autogenerated entries * (lr-wpan) Debloat MAC PD-DATA.indication and reduce packet copies. * (zigbee) Added group table. * (zigbee) Added Groupcast (Multicast) support. diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index b3ba6234c..891a7a0e8 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -43,6 +43,7 @@ The wimax module was removed and moved to the ns-3 App Store. ### Bugs fixed +- (internet) #851 - NeighborCacheHelper entries are no longer removed due to LinkUp events - (internet) #1251 - Added check for longest prefix match in GlobalRouting - (wifi) Block transmission on other EMLSR links as soon as it is detected that the main PHY is receiving an A-MPDU, to prevent that the EMLSR client starts an UL TXOP before the end of the A-MPDU - (wifi) EMLSR clients can switch to listening operations when receiving the MAC header of a broadcast frame that is not a Trigger Frame nor a Multi-STA BA diff --git a/src/internet/doc/ipv4.rst b/src/internet/doc/ipv4.rst index 42a183929..c7bc4f4d6 100644 --- a/src/internet/doc/ipv4.rst +++ b/src/internet/doc/ipv4.rst @@ -286,3 +286,8 @@ The typical usages are:: NeighborCacheHelper neighborCache; neighborCache.PopulateNeighborCache(interfaces); // interfaces is the Ipv4InterfaceContainer want to generate ARP caches + +Neighbor cache entries are not removed by calls to ``ArpCache::Flush()``, +which may be called during the process of bringing IPv4 interfaces up +or down. Instead, to remove them, users must call +``ArpCache::RemoveAutoGenerated()``. diff --git a/src/internet/doc/ipv6.rst b/src/internet/doc/ipv6.rst index 609f46d1c..3521bf45c 100644 --- a/src/internet/doc/ipv6.rst +++ b/src/internet/doc/ipv6.rst @@ -523,3 +523,8 @@ The usages for generating NDISC cache is almost the same as generating ARP cache NeighborCacheHelper neighborCache; neighborCache.PopulateNeighborCache(interfaces); // interfaces is the Ipv6InterfaceContainer want to generate ARP caches + +Neighbor cache entries are not removed by calls to ``NdiscCache::Flush()``, +which may be called during the process of bringing IPv6 interfaces up +or down. Instead, to remove them, users must call +``NdiscCache::RemoveAutoGenerated()``. diff --git a/src/internet/model/arp-cache.cc b/src/internet/model/arp-cache.cc index b79270071..f323ffc5a 100644 --- a/src/internet/model/arp-cache.cc +++ b/src/internet/model/arp-cache.cc @@ -234,11 +234,19 @@ void ArpCache::Flush() { NS_LOG_FUNCTION(this); - for (auto i = m_arpCache.begin(); i != m_arpCache.end(); i++) + for (auto i = m_arpCache.begin(); i != m_arpCache.end();) { - delete (*i).second; + if (!i->second->IsAutoGenerated()) + { + i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress + delete i->second; + i = m_arpCache.erase(i); + } + else + { + i++; + } } - m_arpCache.erase(m_arpCache.begin(), m_arpCache.end()); if (m_waitReplyTimer.IsPending()) { NS_LOG_LOGIC("Stopping WaitReplyTimer at " << Simulator::Now().GetSeconds() @@ -301,10 +309,12 @@ ArpCache::RemoveAutoGeneratedEntries() { i->second->ClearPendingPacket(); // clear the pending packets for entry's ipaddress delete i->second; - m_arpCache.erase(i++); - continue; + i = m_arpCache.erase(i); + } + else + { + i++; } - i++; } } diff --git a/src/internet/model/arp-cache.h b/src/internet/model/arp-cache.h index f3a186991..45c51399c 100644 --- a/src/internet/model/arp-cache.h +++ b/src/internet/model/arp-cache.h @@ -145,7 +145,12 @@ class ArpCache : public Object */ void Remove(ArpCache::Entry* entry); /** - * @brief Clear the ArpCache of all entries + * @brief Clear the ArpCache of all entries except auto-generated entries + * + * If you wish to remove all entries, including auto-generated entries, + * call this method and then also call RemoveAutoGeneratedEntries(). + * + * @see RemoveAutoGenerated */ void Flush(); diff --git a/src/internet/model/ndisc-cache.cc b/src/internet/model/ndisc-cache.cc index e11f3ed57..9ffa1b07e 100644 --- a/src/internet/model/ndisc-cache.cc +++ b/src/internet/model/ndisc-cache.cc @@ -153,12 +153,19 @@ NdiscCache::Flush() { NS_LOG_FUNCTION(this); - for (auto i = m_ndCache.begin(); i != m_ndCache.end(); i++) + for (auto i = m_ndCache.begin(); i != m_ndCache.end();) { - delete (*i).second; /* delete the pointer NdiscCache::Entry */ + if (!i->second->IsAutoGenerated()) + { + i->second->ClearWaitingPacket(); + delete i->second; + i = m_ndCache.erase(i); + } + else + { + i++; + } } - - m_ndCache.erase(m_ndCache.begin(), m_ndCache.end()); } void @@ -712,10 +719,12 @@ NdiscCache::RemoveAutoGeneratedEntries() { i->second->ClearWaitingPacket(); delete i->second; - m_ndCache.erase(i++); - continue; + i = m_ndCache.erase(i); + } + else + { + i++; } - i++; } } diff --git a/src/internet/model/ndisc-cache.h b/src/internet/model/ndisc-cache.h index cdd6ba782..37c5ece40 100644 --- a/src/internet/model/ndisc-cache.h +++ b/src/internet/model/ndisc-cache.h @@ -104,7 +104,12 @@ class NdiscCache : public Object void Remove(NdiscCache::Entry* entry); /** - * @brief Flush the cache. + * @brief Clear the cache of all entries except auto-generated entries + * + * If you wish to remove all entries, including auto-generated entries, + * call this method and then also call RemoveAutoGeneratedEntries(). + * + * @see RemoveAutoGenerated */ void Flush(); diff --git a/src/internet/test/neighbor-cache-test.cc b/src/internet/test/neighbor-cache-test.cc index 3d028db97..5363f7f07 100644 --- a/src/internet/test/neighbor-cache-test.cc +++ b/src/internet/test/neighbor-cache-test.cc @@ -6,6 +6,7 @@ * Author: Zhiheng Dong */ +#include "ns3/arp-cache.h" #include "ns3/icmpv4-l4-protocol.h" #include "ns3/icmpv6-l4-protocol.h" #include "ns3/internet-stack-helper.h" @@ -15,6 +16,7 @@ #include "ns3/ipv6-address-helper.h" #include "ns3/ipv6-l3-protocol.h" #include "ns3/ipv6-routing-helper.h" +#include "ns3/ndisc-cache.h" #include "ns3/neighbor-cache-helper.h" #include "ns3/simple-channel.h" #include "ns3/simple-net-device-helper.h" @@ -882,11 +884,42 @@ FlushTest::DoRun() std::ostringstream stringStream1v6; Ptr ndiscStream = Create(&stringStream1v6); - // Print cache. + // Print cache at time 0. Ipv4RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), arpStream); Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), ndiscStream); + // Flush cache at time 1 s. + Simulator::Schedule(Seconds(1), &ArpCache::Flush, arpCache); + Simulator::Schedule(Seconds(1), &NdiscCache::Flush, ndiscCache); + + // Print cache again at time 2 s. + std::ostringstream stringStream2v4; + Ptr arpStream2 = Create(&stringStream2v4); + std::ostringstream stringStream2v6; + Ptr ndiscStream2 = Create(&stringStream2v6); + Ipv4RoutingHelper::PrintNeighborCacheAllAt(Seconds(2), arpStream2); + Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(2), ndiscStream2); + + // Add autogenerated entries at time 3 s again. + Simulator::Schedule(Seconds(3), [&neighborCache]() { neighborCache.PopulateNeighborCache(); }); + + // Flush cache again at time 4 s. + Simulator::Schedule(Seconds(4), &ArpCache::Flush, arpCache); + Simulator::Schedule(Seconds(4), &NdiscCache::Flush, ndiscCache); + + // Print cache again at time 5 s. + // Check that the autogenerated entries survived the Flush + std::ostringstream stringStream5v4; + Ptr arpStream5 = Create(&stringStream5v4); + std::ostringstream stringStream5v6; + Ptr ndiscStream5 = Create(&stringStream5v6); + // Limit the printed output to node 0 + Ipv4RoutingHelper::PrintNeighborCacheAt(Seconds(5), m_nodes.Get(0), arpStream5); + Ipv6RoutingHelper::PrintNeighborCacheAt(Seconds(5), m_nodes.Get(0), ndiscStream5); + Simulator::Run(); + + // Check the time zero output // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left. constexpr auto ArpCache = "ARP Cache of node 0 at time 0\n" "10.1.1.4 dev 0 lladdr 04-06-00:00:00:00:00:01 PERMANENT\n" @@ -901,6 +934,38 @@ FlushTest::DoRun() "NDISC Cache of node 1 at time +0s\n" "NDISC Cache of node 2 at time +0s\n"; NS_TEST_EXPECT_MSG_EQ(stringStream1v6.str(), NdiscCache, "Ndisc cache is incorrect."); + + // Check output after the first flush-- should be empty + constexpr auto ArpCache2 = "ARP Cache of node 0 at time 2\n" + "ARP Cache of node 1 at time 2\n" + "ARP Cache of node 2 at time 2\n"; + NS_TEST_EXPECT_MSG_EQ(stringStream2v4.str(), + ArpCache2, + "Arp cache is incorrect after Flush()."); + constexpr auto NdiscCache2 = "NDISC Cache of node 0 at time +2s\n" + "NDISC Cache of node 1 at time +2s\n" + "NDISC Cache of node 2 at time +2s\n"; + NS_TEST_EXPECT_MSG_EQ(stringStream2v6.str(), + NdiscCache2, + "Ndisc cache is incorrect after Flush()."); + + // Check output after the second flush-- node 0 should still have two + // static autogenerated entries for IPv6 and one for IPv4. + // This behavior was added in the ns-3.46 release (see issue #851). + constexpr auto ArpCache5 = + "ARP Cache of node 0 at time 5\n" + "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"; + constexpr auto NdiscCache5 = + "NDISC Cache of node 0 at time +5s\n" + "2001::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"; + NS_TEST_EXPECT_MSG_EQ(stringStream5v4.str(), + ArpCache5, + "Arp cache is incorrect after second Flush()."); + NS_TEST_EXPECT_MSG_EQ(stringStream5v6.str(), + NdiscCache5, + "Ndisc cache is incorrect after second Flush()."); + Simulator::Destroy(); } @@ -975,7 +1040,8 @@ DuplicateTest::DoRun() Ipv6RoutingHelper::PrintNeighborCacheAllAt(Seconds(0), ndiscStream); Simulator::Run(); - // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left. + // Check if the overlapped scope of PopulateNeighborCache() calls did + // not lead to duplicate entries. constexpr auto ArpCache = "ARP Cache of node 0 at time 0\n" "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" @@ -986,7 +1052,8 @@ DuplicateTest::DoRun() "10.1.2.1 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"; NS_TEST_EXPECT_MSG_EQ(stringStream1v4.str(), ArpCache, "Arp cache is incorrect."); - // Check if the STATIC_AUTOGENERATED entries are flushed and the PERMANENT entry is left. + // Check if the overlapped scope of PopulateNeighborCache() calls did + // not lead to duplicate entries. constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n" "2001::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"