internet: GSoC-22 update automatic ARP/NDISC cache when network changes

This commit is contained in:
Zhiheng Dong
2022-09-14 15:48:09 -07:00
committed by Tommaso Pecorella
parent 24ee65fb23
commit 90d6e08bb4
13 changed files with 1512 additions and 49 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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``.

View File

@@ -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``.

View File

@@ -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}
)

View File

@@ -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 <dzh2077@gmail.com>
*/
/**
* 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> 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> 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> 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> 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<Node> n1 = csmaNodes.Get (0);
uint32_t ipv4ifIndex = 1;
Ptr<Ipv4Interface> ipv4Interface = n1->GetObject<Ipv4L3Protocol> ()->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<OutputStreamWrapper> outputStream = Create<OutputStreamWrapper> (&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<Node> n1 = csmaNodes.Get (0);
uint32_t ipv6ifIndex = 1;
Ptr<Ipv6Interface> ipv6Interface = n1->GetObject<Ipv6L3Protocol> ()->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<OutputStreamWrapper> outputStream = Create<OutputStreamWrapper> (&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;
}

View File

@@ -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> channel = ChannelList::GetChannel (i);
@@ -205,6 +206,14 @@ NeighborCacheHelper::PopulateNeighborEntriesIpv4 (Ptr<Ipv4Interface> 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<Ipv6Interface> 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<Ipv4Interface> interface, const Ipv4InterfaceAddress ifAddr) const
{
NS_LOG_FUNCTION (this);
Ptr<NetDevice> netDevice = interface->GetDevice ();
Ptr<Channel> channel = netDevice->GetChannel ();
for (std::size_t i = 0; i < channel->GetNDevices (); ++i)
{
Ptr<NetDevice> neighborDevice = channel->GetDevice (i);
Ptr<Node> neighborNode = neighborDevice->GetNode ();
int32_t neighborInterfaceIndex = neighborNode->GetObject<Ipv4> ()->GetInterfaceForDevice (neighborDevice);
if (neighborInterfaceIndex != -1)
{
Ptr<Ipv4Interface> neighborInterface = neighborNode->GetObject<Ipv4L3Protocol> ()->GetInterface (neighborInterfaceIndex);
Ptr<ArpCache> 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<Ipv4Interface> interface, const Ipv4InterfaceAddress ifAddr) const
{
NS_LOG_FUNCTION (this);
Ptr<NetDevice> netDevice = interface->GetDevice ();
Ptr<Channel> channel = netDevice->GetChannel ();
for (std::size_t i = 0; i < channel->GetNDevices (); ++i)
{
Ptr<NetDevice> neighborDevice = channel->GetDevice (i);
if (neighborDevice != netDevice)
{
Ptr<Node> neighborNode = neighborDevice->GetNode ();
int32_t neighborInterfaceIndex = neighborNode->GetObject<Ipv4> ()->GetInterfaceForDevice (neighborDevice);
if (neighborInterfaceIndex != -1)
{
Ptr<Ipv4Interface> neighborInterface = neighborNode->GetObject<Ipv4L3Protocol> ()->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<Ipv6Interface> interface, const Ipv6InterfaceAddress ifAddr) const
{
NS_LOG_FUNCTION (this);
Ptr<NetDevice> netDevice = interface->GetDevice ();
Ptr<Channel> channel = netDevice->GetChannel ();
for (std::size_t i = 0; i < channel->GetNDevices (); ++i)
{
Ptr<NetDevice> neighborDevice = channel->GetDevice (i);
Ptr<Node> neighborNode = neighborDevice->GetNode ();
int32_t neighborInterfaceIndex = neighborNode->GetObject<Ipv6> ()->GetInterfaceForDevice (neighborDevice);
if (neighborInterfaceIndex != -1)
{
Ptr<Ipv6Interface> neighborInterface = neighborNode->GetObject<Ipv6L3Protocol> ()->GetInterface (neighborInterfaceIndex);
Ptr<NdiscCache> 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<Ipv6Interface> interface, const Ipv6InterfaceAddress ifAddr) const
{
NS_LOG_FUNCTION (this);
Ptr<NetDevice> netDevice = interface->GetDevice ();
Ptr<Channel> channel = netDevice->GetChannel ();
for (std::size_t i = 0; i < channel->GetNDevices (); ++i)
{
Ptr<NetDevice> neighborDevice = channel->GetDevice (i);
if (neighborDevice != netDevice)
{
Ptr<Node> neighborNode = neighborDevice->GetNode ();
int32_t neighborInterfaceIndex = neighborNode->GetObject<Ipv6> ()->GetInterfaceForDevice (neighborDevice);
if (neighborInterfaceIndex != -1)
{
Ptr<Ipv6Interface> neighborInterface = neighborNode->GetObject<Ipv6L3Protocol> ()->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

View File

@@ -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<Ipv6Interface> 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<Ipv4Interface> 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<Ipv4Interface> 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<Ipv6Interface> 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<Ipv6Interface> 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

View File

@@ -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<void, Ptr<Ipv4Interface>, Ipv4InterfaceAddress> removeAddressCallback)
{
NS_LOG_FUNCTION (this << &removeAddressCallback);
m_removeAddressCallback = removeAddressCallback;
}
void
Ipv4Interface::AddAddressCallback (Callback<void, Ptr<Ipv4Interface>, Ipv4InterfaceAddress> addAddressCallback)
{
NS_LOG_FUNCTION (this << &addAddressCallback);
m_addAddressCallback = addAddressCallback;
}
} // namespace ns3

View File

@@ -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<void, Ptr<Ipv4Interface>, 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<void, Ptr<Ipv4Interface>, Ipv4InterfaceAddress> addAddressCallback);
protected:
virtual void DoDispose (void);
@@ -227,6 +246,9 @@ private:
Ptr<NetDevice> m_device; //!< The associated NetDevice
Ptr<TrafficControlLayer> m_tc; //!< The associated TrafficControlLayer
Ptr<ArpCache> m_cache; //!< ARP cache
Callback<void, Ptr<Ipv4Interface>, Ipv4InterfaceAddress> m_removeAddressCallback; //!< remove address callback
Callback<void, Ptr<Ipv4Interface>, Ipv4InterfaceAddress> m_addAddressCallback; //!< add address callback
};
} // namespace ns3

View File

@@ -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<NdiscCache> Ipv6Interface::GetNdiscCache () const
return m_ndCache;
}
void
Ipv6Interface::RemoveAddressCallback (Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> removeAddressCallback)
{
NS_LOG_FUNCTION (this << &removeAddressCallback);
m_removeAddressCallback = removeAddressCallback;
}
void
Ipv6Interface::AddAddressCallback (Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback)
{
NS_LOG_FUNCTION (this << &addAddressCallback);
m_addAddressCallback = addAddressCallback;
}
} /* namespace ns3 */

View File

@@ -275,6 +275,24 @@ public:
*/
Ptr<NdiscCache> 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<void, Ptr<Ipv6Interface>, 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<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> addAddressCallback);
protected:
/**
@@ -369,6 +387,10 @@ private:
* Time between retransmission of NS.
*/
uint16_t m_retransTimer;
Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> m_removeAddressCallback; //!< remove address callback
Callback<void, Ptr<Ipv6Interface>, Ipv6InterfaceAddress> m_addAddressCallback; //!< add address callback
};
} /* namespace ns3 */

File diff suppressed because it is too large Load Diff