nix-routing: Print Routing Path

- Add a public function `Ipv4NixVectorRouting::PrintRoutingPath`
  It takes source node pointer, destination IPv4 address, the
  OutputStreamWrapper and Time unit as input.

- Add `Ipv4NixVectorHelper::PrintRoutingPathAt` which will help
  to schedule the printing time. Also, it exposes the function
  with the helper class (which is more user-friendly)

- Overwrite the existing `nix-simple.cc` UDP Echo program with
  the PrintRoutingPath implementation.

Sample Output for `src/nix-vector-routing/examples/nix-simple.cc`:

```
Time: +0s, Nix Routing
Route Path: (Node 0 to Node 3, Nix Vector: 101)
10.1.4.1 (Node 0)   ---->   10.1.4.2 (Node 2)
10.1.3.1 (Node 2)   ---->   10.1.3.2 (Node 3)

Time: +2s, Nix Routing
Route Path: (Node 1 to Node 3, Nix Vector: 101)
10.1.2.1 (Node 1)   ---->   10.1.2.2 (Node 2)
10.1.3.1 (Node 2)   ---->   10.1.3.2 (Node 3)

Time: +5s, Nix Routing
Route Path: (Node 2 to Node 0, Nix Vector: 10)
10.1.4.2 (Node 2)   ---->   10.1.4.1 (Node 0)

Time: +6s, Nix Routing
Route Path: (Node 1 to Node 1, Nix Vector: )
10.1.1.2 (Node 1)   ---->   10.1.1.2 (Node 1)
```

Signed-off-by: Ameya Deshpande <ameyanrd@outlook.com>
This commit is contained in:
Ameya Deshpande
2021-03-16 15:52:33 +05:30
committed by Tommaso Pecorella
parent b8a96f327e
commit 894d786e24
5 changed files with 277 additions and 17 deletions

View File

@@ -23,19 +23,89 @@
#include "ns3/ipv4-list-routing-helper.h"
#include "ns3/ipv4-nix-vector-helper.h"
/*
* Simple point to point links:
/**
* This program demonstrates two types of
* trace output that are available:
* 1) Print Routing Table for all the nodes.
* 2) Print Routing Path, given source and destination.
*
* n0 -- n1 -- n2 -- n3
*
* n0 has UdpEchoClient
* n3 has UdpEchoServer
*
* n0 IP: 10.1.1.1
* n1 IP: 10.1.1.2, 10.1.2.1
* n2 IP: 10.1.2.2, 10.1.3.1
* n3 IP: 10.1.3.2
* Simple point to point links:
* \verbatim
________
/ \
n0 -- n1 -- n2 -- n3
n0 IP: 10.1.1.1, 10.1.4.1
n1 IP: 10.1.1.2, 10.1.2.1
n2 IP: 10.1.2.2, 10.1.3.1, 10.1.4.2
n3 IP: 10.1.3.2
\endverbatim
*
* Route Path for considered cases:
* - Source (n0) and Destination (n3)
* It goes from n0 -> n2 -> n3
* - Source (n1) and Destination (n3)
* It goes from n1 -> n2 -> n3
* - Source (n2) and Destination (n0)
* It goes from n2 -> n0
* - Source (n1) and Destination (n1)
* It goes from n1 -> n1
* .
* \verbatim
Expected Routing Path output for above
cases (in the output stream):
Time: +3s, Nix Routing
Route Path: (Node 0 to Node 3, Nix Vector: 101)
10.1.4.1 (Node 0) ----> 10.1.4.2 (Node 2)
10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
Time: +5s, Nix Routing
Route Path: (Node 1 to Node 3, Nix Vector: 101)
10.1.2.1 (Node 1) ----> 10.1.2.2 (Node 2)
10.1.3.1 (Node 2) ----> 10.1.3.2 (Node 3)
Time: +6s, Nix Routing
Route Path: (Node 2 to Node 0, Nix Vector: 10)
10.1.4.2 (Node 2) ----> 10.1.4.1 (Node 0)
Time: +7s, Nix Routing
Route Path: (Node 1 to Node 1, Nix Vector: )
10.1.1.2 (Node 1) ----> 10.1.1.2 (Node 1)
Node: 0, Time: +8s, Local time: +8s, Nix Routing
NixCache:
Destination NixVector
10.1.3.2 101
Ipv4RouteCache:
Destination Gateway Source OutputDevice
10.1.3.2 10.1.4.2 10.1.4.1 2
Node: 1, Time: +8s, Local time: +8s, Nix Routing
NixCache:
Destination NixVector
10.1.3.2 101
Ipv4RouteCache:
Destination Gateway Source OutputDevice
10.1.3.2 10.1.2.2 10.1.2.1 2
Node: 2, Time: +8s, Local time: +8s, Nix Routing
NixCache:
Destination NixVector
10.1.1.1 10
Ipv4RouteCache:
Destination Gateway Source OutputDevice
10.1.1.1 10.1.4.1 10.1.4.2 3
10.1.3.2 10.1.3.2 10.1.3.1 2
10.1.4.1 10.1.4.1 10.1.4.2 3
Node: 3, Time: +8s, Local time: +8s, Nix Routing
NixCache:
Destination NixVector
10.1.4.1 010
Ipv4RouteCache:
Destination Gateway Source OutputDevice
10.1.4.1 10.1.3.1 10.1.3.2 1
\endverbatim
*/
using namespace ns3;
@@ -47,7 +117,7 @@ main (int argc, char *argv[])
{
CommandLine cmd (__FILE__);
cmd.Parse (argc, argv);
LogComponentEnable ("UdpEchoClientApplication", LOG_LEVEL_INFO);
LogComponentEnable ("UdpEchoServerApplication", LOG_LEVEL_INFO);
@@ -62,6 +132,10 @@ main (int argc, char *argv[])
nodes34.Add (nodes23.Get (1));
nodes34.Create (1);
NodeContainer nodes13;
nodes13.Add (nodes12.Get (0));
nodes13.Add (nodes34.Get (0));
PointToPointHelper pointToPoint;
pointToPoint.SetDeviceAttribute ("DataRate", StringValue ("5Mbps"));
pointToPoint.SetChannelAttribute ("Delay", StringValue ("2ms"));
@@ -78,9 +152,11 @@ main (int argc, char *argv[])
NetDeviceContainer devices12;
NetDeviceContainer devices23;
NetDeviceContainer devices34;
NetDeviceContainer devices13;
devices12 = pointToPoint.Install (nodes12);
devices23 = pointToPoint.Install (nodes23);
devices34 = pointToPoint.Install (nodes34);
devices13 = pointToPoint.Install (nodes13);
Ipv4AddressHelper address1;
address1.SetBase ("10.1.1.0", "255.255.255.0");
@@ -88,10 +164,13 @@ main (int argc, char *argv[])
address2.SetBase ("10.1.2.0", "255.255.255.0");
Ipv4AddressHelper address3;
address3.SetBase ("10.1.3.0", "255.255.255.0");
Ipv4AddressHelper address4;
address4.SetBase ("10.1.4.0", "255.255.255.0");
address1.Assign (devices12);
address2.Assign (devices23);
Ipv4InterfaceContainer interfaces = address3.Assign (devices34);
Ipv4InterfaceContainer interfaces12 = address1.Assign (devices12);
Ipv4InterfaceContainer interfaces23 = address2.Assign (devices23);
Ipv4InterfaceContainer interfaces34 = address3.Assign (devices34);
Ipv4InterfaceContainer interfaces13 = address4.Assign (devices13);
UdpEchoServerHelper echoServer (9);
@@ -99,7 +178,7 @@ main (int argc, char *argv[])
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (interfaces.GetAddress (1), 9);
UdpEchoClientHelper echoClient (interfaces34.GetAddress (1), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
@@ -108,8 +187,13 @@ main (int argc, char *argv[])
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
// Trace routing tables
// Trace routing paths for different source and destinations.
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ("nix-simple.routes", std::ios::out);
nixRouting.PrintRoutingPathAt (Seconds (3), nodes12.Get (0), interfaces34.GetAddress (1), routingStream);
nixRouting.PrintRoutingPathAt (Seconds (5), nodes12.Get (1), interfaces34.GetAddress (1), routingStream);
nixRouting.PrintRoutingPathAt (Seconds (6), nodes23.Get (1), interfaces12.GetAddress (0), routingStream);
nixRouting.PrintRoutingPathAt (Seconds (7), nodes12.Get (1), interfaces12.GetAddress (1), routingStream);
// Trace routing tables
nixRouting.PrintRoutingTableAllAt (Seconds (8), routingStream);
Simulator::Run ();

View File

@@ -47,4 +47,19 @@ Ipv4NixVectorHelper::Create (Ptr<Node> node) const
node->AggregateObject (agent);
return agent;
}
void
Ipv4NixVectorHelper::PrintRoutingPathAt (Time printTime, Ptr<Node> source, Ipv4Address dest, Ptr<OutputStreamWrapper> stream, Time::Unit unit)
{
Simulator::Schedule (printTime, &Ipv4NixVectorHelper::PrintRoute, source, dest, stream, unit);
}
void
Ipv4NixVectorHelper::PrintRoute (Ptr<Node> source, Ipv4Address dest, Ptr<OutputStreamWrapper> stream, Time::Unit unit)
{
Ptr<Ipv4NixVectorRouting> rp = Ipv4RoutingHelper::GetRouting <Ipv4NixVectorRouting> (source->GetObject<Ipv4> ()->GetRoutingProtocol ());
NS_ASSERT (rp);
rp->PrintRoutingPath (source, dest, stream, unit);
}
} // namespace ns3

View File

@@ -66,6 +66,22 @@ public:
*/
virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const;
/**
* \brief prints the routing path for a source and destination at a particular time.
* If the routing path does not exist, it prints that the path does not exist between
* the nodes in the ostream.
* \param printTime the time at which the routing path is supposed to be printed.
* \param source the source node pointer to start traversing
* \param dest the IPv4 destination address
* \param stream the output stream object to use
* \param unit the time unit to be used in the report
*
* This method calls the PrintRoutingPath() method of the
* Ipv4NixVectorRouting for the source and destination to provide
* the routing path at the specified time.
*/
void PrintRoutingPathAt (Time printTime, Ptr<Node> source, Ipv4Address dest, Ptr<OutputStreamWrapper> stream, Time::Unit unit = Time::S);
private:
/**
* \brief Assignment operator declared private and not implemented to disallow
@@ -75,6 +91,20 @@ private:
Ipv4NixVectorHelper &operator = (const Ipv4NixVectorHelper &);
ObjectFactory m_agentFactory; //!< Object factory
/**
* \brief prints the routing path for the source and destination. If the routing path
* does not exist, it prints that the path does not exist between the nodes in the ostream.
* \param source the source node pointer to start traversing
* \param dest the IPv4 destination address
* \param stream the output stream object to use
* \param unit the time unit to be used in the report
*
* This method calls the PrintRoutingPath() method of the
* Ipv4NixVectorRouting for the source and destination to provide
* the routing path.
*/
static void PrintRoute (Ptr<Node> source, Ipv4Address dest, Ptr<OutputStreamWrapper> stream, Time::Unit unit = Time::S);
};
} // namespace ns3

View File

@@ -968,6 +968,127 @@ Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr<Node> source,
return false;
}
void
Ipv4NixVectorRouting::PrintRoutingPath (Ptr<Node> source, Ipv4Address dest,
Ptr<OutputStreamWrapper> stream, Time::Unit unit)
{
NS_LOG_FUNCTION (this << source << dest);
Ptr<NixVector> nixVectorInCache;
Ptr<NixVector> nixVector;
Ptr<Ipv4Route> rtentry;
Ptr<Node> destNode = GetNodeByIp (dest);
std::ostream* os = stream->GetStream ();
// Copy the current ostream state
std::ios oldState (nullptr);
oldState.copyfmt (*os);
*os << std::resetiosflags (std::ios::adjustfield) << std::setiosflags (std::ios::left);
*os << "Time: " << Now().As (unit)
<< ", Nix Routing" << std::endl;
*os << "Route Path: ";
*os << "(Node " << source->GetId () << " to Node " << destNode->GetId () << ", ";
*os << "Nix Vector: ";
nixVectorInCache = GetNixVectorInCache (dest);
// not in cache
if (!nixVectorInCache)
{
NS_LOG_LOGIC ("Nix-vector not in cache, build: ");
// Build the nix-vector, given the source node and the
// dest IP address
nixVectorInCache = GetNixVector (source, dest, nullptr);
}
if (nixVectorInCache || (!nixVectorInCache && source == destNode))
{
Ptr<Node> curr = source;
if (nixVectorInCache)
{
// cache it
m_nixCache.insert (NixMap_t::value_type (dest, nixVectorInCache));
// Make a NixVector copy to work with. This is because
// we don't want to extract the bits from nixVectorInCache
// which is stored in the m_nixCache.
nixVector = Create<NixVector> ();
nixVector = nixVectorInCache->Copy ();
*os << *nixVector;
}
*os << ")" << std::endl;
if (source == destNode)
{
std::ostringstream src, dst;
src << dest << " (Node " << destNode->GetId () << ")";
*os << std::setw (20) << src.str ();
dst << "----> " << dest << " (Node " << destNode->GetId () << ")";
*os << dst.str () << std::endl;
}
while (curr != destNode)
{
// set m_node as current node
// and find the total neighbors
SetNode (curr);
m_totalNeighbors = FindTotalNeighbors ();
// Get the number of bits required
// to represent all the neighbors
uint32_t numberOfBits = nixVector->BitCount (m_totalNeighbors);
// Get the nixIndex
uint32_t nixIndex = nixVector->ExtractNeighborIndex (numberOfBits);
// gatewayIP is the IP of next
// node on channel found from nixIndex
Ipv4Address gatewayIp;
// Get the Net Device index from the nixIndex
uint32_t NetDeviceIndex = FindNetDeviceForNixIndex (nixIndex, gatewayIp);
// Get the interfaceIndex with the help of NetDeviceIndex.
// It will be used to get the IP address on interfaceIndex
// interface of 'curr' node.
Ptr<Ipv4> ipv4 = curr->GetObject<Ipv4> ();
Ptr<NetDevice> outDevice = curr->GetDevice (NetDeviceIndex);
uint32_t interfaceIndex = ipv4->GetInterfaceForDevice (outDevice);
Ipv4Address sourceIPAddr = ipv4->GetAddress (interfaceIndex, 0).GetLocal ();
rtentry = GetIpv4RouteInCache (dest);
if (!rtentry)
{
NS_LOG_LOGIC ("Ipv4Route not in cache, build: ");
// start filling in the Ipv4Route info
rtentry = Create<Ipv4Route> ();
rtentry->SetSource (sourceIPAddr);
rtentry->SetGateway (gatewayIp);
rtentry->SetDestination (dest);
rtentry->SetOutputDevice (outDevice);
// add rtentry to cache
m_ipv4RouteCache.insert (Ipv4RouteMap_t::value_type (dest, rtentry));
}
std::ostringstream currNode, nextNode;
currNode << sourceIPAddr << " (Node " << curr->GetId () << ")";
*os << std::setw (20) << currNode.str ();
// Replace curr with the next node
curr = GetNodeByIp (gatewayIp);
nextNode << "----> " << gatewayIp << " (Node " << curr->GetId () << ")";
*os << nextNode.str () << std::endl;
}
*os << std::endl;
}
else
{
*os << ")" << std::endl;
// No Route exists
*os << "There does not exist a path from Node " << source->GetId ()
<< " to Node " << destNode->GetId () << "." << std::endl;
}
// Restore the previous ostream state
(*os).copyfmt (oldState);
}
void
Ipv4NixVectorRouting::CheckCacheStateAndFlush (void) const
{

View File

@@ -89,6 +89,16 @@ public:
*/
void FlushGlobalNixRoutingCache (void) const;
/**
* @brief Print the Routing Path according to Nix Routing
* \param source Source node
* \param dest Destination node address
* \param stream The ostream the Routing path is printed to
* \param unit the time unit to be used in the report
*/
void PrintRoutingPath (Ptr<Node> source, Ipv4Address dest, Ptr<OutputStreamWrapper> stream, Time::Unit unit);
private:
/**