nix-vector-routing: Make nix-vector routing thread-safe
This commit is contained in:
@@ -41,8 +41,22 @@ NS_LOG_COMPONENT_DEFINE ("NixVectorRouting");
|
||||
NS_OBJECT_TEMPLATE_CLASS_DEFINE (NixVectorRouting, Ipv4RoutingProtocol);
|
||||
NS_OBJECT_TEMPLATE_CLASS_DEFINE (NixVectorRouting, Ipv6RoutingProtocol);
|
||||
|
||||
#ifdef NS3_MTP
|
||||
template <typename T>
|
||||
std::atomic<bool> NixVectorRouting<T>::g_isCacheDirty (false);
|
||||
|
||||
template <typename T>
|
||||
std::atomic<bool> NixVectorRouting<T>::g_cacheFlushing (false);
|
||||
|
||||
template <typename T>
|
||||
std::atomic<bool> NixVectorRouting<T>::g_isMapBuilt (false);
|
||||
|
||||
template <typename T>
|
||||
std::atomic<bool> NixVectorRouting<T>::g_mapBuilding (false);
|
||||
#else
|
||||
template <typename T>
|
||||
bool NixVectorRouting<T>::g_isCacheDirty = false;
|
||||
#endif
|
||||
|
||||
// Epoch starts from one to make it easier to spot an uninitialized NixVector during debug.
|
||||
template <typename T>
|
||||
@@ -162,6 +176,9 @@ NixVectorRouting<T>::FlushGlobalNixRoutingCache (void) const
|
||||
// IP address to node mapping is potentially invalid so clear it.
|
||||
// Will be repopulated in lazy evaluation when mapping is needed.
|
||||
g_ipAddressToNodeMap.clear ();
|
||||
#ifdef NS3_MTP
|
||||
g_isMapBuilt.store (false, std::memory_order_release);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -500,10 +517,27 @@ NixVectorRouting<T>::GetNodeByIp (IpAddress dest) const
|
||||
NS_LOG_FUNCTION (this << dest);
|
||||
|
||||
// Populate lookup table if is empty.
|
||||
#ifdef NS3_MTP
|
||||
if (!g_isMapBuilt.load (std::memory_order_acquire))
|
||||
{
|
||||
if (g_mapBuilding.exchange (true, std::memory_order_relaxed))
|
||||
{
|
||||
while (!g_isMapBuilt.load (std::memory_order_acquire))
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildIpAddressToNodeMap ();
|
||||
g_isMapBuilt.store (true, std::memory_order_release);
|
||||
g_mapBuilding.store (false, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ( g_ipAddressToNodeMap.empty () )
|
||||
{
|
||||
BuildIpAddressToNodeMap ();
|
||||
}
|
||||
#endif
|
||||
|
||||
Ptr<Node> destNode;
|
||||
|
||||
@@ -527,10 +561,27 @@ Ptr<typename NixVectorRouting<T>::IpInterface>
|
||||
NixVectorRouting<T>::GetInterfaceByNetDevice (Ptr<NetDevice> netDevice) const
|
||||
{
|
||||
// Populate lookup table if is empty.
|
||||
#ifdef NS3_MTP
|
||||
if (!g_isMapBuilt.load (std::memory_order_acquire))
|
||||
{
|
||||
if (g_mapBuilding.exchange (true, std::memory_order_relaxed))
|
||||
{
|
||||
while (!g_isMapBuilt.load (std::memory_order_acquire))
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildIpAddressToNodeMap ();
|
||||
g_isMapBuilt.store (true, std::memory_order_release);
|
||||
g_mapBuilding.store (false, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if ( g_netdeviceToIpInterfaceMap.empty () )
|
||||
{
|
||||
BuildIpAddressToNodeMap ();
|
||||
}
|
||||
#endif
|
||||
|
||||
Ptr<IpInterface> ipInterface;
|
||||
|
||||
@@ -1039,37 +1090,61 @@ template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyInterfaceUp (uint32_t i)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyInterfaceDown (uint32_t i)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyAddAddress (uint32_t interface, IpInterfaceAddress address)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyRemoveAddress (uint32_t interface, IpInterfaceAddress address)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyAddRoute (IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::NotifyRemoveRoute (IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse)
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
g_isCacheDirty.store (true, std::memory_order_release);
|
||||
#else
|
||||
g_isCacheDirty = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -1365,12 +1440,29 @@ template <typename T>
|
||||
void
|
||||
NixVectorRouting<T>::CheckCacheStateAndFlush (void) const
|
||||
{
|
||||
#ifdef NS3_MTP
|
||||
if (g_isCacheDirty.load (std::memory_order_acquire))
|
||||
{
|
||||
if (g_cacheFlushing.exchange (true, std::memory_order_relaxed))
|
||||
{
|
||||
while (g_isCacheDirty.load (std::memory_order_acquire))
|
||||
;
|
||||
}
|
||||
else
|
||||
{
|
||||
FlushGlobalNixRoutingCache ();
|
||||
g_isCacheDirty.store (false, std::memory_order_release);
|
||||
g_cacheFlushing.store (false, std::memory_order_release);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (g_isCacheDirty)
|
||||
{
|
||||
FlushGlobalNixRoutingCache ();
|
||||
g_epoch++;
|
||||
g_isCacheDirty = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Public template function declarations */
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/ipv6-l3-protocol.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
@@ -446,7 +447,14 @@ private:
|
||||
* Flag to mark when caches are dirty and need to be flushed.
|
||||
* Used for lazy cleanup of caches when there are many topology changes.
|
||||
*/
|
||||
#ifdef NS3_MTP
|
||||
static std::atomic<bool> g_isCacheDirty;
|
||||
static std::atomic<bool> g_cacheFlushing;
|
||||
static std::atomic<bool> g_isMapBuilt;
|
||||
static std::atomic<bool> g_mapBuilding;
|
||||
#else
|
||||
static bool g_isCacheDirty;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Nix Epoch, incremented each time a flush is perfomed.
|
||||
|
||||
Reference in New Issue
Block a user