From 894d786e24b23d387f250e9cd9ea9bbbc8b11526 Mon Sep 17 00:00:00 2001 From: Ameya Deshpande Date: Tue, 16 Mar 2021 15:52:33 +0530 Subject: [PATCH] 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 --- src/nix-vector-routing/examples/nix-simple.cc | 118 ++++++++++++++--- .../helper/ipv4-nix-vector-helper.cc | 15 +++ .../helper/ipv4-nix-vector-helper.h | 30 +++++ .../model/ipv4-nix-vector-routing.cc | 121 ++++++++++++++++++ .../model/ipv4-nix-vector-routing.h | 10 ++ 5 files changed, 277 insertions(+), 17 deletions(-) diff --git a/src/nix-vector-routing/examples/nix-simple.cc b/src/nix-vector-routing/examples/nix-simple.cc index 67e036df5..64d3e0aaa 100644 --- a/src/nix-vector-routing/examples/nix-simple.cc +++ b/src/nix-vector-routing/examples/nix-simple.cc @@ -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 routingStream = Create ("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 (); diff --git a/src/nix-vector-routing/helper/ipv4-nix-vector-helper.cc b/src/nix-vector-routing/helper/ipv4-nix-vector-helper.cc index 3913843be..a27842962 100644 --- a/src/nix-vector-routing/helper/ipv4-nix-vector-helper.cc +++ b/src/nix-vector-routing/helper/ipv4-nix-vector-helper.cc @@ -47,4 +47,19 @@ Ipv4NixVectorHelper::Create (Ptr node) const node->AggregateObject (agent); return agent; } + +void +Ipv4NixVectorHelper::PrintRoutingPathAt (Time printTime, Ptr source, Ipv4Address dest, Ptr stream, Time::Unit unit) +{ + Simulator::Schedule (printTime, &Ipv4NixVectorHelper::PrintRoute, source, dest, stream, unit); +} + +void +Ipv4NixVectorHelper::PrintRoute (Ptr source, Ipv4Address dest, Ptr stream, Time::Unit unit) +{ + Ptr rp = Ipv4RoutingHelper::GetRouting (source->GetObject ()->GetRoutingProtocol ()); + NS_ASSERT (rp); + rp->PrintRoutingPath (source, dest, stream, unit); +} + } // namespace ns3 diff --git a/src/nix-vector-routing/helper/ipv4-nix-vector-helper.h b/src/nix-vector-routing/helper/ipv4-nix-vector-helper.h index cfa41e205..0ede68478 100644 --- a/src/nix-vector-routing/helper/ipv4-nix-vector-helper.h +++ b/src/nix-vector-routing/helper/ipv4-nix-vector-helper.h @@ -66,6 +66,22 @@ public: */ virtual Ptr Create (Ptr 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 source, Ipv4Address dest, Ptr 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 source, Ipv4Address dest, Ptr stream, Time::Unit unit = Time::S); }; } // namespace ns3 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 49404b68a..a341bbc9c 100644 --- a/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc +++ b/src/nix-vector-routing/model/ipv4-nix-vector-routing.cc @@ -968,6 +968,127 @@ Ipv4NixVectorRouting::BFS (uint32_t numberOfNodes, Ptr source, return false; } +void +Ipv4NixVectorRouting::PrintRoutingPath (Ptr source, Ipv4Address dest, + Ptr stream, Time::Unit unit) +{ + NS_LOG_FUNCTION (this << source << dest); + Ptr nixVectorInCache; + Ptr nixVector; + Ptr rtentry; + + Ptr 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 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 = 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 = curr->GetObject (); + Ptr 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 (); + 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 { 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 168bb90a3..b495cfb8a 100644 --- a/src/nix-vector-routing/model/ipv4-nix-vector-routing.h +++ b/src/nix-vector-routing/model/ipv4-nix-vector-routing.h @@ -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 source, Ipv4Address dest, Ptr stream, Time::Unit unit); + + private: /**