17#include "ns3/ipv4-list-routing.h"
19#include "ns3/loopback-net-device.h"
52 if constexpr (std::is_same_v<T, Ipv4RoutingProtocol>)
60 static TypeId tid =
TypeId(
"ns3::" + name +
"NixVectorRouting")
62 .SetGroupName(
"NixVectorRouting")
108 for (
uint32_t i = 0;
i < m_ip->GetNInterfaces();
i++)
110 m_ip->SetForwarding(
i,
true);
153 rp->FlushIpRouteCache();
154 rp->m_totalNeighbors = 0;
159 g_ipAddressToNodeMap.clear();
175 m_ipRouteCache.clear();
237 CheckCacheStateAndFlush();
239 auto iter = m_nixCache.find(address);
240 if (
iter != m_nixCache.end())
258 CheckCacheStateAndFlush();
260 auto iter = m_ipRouteCache.find(address);
261 if (
iter != m_ipRouteCache.end())
327 Ptr<Node> remoteNode = (*iter)->GetNode();
329 if (remoteNode->GetId() ==
dest)
339 <<
" bits, for node " <<
parentNode->GetId());
359 NS_LOG_LOGIC(
"IpInterface either doesn't exist or is down");
365 for (std::size_t
i = 0;
i < channel->GetNDevices();
i++)
374 NS_LOG_LOGIC(
"IpInterface either doesn't exist or is down");
384 if constexpr (!IsIpv4)
394 if constexpr (!IsIpv4)
424 NS_LOG_LOGIC(
"Looking through bridge ports of bridge net device " <<
bd);
430 NS_LOG_LOGIC(
"That bridge port is me, don't walk backward");
485 g_ipAddressToNodeMap.count(addr),
486 "Duplicate IP address ("
488 <<
") found during NIX Vector map construction for node "
492 << addr <<
" for node " << node->GetId()
493 <<
" to NIX Vector IP address to node map");
494 g_ipAddressToNodeMap[addr] = node;
510 if (g_ipAddressToNodeMap.empty())
512 BuildIpAddressToNodeMap();
517 auto iter = g_ipAddressToNodeMap.find(
dest);
519 if (
iter == g_ipAddressToNodeMap.end())
537 if (g_netdeviceToIpInterfaceMap.empty())
539 BuildIpAddressToNodeMap();
546 if (
iter == g_netdeviceToIpInterfaceMap.end())
619 "NixVectorRouting::NetDeviceIsBridged (): GetObject for <BridgeNetDevice> failed");
624 if (
bnd->GetBridgePort(
j) ==
nd)
697 CheckCacheStateAndFlush();
706 rtentry->SetSource(IpAddress::GetLoopback());
708 rtentry->SetGateway(IpAddress::GetZero());
709 for (
uint32_t i = 0;
i < m_ip->GetNInterfaces();
i++)
722 if constexpr (!IsIpv4)
729 "Try to send on link-local multicast address, and no interface index is given!");
732 m_ip->SourceAddressSelection(m_ip->GetInterfaceForDevice(oif),
destAddress));
768 if (m_totalNeighbors == 0)
770 m_totalNeighbors = FindTotalNeighbors(m_node);
801 interfaceIndex = (m_ip)->GetInterfaceForDevice(m_node->GetDevice(index));
864 NS_LOG_FUNCTION(
this << p << header << header.GetSource() << header.GetDestination() <<
idev);
866 CheckCacheStateAndFlush();
877 if constexpr (IsIpv4)
885 p->SetNixVector(
nullptr);
909 if (m_ip->IsForwarding(
iif) ==
false)
931 <<
") - rebuilding it");
938 if (m_totalNeighbors == 0)
940 m_totalNeighbors = FindTotalNeighbors(m_node);
974 if constexpr (IsIpv4)
992 CheckCacheStateAndFlush();
994 std::ostream* os = stream->GetStream();
999 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
1001 *os <<
"Node: " << m_node->GetId() <<
", Time: " <<
Now().
As(unit)
1002 <<
", Local time: " << m_node->GetLocalTime().As(unit) <<
", Nix Routing" << std::endl;
1004 *os <<
"NixCache:" << std::endl;
1005 if (m_nixCache.size() > 0)
1007 *os << std::setw(30) <<
"Destination";
1008 *os <<
"NixVector" << std::endl;
1009 for (
auto it = m_nixCache.begin();
it != m_nixCache.end();
it++)
1011 std::ostringstream
dest;
1013 *os << std::setw(30) <<
dest.str();
1016 *os << *(
it->second) << std::endl;
1020 *os <<
"-" << std::endl;
1025 *os <<
"IpRouteCache:" << std::endl;
1026 if (m_ipRouteCache.size() > 0)
1028 *os << std::setw(30) <<
"Destination";
1029 *os << std::setw(30) <<
"Gateway";
1030 *os << std::setw(30) <<
"Source";
1031 *os <<
"OutputDevice" << std::endl;
1032 for (
auto it = m_ipRouteCache.begin();
it != m_ipRouteCache.end();
it++)
1034 std::ostringstream
dest;
1035 std::ostringstream
gw;
1036 std::ostringstream src;
1037 dest <<
it->second->GetDestination();
1038 *os << std::setw(30) <<
dest.str();
1039 gw <<
it->second->GetGateway();
1040 *os << std::setw(30) <<
gw.str();
1041 src <<
it->second->GetSource();
1042 *os << std::setw(30) << src.str();
1050 *os <<
it->second->GetOutputDevice()->GetIfIndex();
1061template <
typename T>
1065 g_isCacheDirty =
true;
1068template <
typename T>
1072 g_isCacheDirty =
true;
1075template <
typename T>
1079 g_isCacheDirty =
true;
1082template <
typename T>
1086 g_isCacheDirty =
true;
1089template <
typename T>
1097 g_isCacheDirty =
true;
1100template <
typename T>
1108 g_isCacheDirty =
true;
1111template <
typename T>
1158 if (!(oif->IsLinkUp()))
1180 Ptr<Node> remoteNode = (*iter)->GetNode();
1184 NS_LOG_LOGIC(
"IpInterface either doesn't exist or is down");
1243 Ptr<Node> remoteNode = (*iter)->GetNode();
1247 NS_LOG_LOGIC(
"IpInterface either doesn't exist or is down");
1273template <
typename T>
1286 CheckCacheStateAndFlush();
1295 std::ostream* os = stream->GetStream();
1300 *os << std::resetiosflags(std::ios::adjustfield) << std::setiosflags(std::ios::left);
1301 *os <<
"Time: " <<
Now().
As(unit) <<
", Nix Routing" << std::endl;
1302 *os <<
"Route path from ";
1303 *os <<
"Node " <<
source->GetId() <<
" to Node " <<
destNode->GetId() <<
", ";
1304 *os <<
"Nix Vector: ";
1337 std::ostringstream addr;
1338 std::ostringstream node;
1340 node <<
"(Node " <<
destNode->GetId() <<
")";
1341 *os << std::setw(25) << addr.str();
1342 *os << std::setw(10) << node.str();
1344 *os << std::setw(25) << addr.str();
1345 *os << node.str() << std::endl;
1381 std::ostringstream nextAddr;
1385 *os << std::setw(25) <<
currAddr.str();
1386 *os << std::setw(10) <<
currNode.str();
1392 *os << std::setw(25) << nextAddr.str();
1393 *os <<
nextNode.str() << std::endl;
1399 *os <<
")" << std::endl;
1401 *os <<
"There does not exist a path from Node " <<
source->GetId() <<
" to Node "
1402 <<
destNode->GetId() <<
"." << std::endl;
1408template <
typename T>
1414 FlushGlobalNixRoutingCache();
1416 g_isCacheDirty =
false;
a virtual net device that bridges multiple LAN segments
static Ipv6Address GetZero()
Get the 0 (::) Ipv6Address.
@ LINKLOCAL
Link-local address (fe80::/64)
Describes an IPv6 prefix.
static std::string FindName(Ptr< Object > object)
Given a pointer to an object, look to see if that object has a name associated with it and,...
holds a vector of ns3::NetDevice pointers
Nix-vector routing protocol.
void PrintRoutingPath(Ptr< Node > source, IpAddress dest, Ptr< OutputStreamWrapper > stream, Time::Unit unit) const
Print the Routing Path according to Nix Routing.
void BuildIpAddressToNodeMap() const
Build map from IP Address to Node for faster lookup.
Ptr< IpRoute > GetIpRouteInCache(IpAddress address)
Checks the cache based on dest IP for the IpRoute.
virtual void NotifyRemoveRoute(IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse=IpAddress::GetZero())
Notify route removing.
virtual void NotifyAddRoute(IpAddress dst, Ipv6Prefix mask, IpAddress nextHop, uint32_t interface, IpAddress prefixToUse=IpAddress::GetZero())
Notify a new route.
typename std::conditional_t< IsIpv4, Ipv4InterfaceAddress, Ipv6InterfaceAddress > IpInterfaceAddress
Alias for Ipv4InterfaceAddress and Ipv6InterfaceAddress classes.
bool BFS(uint32_t numberOfNodes, Ptr< Node > source, Ptr< Node > dest, std::vector< Ptr< Node > > &parentVector, Ptr< NetDevice > oif) const
Breadth first search algorithm.
static uint32_t g_epoch
Nix Epoch, incremented each time a flush is performed.
virtual void NotifyInterfaceUp(uint32_t interface)
void GetAdjacentNetDevices(Ptr< NetDevice > netDevice, Ptr< Channel > channel, NetDeviceContainer &netDeviceContainer) const
Given a net-device returns all the adjacent net-devices, essentially getting the neighbors on that ch...
std::conditional_t< IsIpv4, UnicastForwardCallbackv4, UnicastForwardCallbackv6 > UnicastForwardCallback
Callback for unicast packets to be forwarded.
virtual void NotifyInterfaceDown(uint32_t interface)
typename std::conditional_t< IsIpv4, Ipv4Address, Ipv6Address > IpAddress
Alias for Ipv4Address and Ipv6Address classes.
static IpAddressToNodeMap g_ipAddressToNodeMap
Address to node map.
void FlushGlobalNixRoutingCache() const
Called when run-time link topology change occurs which iterates through the node list and flushes any...
virtual void SetIpv6(Ptr< Ip > ipv6)
Typically, invoked directly or indirectly from ns3::Ipv6::SetRoutingProtocol.
virtual Ptr< IpRoute > RouteOutput(Ptr< Packet > p, const IpHeader &header, Ptr< NetDevice > oif, Socket::SocketErrno &sockerr)
Query routing cache for an existing route, for an outbound packet.
virtual void SetIpv4(Ptr< Ip > ipv4)
Typically, invoked directly or indirectly from ns3::Ipv4::SetRoutingProtocol.
Ptr< IpInterface > GetInterfaceByNetDevice(Ptr< NetDevice > netDevice) const
Iterates through the node list and finds the one corresponding to the given IpAddress.
uint32_t FindTotalNeighbors(Ptr< Node > node) const
Simply iterates through the nodes net-devices and determines how many neighbors the node has.
virtual void NotifyAddAddress(uint32_t interface, IpInterfaceAddress address)
std::conditional_t< IsIpv4, MulticastForwardCallbackv4, MulticastForwardCallbackv6 > MulticastForwardCallback
Callback for multicast packets to be forwarded.
void FlushIpRouteCache() const
Flushes the cache which stores the Ip route based on the destination IP.
virtual bool RouteInput(Ptr< const Packet > p, const IpHeader &header, Ptr< const NetDevice > idev, const UnicastForwardCallback &ucb, const MulticastForwardCallback &mcb, const LocalDeliverCallback &lcb, const ErrorCallback &ecb)
Route an input packet (to be forwarded or locally delivered)
Ptr< NixVector > GetNixVector(Ptr< Node > source, IpAddress dest, Ptr< NetDevice > oif) const
Takes in the source node and dest IP and calls GetNodeByIp, BFS, accounting for any output interface ...
typename std::conditional_t< IsIpv4, Ipv4Header, Ipv6Header > IpHeader
Alias for Ipv4Header and Ipv6Header classes.
bool BuildNixVector(const std::vector< Ptr< Node > > &parentVector, uint32_t source, uint32_t dest, Ptr< NixVector > nixVector) const
Recurses the T vector, created by BFS and actually builds the nixvector.
Ptr< NixVector > GetNixVectorInCache(const IpAddress &address, bool &foundInCache) const
Checks the cache based on dest IP for the nix-vector.
uint32_t FindNetDeviceForNixIndex(Ptr< Node > node, uint32_t nodeIndex, IpAddress &gatewayIp) const
Nix index is with respect to the neighbors.
static NetDeviceToIpInterfaceMap g_netdeviceToIpInterfaceMap
NetDevice pointer to IpInterface pointer map.
void SetNode(Ptr< Node > node)
Set the Node pointer of the node for which this routing protocol is to be placed.
virtual void PrintRoutingTable(Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S) const
Print the Routing Table entries.
typename std::conditional_t< IsIpv4, Ipv4L3Protocol, Ipv6L3Protocol > IpL3Protocol
Alias for Ipv4L3Protocol and Ipv4L3Protocol classes.
virtual void NotifyRemoveAddress(uint32_t interface, IpInterfaceAddress address)
static TypeId GetTypeId()
The Interface ID of the Global Router interface.
static bool g_isCacheDirty
Flag to mark when caches are dirty and need to be flushed.
void CheckCacheStateAndFlush() const
Flushes routing caches if required.
std::unordered_map< IpAddress, ns3::Ptr< ns3::Node >, IpAddressHash > IpAddressToNodeMap
Mapping of IP address to ns-3 node.
std::unordered_map< Ptr< NetDevice >, Ptr< IpInterface > > NetDeviceToIpInterfaceMap
Mapping of Ptr<NetDevice> to Ptr<IpInterface>.
Ptr< BridgeNetDevice > NetDeviceIsBridged(Ptr< NetDevice > nd) const
Determine if the NetDevice is bridged.
void FlushNixCache() const
Flushes the cache which stores nix-vector based on destination IP.
Ptr< Node > GetNodeByIp(IpAddress dest) const
Iterates through the node list and finds the one corresponding to the given IpAddress.
static uint32_t GetNNodes()
Smart pointer class similar to boost::intrusive_ptr.
SocketErrno
Enumeration of the possible errors returned by a socket.
TimeWithUnit As(const Unit unit=Time::AUTO) const
Attach a unit to a Time, to facilitate output in a specific unit.
Unit
The unit to use to interpret a number representing time.
a unique identifier for an interface.
TypeId SetParent(TypeId tid)
Set the parent TypeId.
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
#define NS_ASSERT_MSG(condition, message)
At runtime, in debugging builds, if this condition is not true, the program prints the message to out...
#define NS_ABORT_MSG_UNLESS(cond, msg)
Abnormal program termination if a condition is false, with a message.
#define NS_ABORT_MSG_IF(cond, msg)
Abnormal program termination if a condition is true, with a message.
#define NS_LOG_ERROR(msg)
Use NS_LOG to output a message of level LOG_ERROR.
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_OBJECT_TEMPLATE_CLASS_DEFINE(type, param)
Explicitly instantiate a template class with one template parameter and register the resulting instan...
Ptr< T > Create(Ts &&... args)
Create class instances by constructors with varying numbers of arguments and return them by Ptr.
Time Now()
create an ns3::Time instance which contains the current simulation time.
Every class exported by the ns3 library is enclosed in the ns3 namespace.