From 8fa163fb0aacbfcaab7e542f0aa86d8d194c4b2f Mon Sep 17 00:00:00 2001 From: Steven Smith Date: Fri, 21 Aug 2020 15:31:04 -0700 Subject: [PATCH] nix-vector-routing: (merges !380) Provide faster lookups by IP address Use hash table to lookup nodes by IP addresses rather than linear search --- .../model/ipv4-nix-vector-routing.cc | 71 +++++++++++++++---- .../model/ipv4-nix-vector-routing.h | 37 +++++++++- 2 files changed, 93 insertions(+), 15 deletions(-) diff --git a/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc b/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc index 4b2d36bad..e400b1d20 100644 --- a/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc +++ b/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc @@ -25,6 +25,7 @@ #include "ns3/abort.h" #include "ns3/names.h" #include "ns3/ipv4-list-routing.h" +#include "ns3/loopback-net-device.h" #include "ipv4-nix-vector-routing.h" @@ -35,6 +36,7 @@ NS_LOG_COMPONENT_DEFINE ("Ipv4NixVectorRouting"); NS_OBJECT_ENSURE_REGISTERED (Ipv4NixVectorRouting); bool Ipv4NixVectorRouting::g_isCacheDirty = false; +Ipv4NixVectorRouting::Ipv4AddressToNodeMap Ipv4NixVectorRouting::g_ipv4AddressToNodeMap; TypeId Ipv4NixVectorRouting::GetTypeId (void) @@ -105,6 +107,10 @@ Ipv4NixVectorRouting::FlushGlobalNixRoutingCache (void) const rp->FlushNixCache (); rp->FlushIpv4RouteCache (); } + + // IPv4 address to node mapping is potentially invalid so clear it. + // Will be repopulated in lazy evaluation when mapping is needed. + g_ipv4AddressToNodeMap.clear (); } void @@ -342,29 +348,68 @@ Ipv4NixVectorRouting::GetAdjacentNetDevices (Ptr netDevice, Ptr -Ipv4NixVectorRouting::GetNodeByIp (Ipv4Address dest) -{ +void +Ipv4NixVectorRouting::BuildIpv4AddressToNodeMap (void) +{ NS_LOG_FUNCTION_NOARGS (); - NodeContainer allNodes = NodeContainer::GetGlobal (); - Ptr destNode; - - for (NodeContainer::Iterator i = allNodes.Begin (); i != allNodes.End (); ++i) + for (NodeList::Iterator it = NodeList::Begin (); it != NodeList::End (); ++it) { - Ptr node = *i; + Ptr node = *it; Ptr ipv4 = node->GetObject (); - if (ipv4->GetInterfaceForAddress (dest) != -1) + + if(ipv4) { - destNode = node; - break; + uint32_t numberOfDevices = node->GetNDevices (); + + for (uint32_t deviceId = 0; deviceId < numberOfDevices; deviceId++) + { + Ptr device = node->GetDevice (deviceId); + + // If this is not a loopback device add the IPv4 address to the map + if ( !DynamicCast(device) ) + { + int32_t interfaceIndex = (ipv4)->GetInterfaceForDevice (node->GetDevice (deviceId)); + if (interfaceIndex != -1) + { + Ipv4InterfaceAddress ifAddr = ipv4->GetAddress (interfaceIndex, 0); + Ipv4Address addr = ifAddr.GetLocal (); + + NS_ABORT_MSG_IF (g_ipv4AddressToNodeMap.count (addr), + "Duplicate IPv4 address (" << addr << ") found during NIX Vector map construction for node " << node->GetId ()); + + NS_LOG_LOGIC ("Adding IPv4 address " << addr << " for node " << node->GetId () << " to NIX Vector IPv4 address to node map"); + g_ipv4AddressToNodeMap[addr] = node; + } + } + } } } +} - if (!destNode) +Ptr +Ipv4NixVectorRouting::GetNodeByIp (Ipv4Address dest) +{ + NS_LOG_FUNCTION_NOARGS (); + + // Populate lookup table if is empty. + if ( g_ipv4AddressToNodeMap.empty () ) + { + BuildIpv4AddressToNodeMap (); + } + + Ptr destNode; + + Ipv4AddressToNodeMap::iterator iter = g_ipv4AddressToNodeMap.find(dest); + + if(iter == g_ipv4AddressToNodeMap.end ()) { NS_LOG_ERROR ("Couldn't find dest node given the IP" << dest); - return 0; + destNode = 0; + } + else + { + destNode = iter -> second; } return destNode; diff --git a/src/nix-vector-routing/model/ipv4-nix-vector-routing.h b/src/nix-vector-routing/model/ipv4-nix-vector-routing.h index 5e43acf65..168bb90a3 100644 --- a/src/nix-vector-routing/model/ipv4-nix-vector-routing.h +++ b/src/nix-vector-routing/model/ipv4-nix-vector-routing.h @@ -21,8 +21,6 @@ #ifndef IPV4_NIX_VECTOR_ROUTING_H #define IPV4_NIX_VECTOR_ROUTING_H -#include - #include "ns3/channel.h" #include "ns3/node-container.h" #include "ns3/node-list.h" @@ -33,6 +31,9 @@ #include "ns3/bridge-net-device.h" #include "ns3/nstime.h" +#include +#include + namespace ns3 { /** @@ -227,6 +228,11 @@ private: */ void CheckCacheStateAndFlush (void) const; + /** + * Build map from IPv4 Address to Node for faster lookup. + */ + void BuildIpv4AddressToNodeMap (void); + /** * Flag to mark when caches are dirty and need to be flushed. * Used for lazy cleanup of caches when there are many topology changes. @@ -244,6 +250,33 @@ private: /** Total neighbors used for nix-vector to determine number of bits */ uint32_t m_totalNeighbors; + + + /** + * \brief Hashing for the ipv4Address class + */ + struct Ipv4AddressHash + { + /** + * \brief operator () + * \param address the IPv4 address to hash + * \return the hash of the address + */ + size_t operator() (const Ipv4Address &address) const + { + return std::hash()(address.Get ()); + } + }; + + /** + * Mapping of IPv4 address to ns-3 node. + * + * Used to avoid linear searching of nodes/devices to find a node in + * GetNodeByIp() method. NIX vector routing assumes IP addresses + * are unique so mapping can be done without duplication. + **/ + typedef std::unordered_map, Ipv4AddressHash > Ipv4AddressToNodeMap; + static Ipv4AddressToNodeMap g_ipv4AddressToNodeMap; }; } // namespace ns3