From 90d6e08bb417ff0e41318552935b6ce7f9062aa8 Mon Sep 17 00:00:00 2001 From: Zhiheng Dong Date: Wed, 14 Sep 2022 15:48:09 -0700 Subject: [PATCH] internet: GSoC-22 update automatic ARP/NDISC cache when network changes --- CHANGES.md | 5 + RELEASE_NOTES.md | 1 + src/internet/doc/ipv4.rst | 7 + src/internet/doc/ipv6.rst | 7 + src/internet/examples/CMakeLists.txt | 9 + .../examples/neighbor-cache-dynamic.cc | 270 +++++ src/internet/helper/neighbor-cache-helper.cc | 145 ++- src/internet/helper/neighbor-cache-helper.h | 44 +- src/internet/model/ipv4-interface.cc | 26 + src/internet/model/ipv4-interface.h | 22 + src/internet/model/ipv6-interface.cc | 27 + src/internet/model/ipv6-interface.h | 22 + src/internet/test/neighbor-cache-test.cc | 976 +++++++++++++++++- 13 files changed, 1512 insertions(+), 49 deletions(-) create mode 100644 src/internet/examples/neighbor-cache-dynamic.cc diff --git a/CHANGES.md b/CHANGES.md index aac8ec8b3..2fe225f1f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,11 @@ Changes from ns-3.36 to ns-3.37 * `WifiPhyListener::NotifyMaybeCcaBusyStart` has been renamed to `WifiPhyListener::NotifyCcaBusyStart` and has two additional parameters: the channel type that indicates for which subchannel the CCA-BUSY is reported and a vector of CCA-BUSY durations for each 20 MHz subchannel. A duration of zero indicates CCA is IDLE, and the vector of CCA-BUSY durations is not empty if the PHY supports 802.11ax and the operational channel width is larger than 20 MHz. * Added a new attribute **CcaSensitivity** in WifiPhy for configuring the threshold that corresponds to the minimum received power of a PPDU, that occupies the primary channel, should have to report a CCA-BUSY indication. * Added a new attribute **SecondaryCcaSensitivityThresholds** in VhtConfiguration for configuring the thresholds that corresponds to the minimum received power of a PPDU, that does not occupy the primary 20 MHz channel, should have to report a CCA-BUSY indication. This is made of a tuple, where the first threshold is used for 20 MHz PPDUs, the second one is used for 40 MHz PPDUs and the third one is used for 80 MHz PPDUs. +* In `src/internet`, several changes were made to enable auto-generated neighbor cache: + * A new helper (NeighborCacheHelper) was added to set up auto-generated neighbor cache. + * New NUD_STATE `STATIC_AUTOGENERATED` was added to help the user manage auto-generated entries in Arp cache and Ndisc cache. + * Add new callbacks RemoveAddressCallback and AddAddressCallback to dynamically update neighbor cache during addresses are removed/added. + * Add NeighborCacheTestSuite to test auto-generated neighbor cache. ### Changes to existing API diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 91da108a5..1df21fb98 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -22,6 +22,7 @@ Release 3-dev - (lr-wpan) !997 - Adds MAC ACTIVE and PASSIVE scan support - (wifi) CCA has been reworked to report the channel type in the CCA-BUSY indication and the per-20 MHz CCA bitmap for 802.11ax. - (wifi) PPDUs are transmitted on the largest primary channel that is found to be idle (according to the CCA-BUSY indication provided by the PHY) when gaining a TXOP. +- (internet) Add auto-generate ARP/NDISC cache, as the outcome of GSoC 2022 project. ### Bugs fixed diff --git a/src/internet/doc/ipv4.rst b/src/internet/doc/ipv4.rst index d2fcdb394..171fd7d02 100644 --- a/src/internet/doc/ipv4.rst +++ b/src/internet/doc/ipv4.rst @@ -244,6 +244,13 @@ address resolution in simulations that are focused on other performance aspects. The state of entries which are generated by NeighborCacheHelper is ``STATIC_AUTOGENERATED``, which is similar to ``PERMANENT``, but they are not manually added or removed by user, they will be managed by NeighborCacheHelper when user need pre-generate cache. +When user is generating neighbor caches globally, neighbor caches will update dynamically when +IPv4 addresses are removed or added; when user is generating neighbor caches partially, +NeighborCacheHelper will take care of address removal, for adding address user may rerun a +reduced-scope PopulateNeighbor() again to pick up the new IP address or manually +add an entry to keep the neighbor cache up-to-date, the reason is that: when PopulateNeighborCache() +has previously been run with a scope less than global, the code does not know whether it was previously +run with a scope of Channel, NetDeviceContainer, or Ip interface container. The source code for NeighborCache is located in ``src/internet/helper/neighbor-cache-helper`` A complete example is in ``src/internet/examples/neighbor-cache-example.cc``. diff --git a/src/internet/doc/ipv6.rst b/src/internet/doc/ipv6.rst index 842919553..8dc72e154 100644 --- a/src/internet/doc/ipv6.rst +++ b/src/internet/doc/ipv6.rst @@ -501,6 +501,13 @@ neighbor discovery in simulations that are focused on other performance aspects. The state of entries generate by NeighborCacheHelper is ``STATIC_AUTOGENERATED``, which is similar to ``PERMANENT``, but they are not manually added or removed by user, they will be managed by NeighborCacheHelper when user need pre-generate cache. +When user is generating neighbor caches globally, neighbor caches will update dynamically when +IPv6 addresses are removed or added; when user is generating neighbor caches partially, +NeighborCacheHelper will take care of address removal, for adding address user may rerun a +reduced-scope PopulateNeighbor() again to pick up the new IP address or manually +add an entry to keep the neighbor cache up-to-date, the reason is that: when PopulateNeighborCache() +has previously been run with a scope less than global, the code does not know whether it was previously +run with a scope of Channel, NetDeviceContainer, or Ip interface container. The source code for NeighborCache is located in ``src/internet/helper/neighbor-cache-helper`` A complete example is in ``src/internet/examples/neighbor-cache-example.cc``. diff --git a/src/internet/examples/CMakeLists.txt b/src/internet/examples/CMakeLists.txt index 0f7970cc0..826689088 100644 --- a/src/internet/examples/CMakeLists.txt +++ b/src/internet/examples/CMakeLists.txt @@ -16,3 +16,12 @@ build_lib_example( ${libinternet} ${libnetwork} ) + +build_lib_example( + NAME neighbor-cache-dynamic + SOURCE_FILES neighbor-cache-dynamic.cc + LIBRARIES_TO_LINK + ${libcsma} + ${libinternet} + ${libnetwork} +) diff --git a/src/internet/examples/neighbor-cache-dynamic.cc b/src/internet/examples/neighbor-cache-dynamic.cc new file mode 100644 index 000000000..ee0903bdc --- /dev/null +++ b/src/internet/examples/neighbor-cache-dynamic.cc @@ -0,0 +1,270 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2022 ZHIHENG DONG + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation; + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Author: Zhiheng Dong + */ + +/** + * This example shows how neighbor caches generate dynamically, when + * user is generating neighbor caches globally, neighbor caches will + * update dynamically when IPv4/IPv6 addresses are removed or added; + * when user is generating neighbor caches partially, NeighborCacheHelper + * will take care of address removal, for adding address user may manually + * add entry to keep the neighbor cache up-to-date. + * + * IPv4 Network Topology + * \verbatim + n1 n2 n3 + | | | + =========== + LAN 10.1.1.0 + \endverbatim + * + * IPv6 Network Topology + * \verbatim + n1 n2 n3 + | | | + =========== + LAN 2001:1::/64 + \endverbatim + * + * Expected Outputs: + * IPv4 (default): + * \verbatim + ARP Cache of node 0 at time 0 + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + ARP Cache of node 1 at time 0 + 10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + ARP Cache of node 2 at time 0 + 10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + + Arp caches after add address 10.1.1.4 to n1 + ARP Cache of node 0 at time 1 + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + ARP Cache of node 1 at time 1 + 10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + 10.1.1.4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + ARP Cache of node 2 at time 1 + 10.1.1.1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 10.1.1.4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + + Arp caches after remove the first address (10.1.1.1) from n1 + ARP Cache of node 0 at time 2 + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + ARP Cache of node 1 at time 2 + 10.1.1.3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + 10.1.1.4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + ARP Cache of node 2 at time 2 + 10.1.1.2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 10.1.1.4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + \endverbatim + * + * IPv6 (--useIPv6): + * \verbatim + NDISC Cache of node 0 at time +0s + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 1 at time +0s + 2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 2 at time +0s + 2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + + Ndisc caches after add address 2001:1::200:ff:fe00:4 n1 + NDISC Cache of node 0 at time +1s + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 1 at time +1s + 2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 2 at time +1s + 2001:1::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + + Arp caches after remove the second address (2001:1::200:ff:fe00:1) from n1 + NDISC Cache of node 0 at time +2s + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 1 at time +2s + 2001:1::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:3 dev 0 lladdr 02-06-00:00:00:00:00:03 STATIC_AUTOGENERATED + NDISC Cache of node 2 at time +2s + 2001:1::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + 2001:1::200:ff:fe00:4 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:1 dev 0 lladdr 02-06-00:00:00:00:00:01 STATIC_AUTOGENERATED + fe80::200:ff:fe00:2 dev 0 lladdr 02-06-00:00:00:00:00:02 STATIC_AUTOGENERATED + \endverbatim + */ + + + + +#include "ns3/core-module.h" +#include "ns3/network-module.h" +#include "ns3/csma-module.h" +#include "ns3/internet-module.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("NeighborCacheDynamic"); + +void AddIpv4Address (Ptr ipv4Interface, Ipv4InterfaceAddress ifaceAddr) +{ + ipv4Interface->AddAddress (ifaceAddr); + std::cout << "\nArp caches after add address 10.1.1.4 to n1" << std::endl; + +} + +void AddIpv6Address (Ptr ipv6Interface, Ipv6InterfaceAddress ifaceAddr) +{ + ipv6Interface->AddAddress (ifaceAddr); + std::cout << "\nNdisc caches after add address 2001:1::200:ff:fe00:4 n1" << std::endl; +} + +void RemoveIpv4Address (Ptr ipv4Interface, uint32_t index) +{ + ipv4Interface->RemoveAddress (index); + std::cout << "\nArp caches after remove the first address (10.1.1.1) from n1" << std::endl; +} + +void RemoveIpv6Address (Ptr ipv6Interface, uint32_t index) +{ + ipv6Interface->RemoveAddress (index); + std::cout << "\nArp caches after remove the second address (2001:1::200:ff:fe00:1) from n1" << std::endl; + +} + +int +main (int argc, char *argv[]) +{ + bool useIpv6 = false; + bool enableLog = false; + + CommandLine cmd (__FILE__); + cmd.AddValue ("useIPv6", "Use IPv6 instead of IPv4", useIpv6); + cmd.AddValue ("enableLog", "Enable ArpL3Protocol and Icmpv6L4Protocol logging", enableLog); + cmd.Parse (argc,argv); + + if (enableLog) + { + LogComponentEnable ("ArpL3Protocol", LOG_LEVEL_LOGIC); + LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_LOGIC); + } + + uint32_t nCsma = 3; + NodeContainer csmaNodes; + csmaNodes.Create (nCsma); + + CsmaHelper csma; + csma.SetChannelAttribute ("DataRate", StringValue ("100Mbps")); + csma.SetChannelAttribute ("Delay", TimeValue (NanoSeconds (6560))); + + NetDeviceContainer csmaDevices; + csmaDevices = csma.Install (csmaNodes); + + InternetStackHelper stack; + stack.Install (csmaNodes); + + if (!useIpv6) + { + Ipv4AddressHelper address; + address.SetBase ("10.1.1.0", "255.255.255.0"); + Ipv4InterfaceContainer csmaInterfaces; + csmaInterfaces = address.Assign (csmaDevices); + } + else + { + Ipv6AddressHelper address; + address.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer csmaInterfaces; + csmaInterfaces = address.Assign (csmaDevices); + } + + // Populate neighbor caches for all devices + NeighborCacheHelper neighborCache; + neighborCache.SetDynamicNeighborCache (true); + neighborCache.PopulateNeighborCache (); + + if (!useIpv6) + { + // Add address 10.1.1.4 to interface 1 in 0.5 seconds + Ptr n1 = csmaNodes.Get (0); + uint32_t ipv4ifIndex = 1; + Ptr ipv4Interface = n1->GetObject ()->GetInterface (ipv4ifIndex); + Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress ("10.1.1.4","255.255.255.0"); + Simulator::Schedule (Seconds (0.5),&AddIpv4Address,ipv4Interface, ifaceAddr); + + // Remove the first address (10.1.1.1) from interface 1 in 1.5 seconds + uint32_t addressIndex = 0; + Simulator::Schedule (Seconds (1.5),&RemoveIpv4Address,ipv4Interface, addressIndex); + + Ptr outputStream = Create (&std::cout); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), outputStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), outputStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), outputStream); + } + else + { + // Add address 2001:1::200:ff:fe00:4 to interface 1 in 0.5 seconds + Ptr n1 = csmaNodes.Get (0); + uint32_t ipv6ifIndex = 1; + Ptr ipv6Interface = n1->GetObject ()->GetInterface (ipv6ifIndex); + Ipv6InterfaceAddress ifaceAddr = Ipv6InterfaceAddress ( "2001:1::200:ff:fe00:4", Ipv6Prefix (64)); + Simulator::Schedule (Seconds (0.5),&AddIpv6Address,ipv6Interface, ifaceAddr); + + // Remove the second address (2001:1::200:ff:fe00:1) from interface 1 in 1.5 seconds + uint32_t addressIndex = 1; + Simulator::Schedule (Seconds (1.5),&RemoveIpv6Address,ipv6Interface, addressIndex); + + Ptr outputStream = Create (&std::cout); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), outputStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), outputStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), outputStream); + + } + + Simulator::Stop (Seconds (10.0)); + Simulator::Run (); + Simulator::Destroy (); + return 0; +} diff --git a/src/internet/helper/neighbor-cache-helper.cc b/src/internet/helper/neighbor-cache-helper.cc index e76fa125d..9b1f37eb6 100644 --- a/src/internet/helper/neighbor-cache-helper.cc +++ b/src/internet/helper/neighbor-cache-helper.cc @@ -43,9 +43,10 @@ NeighborCacheHelper::~NeighborCacheHelper () NS_LOG_FUNCTION (this); } void -NeighborCacheHelper::PopulateNeighborCache (void) const +NeighborCacheHelper::PopulateNeighborCache (void) { NS_LOG_FUNCTION (this); + m_globalNeighborCache = true; for (uint32_t i = 0; i < ChannelList::GetNChannels (); ++i) { Ptr channel = ChannelList::GetChannel (i); @@ -205,6 +206,14 @@ NeighborCacheHelper::PopulateNeighborEntriesIpv4 (Ptr ipv4Interfa { uint32_t netDeviceAddresses = ipv4Interface->GetNAddresses (); uint32_t neighborDeviceAddresses = neighborDeviceInterface->GetNAddresses (); + if (m_dynamicNeighborCache) + { + ipv4Interface->RemoveAddressCallback (MakeCallback (&NeighborCacheHelper::UpdateCacheByIpv4AddressRemoved, this)); + if (m_globalNeighborCache) + { + ipv4Interface->AddAddressCallback (MakeCallback (&NeighborCacheHelper::UpdateCacheByIpv4AddressAdded, this)); + } + } for (uint32_t n = 0; n < netDeviceAddresses; ++n) { Ipv4InterfaceAddress netDeviceIfAddr = ipv4Interface->GetAddress (n); @@ -226,6 +235,14 @@ NeighborCacheHelper::PopulateNeighborEntriesIpv6 (Ptr ipv6Interfa { uint32_t netDeviceAddresses = ipv6Interface->GetNAddresses (); uint32_t neighborDeviceAddresses = neighborDeviceInterface->GetNAddresses (); + if (m_dynamicNeighborCache) + { + ipv6Interface->RemoveAddressCallback (MakeCallback (&NeighborCacheHelper::UpdateCacheByIpv6AddressRemoved, this)); + if (m_globalNeighborCache) + { + ipv6Interface->AddAddressCallback (MakeCallback (&NeighborCacheHelper::UpdateCacheByIpv6AddressAdded, this)); + } + } for (uint32_t n = 0; n < netDeviceAddresses; ++n) { Ipv6InterfaceAddress netDeviceIfAddr = ipv6Interface->GetAddress (n); @@ -333,7 +350,133 @@ NeighborCacheHelper::FlushAutoGenerated (void) const } +void +NeighborCacheHelper::UpdateCacheByIpv4AddressRemoved (const Ptr interface, const Ipv4InterfaceAddress ifAddr) const +{ + NS_LOG_FUNCTION (this); + Ptr netDevice = interface->GetDevice (); + Ptr channel = netDevice->GetChannel (); + for (std::size_t i = 0; i < channel->GetNDevices (); ++i) + { + Ptr neighborDevice = channel->GetDevice (i); + Ptr neighborNode = neighborDevice->GetNode (); + int32_t neighborInterfaceIndex = neighborNode->GetObject ()->GetInterfaceForDevice (neighborDevice); + if (neighborInterfaceIndex != -1) + { + Ptr neighborInterface = neighborNode->GetObject ()->GetInterface (neighborInterfaceIndex); + Ptr arpCache = neighborInterface->GetArpCache (); + if (!arpCache) + { + NS_LOG_LOGIC ("ArpCache doesn't exist"); + return; + } + ArpCache::Entry *entry = arpCache->Lookup (ifAddr.GetLocal ()); + if (entry) + { + arpCache->Remove (entry); + } + } + } +} +void +NeighborCacheHelper::UpdateCacheByIpv4AddressAdded (const Ptr interface, const Ipv4InterfaceAddress ifAddr) const +{ + + NS_LOG_FUNCTION (this); + Ptr netDevice = interface->GetDevice (); + Ptr channel = netDevice->GetChannel (); + for (std::size_t i = 0; i < channel->GetNDevices (); ++i) + { + Ptr neighborDevice = channel->GetDevice (i); + if (neighborDevice != netDevice) + { + Ptr neighborNode = neighborDevice->GetNode (); + int32_t neighborInterfaceIndex = neighborNode->GetObject ()->GetInterfaceForDevice (neighborDevice); + if (neighborInterfaceIndex != -1) + { + Ptr neighborInterface = neighborNode->GetObject ()->GetInterface (neighborInterfaceIndex); + uint32_t neighborDeviceAddresses = neighborInterface->GetNAddresses (); + for (uint32_t m = 0; m < neighborDeviceAddresses; ++m) + { + Ipv4InterfaceAddress neighborDeviceIfAddr = neighborInterface->GetAddress (m); + if (ifAddr.IsInSameSubnet (neighborDeviceIfAddr.GetLocal ())) + { + // Add Arp entity of current interface to its neighbor's Arp cache + AddEntry (neighborInterface, ifAddr.GetAddress (),netDevice->GetAddress () ); + } + } + } + } + } +} + +void +NeighborCacheHelper::UpdateCacheByIpv6AddressRemoved (const Ptr interface, const Ipv6InterfaceAddress ifAddr) const +{ + NS_LOG_FUNCTION (this); + Ptr netDevice = interface->GetDevice (); + Ptr channel = netDevice->GetChannel (); + for (std::size_t i = 0; i < channel->GetNDevices (); ++i) + { + Ptr neighborDevice = channel->GetDevice (i); + Ptr neighborNode = neighborDevice->GetNode (); + int32_t neighborInterfaceIndex = neighborNode->GetObject ()->GetInterfaceForDevice (neighborDevice); + if (neighborInterfaceIndex != -1) + { + Ptr neighborInterface = neighborNode->GetObject ()->GetInterface (neighborInterfaceIndex); + Ptr ndiscCache = neighborInterface->GetNdiscCache (); + if (!ndiscCache) + { + NS_LOG_LOGIC ("ndiscCache doesn't exist"); + return; + } + NdiscCache::Entry *entry = ndiscCache->Lookup (ifAddr.GetAddress ()); + if (entry) + { + ndiscCache->Remove (entry); + } + } + } +} + +void +NeighborCacheHelper::UpdateCacheByIpv6AddressAdded (const Ptr interface, const Ipv6InterfaceAddress ifAddr) const +{ + NS_LOG_FUNCTION (this); + Ptr netDevice = interface->GetDevice (); + Ptr channel = netDevice->GetChannel (); + for (std::size_t i = 0; i < channel->GetNDevices (); ++i) + { + Ptr neighborDevice = channel->GetDevice (i); + if (neighborDevice != netDevice) + { + Ptr neighborNode = neighborDevice->GetNode (); + int32_t neighborInterfaceIndex = neighborNode->GetObject ()->GetInterfaceForDevice (neighborDevice); + if (neighborInterfaceIndex != -1) + { + Ptr neighborInterface = neighborNode->GetObject ()->GetInterface (neighborInterfaceIndex); + uint32_t neighborDeviceAddresses = neighborInterface->GetNAddresses (); + for (uint32_t m = 0; m < neighborDeviceAddresses; ++m) + { + Ipv6InterfaceAddress neighborDeviceIfAddr = neighborInterface->GetAddress (m); + if (ifAddr.IsInSameSubnet (neighborDeviceIfAddr.GetAddress ())) + { + // Add Arp entity of current interface to its neighbor's Arp cache + AddEntry (neighborInterface, ifAddr.GetAddress (),netDevice->GetAddress () ); + } + } + } + } + } +} + +void +NeighborCacheHelper::SetDynamicNeighborCache (bool enable) +{ + NS_LOG_FUNCTION (this); + m_dynamicNeighborCache = enable; +} } // namespace ns3 diff --git a/src/internet/helper/neighbor-cache-helper.h b/src/internet/helper/neighbor-cache-helper.h index 0779b1850..627456c2a 100644 --- a/src/internet/helper/neighbor-cache-helper.h +++ b/src/internet/helper/neighbor-cache-helper.h @@ -59,7 +59,7 @@ public: * \brief Populate neighbor ARP and NDISC caches for all devices. * This method walks the global ChannelList. */ - void PopulateNeighborCache (void) const; + void PopulateNeighborCache (void); /** * \brief Populate neighbor ARP and NDISC caches for all devices in the given @@ -94,6 +94,15 @@ public: */ void FlushAutoGenerated (void) const; + /** + * \brief Enable/diable dynamic neighbor cache, auto-generated neighbor cache will update + * by IP addresses changed when dynamic neighbor cache enabled. User should ensure that + * the NeighborCacheHelper object persists for the duration of the simulation when dynamic + * neighbor cache is enabled. + * \param enable enable state + */ + void SetDynamicNeighborCache (bool enable); + private: /** * \brief Populate neighbor ARP entries for given IPv4 interface. @@ -125,6 +134,39 @@ private: */ void AddEntry (Ptr netDeviceInterface, Ipv6Address ipv6Address, Address macAddress) const; + /** + * \brief Update neighbor caches when an address is removed from a Ipv4Interface with auto generated neighbor cache. + * \param interface the Ipv4Interface that address removed from. + * \param ifAddr the removed IPv4 interface address . + */ + void UpdateCacheByIpv4AddressRemoved (const Ptr interface, const Ipv4InterfaceAddress ifAddr) const; + + /** + * \brief Update neighbor caches when an address is added to a Ipv4Interface with auto generated neighbor cache. + * \param interface the Ipv4Interface that address added to. + * \param ifAddr the added IPv4 interface address. + */ + void UpdateCacheByIpv4AddressAdded (const Ptr interface, const Ipv4InterfaceAddress ifAddr) const; + + /** + * \brief Update neighbor caches when an address is removed from a Ipv6Interface with auto generated neighbor cache. + * \param interface the Ipv6Interface that address removed from. + * \param ifAddr the removed IPv6 interface address. + */ + void UpdateCacheByIpv6AddressRemoved (const Ptr interface, const Ipv6InterfaceAddress ifAddr) const; + + /** + * \brief Update neighbor cache when an address is added to a Ipv6Interface with auto generated neighbor cache. + * \param interface the Ipv6Interface that address added to. + * \param ifAddr the added IPv6 interface address. + */ + void UpdateCacheByIpv6AddressAdded (const Ptr interface, const Ipv6InterfaceAddress ifAddr) const; + + bool m_globalNeighborCache {false}; //!< flag will set true if neighbor caches were generated for all devices + + bool m_dynamicNeighborCache {false}; //!< flag will set true if dynamic neighbor cache is enabled. + + }; } // namespace ns3 diff --git a/src/internet/model/ipv4-interface.cc b/src/internet/model/ipv4-interface.cc index 1d1b88e1b..666c52de2 100644 --- a/src/internet/model/ipv4-interface.cc +++ b/src/internet/model/ipv4-interface.cc @@ -310,6 +310,10 @@ Ipv4Interface::AddAddress (Ipv4InterfaceAddress addr) { NS_LOG_FUNCTION (this << addr); m_ifaddrs.push_back (addr); + if (!m_addAddressCallback.IsNull ()) + { + m_addAddressCallback(this, addr); + } return true; } @@ -353,6 +357,10 @@ Ipv4Interface::RemoveAddress (uint32_t index) { Ipv4InterfaceAddress addr = *i; m_ifaddrs.erase (i); + if (!m_removeAddressCallback.IsNull ()) + { + m_removeAddressCallback(this, addr); + } return addr; } ++tmp; @@ -380,11 +388,29 @@ Ipv4Interface::RemoveAddress(Ipv4Address address) { Ipv4InterfaceAddress ifAddr = *it; m_ifaddrs.erase(it); + if (!m_removeAddressCallback.IsNull ()) + { + m_removeAddressCallback(this, ifAddr); + } return ifAddr; } } return Ipv4InterfaceAddress(); } +void +Ipv4Interface::RemoveAddressCallback (Callback, Ipv4InterfaceAddress> removeAddressCallback) +{ + NS_LOG_FUNCTION (this << &removeAddressCallback); + m_removeAddressCallback = removeAddressCallback; +} + +void +Ipv4Interface::AddAddressCallback (Callback, Ipv4InterfaceAddress> addAddressCallback) +{ + NS_LOG_FUNCTION (this << &addAddressCallback); + m_addAddressCallback = addAddressCallback; +} + } // namespace ns3 diff --git a/src/internet/model/ipv4-interface.h b/src/internet/model/ipv4-interface.h index 64d03e99c..57c48f295 100644 --- a/src/internet/model/ipv4-interface.h +++ b/src/internet/model/ipv4-interface.h @@ -192,6 +192,25 @@ public: */ Ipv4InterfaceAddress RemoveAddress (Ipv4Address address); + /** + * This callback is set when an address is removed from an interface with + * auto-generated Arp cache and it allow the neighbor cache helper to update + * neighbor's Arp cache + * + * \param removeAddressCallback Callback when remove an address. + */ + void RemoveAddressCallback (Callback, Ipv4InterfaceAddress> removeAddressCallback); + + /** + * This callback is set when an address is added from an interface with + * auto-generated Arp cache and it allow the neighbor cache helper to update + * neighbor's Arp cache + * + * \param addAddressCallback Callback when remove an address. + */ + void AddAddressCallback (Callback, Ipv4InterfaceAddress> addAddressCallback); + + protected: virtual void DoDispose (void); @@ -227,6 +246,9 @@ private: Ptr m_device; //!< The associated NetDevice Ptr m_tc; //!< The associated TrafficControlLayer Ptr m_cache; //!< ARP cache + Callback, Ipv4InterfaceAddress> m_removeAddressCallback; //!< remove address callback + Callback, Ipv4InterfaceAddress> m_addAddressCallback; //!< add address callback + }; } // namespace ns3 diff --git a/src/internet/model/ipv6-interface.cc b/src/internet/model/ipv6-interface.cc index f8ebff6c3..634b8c9bf 100644 --- a/src/internet/model/ipv6-interface.cc +++ b/src/internet/model/ipv6-interface.cc @@ -209,6 +209,10 @@ bool Ipv6Interface::AddAddress (Ipv6InterfaceAddress iface) Ipv6Address solicited = Ipv6Address::MakeSolicitedAddress (iface.GetAddress ()); m_addresses.push_back (std::make_pair (iface, solicited)); + if (!m_addAddressCallback.IsNull ()) + { + m_addAddressCallback(this, addr); + } if (!addr.IsAny () || !addr.IsLocalhost ()) { @@ -307,6 +311,10 @@ Ipv6InterfaceAddress Ipv6Interface::RemoveAddress (uint32_t index) { Ipv6InterfaceAddress iface = it->first; m_addresses.erase (it); + if (!m_removeAddressCallback.IsNull ()) + { + m_removeAddressCallback(this, iface); + } return iface; } @@ -334,6 +342,10 @@ Ipv6Interface::RemoveAddress(Ipv6Address address) { Ipv6InterfaceAddress iface = it->first; m_addresses.erase(it); + if (!m_removeAddressCallback.IsNull ()) + { + m_removeAddressCallback(this, iface); + } return iface; } } @@ -522,5 +534,20 @@ Ptr Ipv6Interface::GetNdiscCache () const return m_ndCache; } +void +Ipv6Interface::RemoveAddressCallback (Callback, Ipv6InterfaceAddress> removeAddressCallback) +{ + NS_LOG_FUNCTION (this << &removeAddressCallback); + m_removeAddressCallback = removeAddressCallback; +} + +void +Ipv6Interface::AddAddressCallback (Callback, Ipv6InterfaceAddress> addAddressCallback) +{ + NS_LOG_FUNCTION (this << &addAddressCallback); + m_addAddressCallback = addAddressCallback; +} + + } /* namespace ns3 */ diff --git a/src/internet/model/ipv6-interface.h b/src/internet/model/ipv6-interface.h index c892bb4e3..6cb5bebe6 100644 --- a/src/internet/model/ipv6-interface.h +++ b/src/internet/model/ipv6-interface.h @@ -275,6 +275,24 @@ public: */ Ptr GetNdiscCache () const; + /** + * This callback is set when an address is removed from an interface with + * auto-generated Ndisc cache and it allow the neighbor cache helper to update + * neighbor's Ndisc cache + * + * \param removeAddressCallback Callback when remove an address. + */ + void RemoveAddressCallback (Callback, Ipv6InterfaceAddress> removeAddressCallback); + + /** + * This callback is set when an address is added from an interface with + * auto-generated Ndisc cache and it allow the neighbor cache helper to update + * neighbor's Ndisc cache + * + * \param addAddressCallback Callback when remove an address. + */ + void AddAddressCallback (Callback, Ipv6InterfaceAddress> addAddressCallback); + protected: /** @@ -369,6 +387,10 @@ private: * Time between retransmission of NS. */ uint16_t m_retransTimer; + + Callback, Ipv6InterfaceAddress> m_removeAddressCallback; //!< remove address callback + + Callback, Ipv6InterfaceAddress> m_addAddressCallback; //!< add address callback }; } /* namespace ns3 */ diff --git a/src/internet/test/neighbor-cache-test.cc b/src/internet/test/neighbor-cache-test.cc index 4a51f1ec1..6bcffc32a 100644 --- a/src/internet/test/neighbor-cache-test.cc +++ b/src/internet/test/neighbor-cache-test.cc @@ -24,6 +24,7 @@ #include "ns3/simulator.h" #include "ns3/simple-channel.h" #include "ns3/simple-net-device.h" +#include "ns3/simple-net-device-helper.h" #include "ns3/socket.h" #include "ns3/internet-stack-helper.h" @@ -44,9 +45,9 @@ using namespace ns3; * \ingroup internet-test * \ingroup tests * - * \brief Neighbor cache Test + * \brief Dynamic Neighbor Cache Test */ -class NeighborCacheTest : public TestCase +class DynamicNeighborCacheTest : public TestCase { Ptr m_receivedPacket; //!< Received packet @@ -78,10 +79,38 @@ class NeighborCacheTest : public TestCase */ void SendData (Ptr socket, Ipv6Address to); + /** + * \brief Add an IPv4 address to an IPv4 interface + * \param ipv4Interface The interface that address will be added. + * \param ifaceAddr The added IPv4 address. + */ + void AddIpv4Address (Ptr ipv4Interface, Ipv4InterfaceAddress ifaceAddr); + + /** + * \brief Add an IPv6 address to an IPv6 interface + * \param ipv6Interface The interface that address will be added. + * \param ifaceAddr The added IPv6 address. + */ + void AddIpv6Address (Ptr ipv6Interface, Ipv6InterfaceAddress ifaceAddr); + + /** + * \brief Remove an IPv4 address from an IPv4 interface + * \param ipv4Interface The interface that address will be removed from. + * \param index The index of IPv4 address that will be removed. + */ + void RemoveIpv4Address (Ptr ipv4Interface, uint32_t index); + + /** + * \brief Remove an IPv6 address from an IPv6 interface + * \param ipv6Interface The interface that address will be removed from. + * \param index The index of IPv6 address that will be removed. + */ + void RemoveIpv6Address (Ptr ipv6Interface, uint32_t index); + public: virtual void DoRun (void); - NeighborCacheTest (); + DynamicNeighborCacheTest (); /** * \brief Receive data. @@ -92,11 +121,11 @@ public: std::vector m_receivedPacketSizes; //!< Received packet sizes }; -NeighborCacheTest::NeighborCacheTest () - : TestCase ("NeighborCache") +DynamicNeighborCacheTest::DynamicNeighborCacheTest () + : TestCase ("The DynamicNeighborCacheTestPopulate checks if neighbor caches are correctly populated in global scope and updated when there is an IP address added or removed.") {} -void NeighborCacheTest::ReceivePkt (Ptr socket) +void DynamicNeighborCacheTest::ReceivePkt (Ptr socket) { [[maybe_unused]] uint32_t availableData; availableData = socket->GetRxAvailable (); @@ -106,7 +135,7 @@ void NeighborCacheTest::ReceivePkt (Ptr socket) } void -NeighborCacheTest::DoSendDatav4 (Ptr socket, Ipv4Address to) +DynamicNeighborCacheTest::DoSendDatav4 (Ptr socket, Ipv4Address to) { Address realTo = InetSocketAddress (to, 1234); NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create (123), 0, realTo), @@ -114,7 +143,7 @@ NeighborCacheTest::DoSendDatav4 (Ptr socket, Ipv4Address to) } void -NeighborCacheTest::DoSendDatav6 (Ptr socket, Ipv6Address to) +DynamicNeighborCacheTest::DoSendDatav6 (Ptr socket, Ipv6Address to) { Address realTo = Inet6SocketAddress (to, 1234); NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create (123), 0, realTo), @@ -122,29 +151,54 @@ NeighborCacheTest::DoSendDatav6 (Ptr socket, Ipv6Address to) } void -NeighborCacheTest::SendData (Ptr socket, Ipv4Address to) +DynamicNeighborCacheTest::SendData (Ptr socket, Ipv4Address to) { m_receivedPacket = Create (); Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60), - &NeighborCacheTest::DoSendDatav4, this, socket, to); + &DynamicNeighborCacheTest::DoSendDatav4, this, socket, to); } void -NeighborCacheTest::SendData (Ptr socket, Ipv6Address to) +DynamicNeighborCacheTest::SendData (Ptr socket, Ipv6Address to) { m_receivedPacket = Create (); Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60), - &NeighborCacheTest::DoSendDatav6, this, socket, to); + &DynamicNeighborCacheTest::DoSendDatav6, this, socket, to); } void -NeighborCacheTest::DoRun (void) +DynamicNeighborCacheTest::AddIpv4Address (Ptr ipv4Interface, Ipv4InterfaceAddress ifaceAddr) { - Ptr txNode = CreateObject (); + ipv4Interface->AddAddress (ifaceAddr); +} + +void +DynamicNeighborCacheTest::AddIpv6Address (Ptr ipv6Interface, Ipv6InterfaceAddress ifaceAddr) +{ + ipv6Interface->AddAddress (ifaceAddr); +} + +void +DynamicNeighborCacheTest::RemoveIpv4Address (Ptr ipv4Interface, uint32_t index) +{ + ipv4Interface->RemoveAddress (index); +} + +void +DynamicNeighborCacheTest::RemoveIpv6Address (Ptr ipv6Interface, uint32_t index) +{ + ipv6Interface->RemoveAddress (index); +} + +void +DynamicNeighborCacheTest::DoRun (void) +{ + Ptr tx1Node = CreateObject (); + Ptr tx2Node = CreateObject (); Ptr rxNode = CreateObject (); Ptr snifferNode = CreateObject (); - NodeContainer all (txNode, rxNode, snifferNode); + NodeContainer all (tx1Node, tx2Node, rxNode, snifferNode); std::ostringstream stringStream1v4; Ptr arpStream = Create (&stringStream1v4); @@ -156,19 +210,27 @@ NeighborCacheTest::DoRun (void) NetDeviceContainer net; // Sender Node - Ptr txDev; + Ptr tx1Dev; { - txDev = CreateObject (); - txDev->SetAddress (Mac48Address ("00:00:00:00:00:01")); - txNode->AddDevice (txDev); + tx1Dev = CreateObject (); + tx1Dev->SetAddress (Mac48Address ("00:00:00:00:00:01")); + tx1Node->AddDevice (tx1Dev); } - net.Add (txDev); + net.Add (tx1Dev); + + Ptr tx2Dev; + { + tx2Dev = CreateObject (); + tx2Dev->SetAddress (Mac48Address ("00:00:00:00:00:02")); + tx2Node->AddDevice (tx2Dev); + } + net.Add (tx2Dev); // Recieve node Ptr rxDev; { rxDev = CreateObject (); - rxDev->SetAddress (Mac48Address ("00:00:00:00:00:02")); + rxDev->SetAddress (Mac48Address ("00:00:00:00:00:03")); rxNode->AddDevice (rxDev); } net.Add (rxDev); @@ -177,14 +239,15 @@ NeighborCacheTest::DoRun (void) Ptr snifferDev; { snifferDev = CreateObject (); - snifferDev->SetAddress (Mac48Address ("00:00:00:00:00:03")); + snifferDev->SetAddress (Mac48Address ("00:00:00:00:00:04")); snifferNode->AddDevice (snifferDev); } net.Add (snifferDev); // link the channels Ptr channel = CreateObject (); - txDev->SetChannel (channel); + tx1Dev->SetChannel (channel); + tx2Dev->SetChannel (channel); rxDev->SetChannel (channel); snifferDev->SetChannel (channel); @@ -193,80 +256,238 @@ NeighborCacheTest::DoRun (void) ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0")); Ipv4InterfaceContainer icv4 = ipv4.Assign (net); - //Setup IPv6 addresses + // Add address 10.1.1.5 to rxNode in 0.5 seconds + Ptr n1 = rxNode; + uint32_t ipv4ifIndex = 1; + Ptr ipv4Interface = n1->GetObject ()->GetInterface (ipv4ifIndex); + Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress ("10.0.1.5","255.255.255.0"); + Simulator::Schedule (Seconds (0.5),&DynamicNeighborCacheTest::AddIpv4Address,this, ipv4Interface, ifaceAddr); + + // Remove the first address (10.1.1.3) from rxNode in 1.5 seconds + uint32_t addressIndex = 0; + Simulator::Schedule (Seconds (1.5),&DynamicNeighborCacheTest::RemoveIpv4Address,this, ipv4Interface, addressIndex); + + // Setup IPv6 addresses Ipv6AddressHelper ipv6; ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); Ipv6InterfaceContainer icv6 = ipv6.Assign (net); - //Populate perfect caches. + // Add address 2001:1::200:ff:fe00:5 to rxNode in 0.5 seconds + uint32_t ipv6ifIndex = 1; + Ptr ipv6Interface = n1->GetObject ()->GetInterface (ipv6ifIndex); + Ipv6InterfaceAddress ifaceAddrv6 = Ipv6InterfaceAddress ( "2001:0::200:ff:fe00:5", Ipv6Prefix (64)); + Simulator::Schedule (Seconds (0.5),&DynamicNeighborCacheTest::AddIpv6Address, this, ipv6Interface, ifaceAddrv6); + + // Remove the second address (2001:1::200:ff:fe00:3) from rxNode in 1.5 seconds + addressIndex = 1; + Simulator::Schedule (Seconds (1.5),&DynamicNeighborCacheTest::RemoveIpv6Address, this, ipv6Interface, addressIndex); + + // Populate neighbor caches. NeighborCacheHelper neighborCache; + neighborCache.SetDynamicNeighborCache (true); neighborCache.PopulateNeighborCache (); - //Print cache. + // Print cache. Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), ndiscStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), ndiscStream); // Create the UDP sockets Ptr rxSocketFactory = rxNode->GetObject (); Ptr rxSocketv4 = rxSocketFactory->CreateSocket (); Ptr rxSocketv6 = rxSocketFactory->CreateSocket (); - NS_TEST_EXPECT_MSG_EQ (rxSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.2"), 1234)), 0, "trivial"); - NS_TEST_EXPECT_MSG_EQ (rxSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:2"), 1234)), 0, "trivial"); - rxSocketv4->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this)); - rxSocketv6->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this)); + NS_TEST_EXPECT_MSG_EQ (rxSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.5"), 1234)), 0, "trivial"); + NS_TEST_EXPECT_MSG_EQ (rxSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:5"), 1234)), 0, "trivial"); + rxSocketv4->SetRecvCallback (MakeCallback (&DynamicNeighborCacheTest::ReceivePkt, this)); + rxSocketv6->SetRecvCallback (MakeCallback (&DynamicNeighborCacheTest::ReceivePkt, this)); Ptr snifferSocketFactory = snifferNode->GetObject (); Ptr snifferSocketv4 = snifferSocketFactory->CreateSocket (); Ptr snifferSocketv6 = snifferSocketFactory->CreateSocket (); - NS_TEST_EXPECT_MSG_EQ (snifferSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.3"), 1234)), 0, "trivial"); - NS_TEST_EXPECT_MSG_EQ (snifferSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:3"), 1234)), 0, "trivial"); - snifferSocketv4->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this)); - snifferSocketv6->SetRecvCallback (MakeCallback (&NeighborCacheTest::ReceivePkt, this)); + NS_TEST_EXPECT_MSG_EQ (snifferSocketv4->Bind (InetSocketAddress (Ipv4Address ("10.0.1.4"), 1234)), 0, "trivial"); + NS_TEST_EXPECT_MSG_EQ (snifferSocketv6->Bind (Inet6SocketAddress (Ipv6Address ("2001:0::200:ff:fe00:4"), 1234)), 0, "trivial"); + snifferSocketv4->SetRecvCallback (MakeCallback (&DynamicNeighborCacheTest::ReceivePkt, this)); + snifferSocketv6->SetRecvCallback (MakeCallback (&DynamicNeighborCacheTest::ReceivePkt, this)); - Ptr txSocketFactory = txNode->GetObject (); - Ptr txSocket = txSocketFactory->CreateSocket (); - txSocket->SetAllowBroadcast (true); + Ptr tx1SocketFactory = tx1Node->GetObject (); + Ptr tx1Socket = tx1SocketFactory->CreateSocket (); + tx1Socket->SetAllowBroadcast (true); + + Ptr tx2SocketFactory = tx2Node->GetObject (); + Ptr tx2Socket = tx2SocketFactory->CreateSocket (); + tx2Socket->SetAllowBroadcast (true); // ------ Now the tests ------------ // Unicast test - SendData (txSocket, Ipv4Address ("10.0.1.2")); - SendData (txSocket, Ipv6Address ("2001:0::200:ff:fe00:2")); + + // send data to the added address + SendData (tx1Socket, Ipv4Address ("10.0.1.5")); + SendData (tx1Socket, Ipv6Address ("2001:0::200:ff:fe00:5")); + + // send data to the removed address + SendData (tx1Socket, Ipv4Address ("10.0.1.3")); + SendData (tx1Socket, Ipv6Address ("2001:0::200:ff:fe00:3")); + Simulator::Stop (Seconds (66)); Simulator::Run (); - NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[0], 123, "Perfect Arp should work."); - NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[1], 123, "Perfect Ndp should work."); - NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes.size (), 2, "Perfect Arp and perfect Ndp should have received only 1 packet."); + //Check if all packet are correctly received. + NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[0], 123, "Should receive packet sending to the added IPv4 address."); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes[1], 123, "Should receive packet sending to the added IPv6 address."); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacketSizes.size (), 2, "Should receive only 1 packet from IPv4 interface and only 1 packet from IPv6 interface."); - // Test the Cache + // Check if the arp caches are populated correctly at time 0, + // Check if the arp caches are updated correctly at time 1 after new IP address is added, + // Check if the arp caches are updated correctly at time 2 after an IP address is removed. constexpr auto arpCache = "ARP Cache of node 0 at time 0\n" "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "ARP Cache of node 1 at time 0\n" "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "ARP Cache of node 2 at time 0\n" "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" - "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"; + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "ARP Cache of node 3 at time 0\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 0 at time 1\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 1 at time 1\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 1\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "ARP Cache of node 3 at time 1\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 0 at time 2\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 1 at time 2\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 2\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "ARP Cache of node 3 at time 2\n" + "10.0.1.1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.0.1.2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "10.0.1.5 dev 1 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 ndisc caches are populated correctly at time 0, + // Check if the ndisc caches are updated correctly at time 1 after new IP address is added, + // Check if the ndisc caches are updated correctly at time 2 after an IP address is removed. constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n" "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "NDISC Cache of node 1 at time +0s\n" "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "NDISC Cache of node 2 at time +0s\n" "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" - "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n"; + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 3 at time +0s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 0 at time +1s\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 1 at time +1s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +1s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 3 at time +1s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 0 at time +2s\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 1 at time +2s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +2s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 3 at time +2s\n" + "2001::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "2001::200:ff:fe00:5 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 1 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:2 dev 1 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 1 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + ; NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); m_receivedPacket->RemoveAllByteTags (); @@ -278,14 +499,675 @@ NeighborCacheTest::DoRun (void) * \ingroup internet-test * \ingroup tests * - * \brief IPv4 RIP TestSuite + * \brief Neighbor cache on Channel Test + */ +class ChannelTest : public TestCase +{ +public: + virtual void DoRun (void); + ChannelTest (); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +ChannelTest::ChannelTest () + : TestCase ("The ChannelTest Check if neighbor caches are correctly populated on specific channel.") +{} + +void +ChannelTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Populate neighbor caches on the first channel + NeighborCacheHelper neighborCache; + neighborCache.PopulateNeighborCache (channel); + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + + Simulator::Run (); + + // Check if arp caches are populated correctly in the first channel + 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" + "ARP Cache of node 1 at time 0\n" + "10.1.1.1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 0\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v4.str (), arpCache, "Arp cache is incorrect."); + + // Check if ndisc caches are populated correctly in the first channel + 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" + "fe80::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 1 at time +0s\n" + "2001::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +0s\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief Neighbor Cache on NetDeviceContainer Test + */ +class NetDeviceContainerTest : public TestCase +{ +public: + virtual void DoRun (void); + NetDeviceContainerTest (); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +NetDeviceContainerTest::NetDeviceContainerTest () + : TestCase ("The NetDeviceContainerTest check if neighbor caches are populated correctly on specific netDeviceContainer.") +{} + +void +NetDeviceContainerTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Populate neighbor caches on NetDeviceContainer net2. + NeighborCacheHelper neighborCache; + neighborCache.PopulateNeighborCache (net2); + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + + Simulator::Run (); + + // Check if arp caches are populated correctly on NetDeviceContainer net2. + constexpr auto arpCache = "ARP Cache of node 0 at time 0\n" + "ARP Cache of node 1 at time 0\n" + "10.1.2.2 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 0\n" + "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 ndisc caches are populated correctly on NetDeviceContainer net2. + constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n" + "NDISC Cache of node 1 at time +0s\n" + "2001:1::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +0s\n" + "2001:1::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief Neighbor Cache on InterfaceContainer Test + */ +class InterfaceContainerTest : public TestCase +{ +public: + virtual void DoRun (void); + InterfaceContainerTest (); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +InterfaceContainerTest::InterfaceContainerTest () + : TestCase ("The InterfaceContainerTest check if neighbor caches are populated correctly on specific interfaceContainer.") +{} + +void +InterfaceContainerTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Populate neighbor caches on Ipv4InterfaceContainer i and Ipv6InterfaceContainer icv62. + NeighborCacheHelper neighborCache; + neighborCache.PopulateNeighborCache (i); + neighborCache.PopulateNeighborCache (icv62); + + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + + Simulator::Run (); + + // Check if arp caches are populated correctly on Ipv4InterfaceContainer i. + 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" + "ARP Cache of node 1 at time 0\n" + "10.1.1.1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 0\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v4.str (), arpCache, "Arp cache is incorrect."); + + // Check if ndisc caches are populated correctly on Ipv6InterfaceContainer icv62. + constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n" + "NDISC Cache of node 1 at time +0s\n" + "2001:1::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +0s\n" + "2001:1::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief Neighbor Cache Flush Test + */ +class FlushTest : public TestCase +{ +public: + virtual void DoRun (void); + FlushTest (); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +FlushTest::FlushTest () + : TestCase ("The FlushTest checks that FlushAutoGenerated() will only remove STATIC_AUTOGENERATED entries.") +{} + +void +FlushTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Populate STATIC_AUTOGENERATED neighbor cache + NeighborCacheHelper neighborCache; + neighborCache.PopulateNeighborCache (); + + // Manually add an PERMANENT arp cache entry + std::pair, uint32_t> returnValue = i.Get (0); + Ptr v4 = returnValue.first; + uint32_t index = returnValue.second; + Ptr iface = DynamicCast (v4)->GetInterface (index); + Ptr arpCache = iface->GetArpCache (); + ArpCache::Entry* arpCacheEntry = arpCache->Add (Ipv4Address ("10.1.1.4")); + arpCacheEntry->SetMacAddress (Mac48Address ("04-06-00:00:00:00:00:01")); + arpCacheEntry->MarkPermanent (); + + // Manually add an PERMANENT ndisc entry + std::pair, uint32_t> returnValue2 = icv61.Get (0); + Ptr v6 = returnValue2.first; + index = returnValue2.second; + Ptr ifacev6 = DynamicCast (v6)->GetInterface (index); + Ptr ndiscCache = ifacev6->GetNdiscCache (); + NdiscCache::Entry* ndiscCacheEntry = ndiscCache->Add (Ipv6Address ("2001::200:ff:fe00:4")); + ndiscCacheEntry->SetMacAddress (Mac48Address ("04-06-00:00:00:00:00:01")); + ndiscCacheEntry->MarkPermanent (); + + // flush auto-generated cache + neighborCache.FlushAutoGenerated (); + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + + Simulator::Run (); + // 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" + "ARP Cache of node 1 at time 0\n" + "ARP Cache of node 2 at time 0\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. + constexpr auto NdiscCache = "NDISC Cache of node 0 at time +0s\n" + "2001::200:ff:fe00:4 dev 0 lladdr 04-06-00:00:00:00:00:01 PERMANENT\n" + "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."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief Neighbor Cache on Overlapped Scope Test + */ +class DuplicateTest : public TestCase +{ +public: + virtual void DoRun (void); + DuplicateTest (); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +DuplicateTest::DuplicateTest () + : TestCase ("The DuplicateTest checks that populate neighbor caches in overlapped scope does not raise an error or generate duplicate entries.") +{} + +void +DuplicateTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Populate neighbor cache in overlapped scope. + NeighborCacheHelper neighborCache; + neighborCache.PopulateNeighborCache (); + neighborCache.PopulateNeighborCache (channel); + neighborCache.PopulateNeighborCache (net2); + neighborCache.PopulateNeighborCache (icv61); + neighborCache.PopulateNeighborCache (); + + + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + + Simulator::Run (); + // 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.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "ARP Cache of node 1 at time 0\n" + "10.1.1.1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "10.1.2.2 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 0\n" + "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. + 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" + "fe80::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 1 at time +0s\n" + "2001::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "2001:1::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:4 dev 1 lladdr 04-06-00:00:00:00:00:04 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +0s\n" + "2001:1::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:3 dev 0 lladdr 04-06-00:00:00:00:00:03 STATIC_AUTOGENERATED\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief Dynamic Neighbor Cache on Reduced Scope Test + */ +class DynamicPartialTest : public TestCase +{ +public: + virtual void DoRun (void); + DynamicPartialTest (); + + /** + * \brief Add an IPv4 address to an IPv4 interface + * \param ipv4Interface The interface that address will be added. + * \param ifaceAddr The added IPv4 address. + */ + void AddIpv4Address (Ptr ipv4Interface, Ipv4InterfaceAddress ifaceAddr); + + /** + * \brief Add an IPv6 address to an IPv6 interface + * \param ipv6Interface The interface that address will be added. + * \param ifaceAddr The added IPv6 address. + */ + void AddIpv6Address (Ptr ipv6Interface, Ipv6InterfaceAddress ifaceAddr); + + /** + * \brief Remove an IPv4 address from an IPv4 interface + * \param ipv4Interface The interface that address will be removed from. + * \param index The index of IPv4 address that will be removed. + */ + void RemoveIpv4Address (Ptr ipv4Interface, uint32_t index); + + /** + * \brief Remove an IPv6 address from an IPv6 interface + * \param ipv6Interface The interface that address will be removed from. + * \param index The index of IPv6 address that will be removed. + */ + void RemoveIpv6Address (Ptr ipv6Interface, uint32_t index); + +private: + NodeContainer m_nodes; //!< Nodes used in the test. +}; + +DynamicPartialTest::DynamicPartialTest () + : TestCase ("The DynamicPartialTest checks if dynamic neighbor cache update correctly when generating on a non-global scope.") +{} + +void +DynamicPartialTest::AddIpv4Address (Ptr ipv4Interface, Ipv4InterfaceAddress ifaceAddr) +{ + ipv4Interface->AddAddress (ifaceAddr); +} + +void +DynamicPartialTest::AddIpv6Address (Ptr ipv6Interface, Ipv6InterfaceAddress ifaceAddr) +{ + ipv6Interface->AddAddress (ifaceAddr); +} + +void +DynamicPartialTest::RemoveIpv4Address (Ptr ipv4Interface, uint32_t index) +{ + ipv4Interface->RemoveAddress (index); +} + +void +DynamicPartialTest::RemoveIpv6Address (Ptr ipv6Interface, uint32_t index) +{ + ipv6Interface->RemoveAddress (index); +} + +void +DynamicPartialTest::DoRun () +{ + m_nodes.Create (3); + + Ptr channel = CreateObject (); + SimpleNetDeviceHelper simpleHelper; + NetDeviceContainer net = simpleHelper.Install (m_nodes.Get (0), channel); + net.Add (simpleHelper.Install (m_nodes.Get (1), channel)); + + Ptr channel2 = CreateObject (); + SimpleNetDeviceHelper simpleHelper2; + NetDeviceContainer net2 = simpleHelper.Install (m_nodes.Get (1), channel2); + net2.Add (simpleHelper2.Install (m_nodes.Get (2), channel2)); + + InternetStackHelper internet; + internet.Install (m_nodes); + + // Setup IPv4 addresses + Ipv4AddressHelper ipv4; + ipv4.SetBase ("10.1.1.0", "255.255.255.252"); + Ipv4InterfaceContainer i = ipv4.Assign (net); + ipv4.SetBase ("10.1.2.0", "255.255.255.252"); + Ipv4InterfaceContainer i2 = ipv4.Assign (net2); + + // Add address 10.1.1.5 to n1 in 0.5 seconds + Ptr n1 = m_nodes.Get (0); + uint32_t ipv4ifIndex = 1; + Ptr ipv4Interface = n1->GetObject ()->GetInterface (ipv4ifIndex); + Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress ("10.1.1.5","255.255.255.0"); + Simulator::Schedule (Seconds (0.5),&DynamicPartialTest::AddIpv4Address,this, ipv4Interface, ifaceAddr); + + // Remove the first address (10.1.1.1) from n1 in 1.5 seconds + uint32_t addressIndex = 0; + Simulator::Schedule (Seconds (1.5),&DynamicPartialTest::RemoveIpv4Address,this, ipv4Interface, addressIndex); + + //Setup IPv6 addresses + Ipv6AddressHelper ipv6; + ipv6.SetBase (Ipv6Address ("2001:0::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv61 = ipv6.Assign (net); + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer icv62 = ipv6.Assign (net2); + + // Add address 2001:1::200:ff:fe00:5 to n1 in 0.5 seconds + uint32_t ipv6ifIndex = 1; + Ptr ipv6Interface = n1->GetObject ()->GetInterface (ipv6ifIndex); + Ipv6InterfaceAddress ifaceAddrv6 = Ipv6InterfaceAddress ( "2001:0::200:ff:fe00:5", Ipv6Prefix (64)); + Simulator::Schedule (Seconds (0.5),&DynamicPartialTest::AddIpv6Address, this, ipv6Interface, ifaceAddrv6); + + // Remove the second address (2001:1::200:ff:fe00:1) from n1 in 1.5 seconds + addressIndex = 1; + Simulator::Schedule (Seconds (1.5),&DynamicPartialTest::RemoveIpv6Address, this, ipv6Interface, addressIndex); + + // Populate dynamic neighbor cache on the first channel + NeighborCacheHelper neighborCache; + neighborCache.SetDynamicNeighborCache (true); + neighborCache.PopulateNeighborCache (channel); + + std::ostringstream stringStream1v4; + Ptr arpStream = Create (&stringStream1v4); + std::ostringstream stringStream1v6; + Ptr ndiscStream = Create (&stringStream1v6); + + // Print cache. + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (0), ndiscStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (1), ndiscStream); + Ipv4RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), arpStream); + Ipv6RoutingHelper::PrintNeighborCacheAllAt (Seconds (2), ndiscStream); + + Simulator::Run (); + // Check if the dynamic neighbor cache doesn't change after an Ip address is added, + // Check if the dynamic neighbor cache update correctly after an Ip address is removed. + 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" + "ARP Cache of node 1 at time 0\n" + "10.1.1.1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 0\n" + "ARP Cache of node 0 at time 1\n" + "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "ARP Cache of node 1 at time 1\n" + "10.1.1.1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "ARP Cache of node 2 at time 1\n" + "ARP Cache of node 0 at time 2\n" + "10.1.1.2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "ARP Cache of node 1 at time 2\n" + "ARP Cache of node 2 at time 2\n"; + NS_TEST_EXPECT_MSG_EQ (stringStream1v4.str (), ArpCache, "Arp cache is incorrect."); + + // Check if the dynamic neighbor cache doesn't change after an Ip address is added, + // Check if the dynamic neighbor cache update correctly after an Ip address is removed. + 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" + "fe80::200:ff:fe00:2 dev 0 lladdr 04-06-00:00:00:00:00:02 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 1 at time +0s\n" + "2001::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +0s\n" + "NDISC Cache of node 0 at time +1s\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" + "NDISC Cache of node 1 at time +1s\n" + "2001::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "fe80::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +1s\n" + "NDISC Cache of node 0 at time +2s\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" + "NDISC Cache of node 1 at time +2s\n" + "fe80::200:ff:fe00:1 dev 0 lladdr 04-06-00:00:00:00:00:01 STATIC_AUTOGENERATED\n" + "NDISC Cache of node 2 at time +2s\n" + ; + NS_TEST_EXPECT_MSG_EQ (stringStream1v6.str (), NdiscCache, "Ndisc cache is incorrect."); + Simulator::Destroy (); +} + +/** + * \ingroup internet-test + * \ingroup tests + * + * \brief NeighborCache TestSuite */ class NeighborCacheTestSuite : public TestSuite { public: NeighborCacheTestSuite () : TestSuite ("neighbor-cache", UNIT) { - AddTestCase (new NeighborCacheTest, TestCase::QUICK); + AddTestCase (new DynamicNeighborCacheTest, TestCase::QUICK); + AddTestCase (new ChannelTest, TestCase::QUICK); + AddTestCase (new NetDeviceContainerTest, TestCase::QUICK); + AddTestCase (new InterfaceContainerTest, TestCase::QUICK); + AddTestCase (new FlushTest, TestCase::QUICK); + AddTestCase (new DuplicateTest, TestCase::QUICK); + AddTestCase (new DynamicPartialTest, TestCase::QUICK); } };