# HG changeset patch # User Tom Henderson # Date 1273690610 25200 # Node ID d9990845c9ff0af490843385a120e38b1d9c8a9a # Parent b2b5d61f5946c47670fcce615f86d5fba4e0d71d bug 702: make global routing robust to interface events diff -r b2b5d61f5946 -r d9990845c9ff doc/manual/routing.texi --- a/doc/manual/routing.texi Tue May 11 08:56:28 2010 +0100 +++ b/doc/manual/routing.texi Wed May 12 11:56:50 2010 -0700 @@ -147,6 +147,16 @@ &Ipv4GlobalRoutingHelper::RecomputeRoutingTables); @end verbatim +There are two attributes that govern the behavior. The first is +Ipv4GlobalRouting::RandomEcmpRouting. If set to true, packets are randomly +routed across equal-cost multipath routes. If set to false (default), +only one route is consistently used. The second is +Ipv4GlobalRouting::RespondToInterfaceEvents. If set to true, dynamically +recompute the global routes upon Interface notification events (up/down, +or add/remove address). If set to false (default), routing may break +unless the user manually calls RecomputeRoutingTables() after such events. +The default is set to false to preserve legacy ns-3 program behavior. + @subsection Global Routing Implementation This section is for those readers who care about how this is implemented. diff -r b2b5d61f5946 -r d9990845c9ff examples/routing/dynamic-global-routing.cc --- a/examples/routing/dynamic-global-routing.cc Tue May 11 08:56:28 2010 +0100 +++ b/examples/routing/dynamic-global-routing.cc Wed May 12 11:56:50 2010 -0700 @@ -18,7 +18,10 @@ // This script exercises global routing code in a mixed point-to-point -// and csma/cd environment +// and csma/cd environment. We bring up and down interfaces and observe +// the effect on global routing. We explicitly enable the attribute +// to respond to interface events, so that routes are recomputed +// automatically. // // Network topology // @@ -41,33 +44,20 @@ // n1 to n6 is via the direct point-to-point link // At time 1s, start CBR traffic flow from n1 to n6 // At time 2s, set the n1 point-to-point interface to down. Packets -// will start to be dropped -// At time 3s, call RecomputeRoutingTables() and traffic will -// start flowing again on the alternate path -// At time 4s, re-enable the n1/n6 interface to up. Will not change routing -// At time 5s, call RecomputeRoutingTables() and traffic will start flowing -// again on the original path +// will be diverted to the n1-n2-n5-n6 path +// At time 4s, re-enable the n1/n6 interface to up. n1-n6 route restored. // At time 6s, set the n6-n1 point-to-point Ipv4 interface to down (note, this -// keeps the point-to-point link "up" from n1's perspective). Packets -// will traverse the link and be dropped at n6 upon receipt. These drops -// are not visible in the pcap trace but in the ascii trace. -// At time 7s, call RecomputeRoutingTables() and traffic will flow again -// through the path n1-n2-n5-n6 -// At time 8s, bring the interface back up. -// At time 9s, call RecomputeRoutingTables() and traffic will flow again -// through the path n1-n6 +// keeps the point-to-point link "up" from n1's perspective). Traffic will +// flow through the path n1-n2-n5-n6 +// At time 8s, bring the interface back up. Path n1-n6 is restored // At time 10s, stop the first flow. // At time 11s, start a new flow, but to n6's other IP address (the one // on the n1/n6 p2p link) // At time 12s, bring the n1 interface down between n1 and n6. Packets -// will start to be dropped -// At time 13s, call RecomputeRoutingTables() and traffic will -// start flowing again on the alternate path +// will be diverted to the alternate path // At time 14s, re-enable the n1/n6 interface to up. This will change // routing back to n1-n6 since the interface up notification will cause // a new local interface route, at higher priority than global routing -// At time 15s, call RecomputeRoutingTables(), but there is no effect -// since global routing is lower in priority than static routing // At time 16s, stop the second flow. // - Tracing of queues and packet receptions to file "dynamic-global-routing.tr" @@ -89,6 +79,10 @@ int main (int argc, char *argv[]) { + // The below value configures the default behavior of global routing. + // By default, it is disabled. To respond to interface events, set to true + Config::SetDefault ("ns3::Ipv4GlobalRouting::RespondToInterfaceEvents", BooleanValue (false)); + // Allow the user to override any of the defaults and the above // Bind ()s at run-time, via command-line arguments CommandLine cmd; @@ -206,9 +200,7 @@ uint32_t ipv4ifIndex1 = 2; Simulator::Schedule (Seconds (2),&Ipv4::SetDown,ipv41, ipv4ifIndex1); - Simulator::Schedule (Seconds (3),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); Simulator::Schedule (Seconds (4),&Ipv4::SetUp,ipv41, ipv4ifIndex1); - Simulator::Schedule (Seconds (5),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); Ptr n6 = c.Get (6); Ptr ipv46 = n6->GetObject (); @@ -216,14 +208,10 @@ // then the next p2p is numbered 2 uint32_t ipv4ifIndex6 = 2; Simulator::Schedule (Seconds (6),&Ipv4::SetDown,ipv46, ipv4ifIndex6); - Simulator::Schedule (Seconds (7),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); Simulator::Schedule (Seconds (8),&Ipv4::SetUp,ipv46, ipv4ifIndex6); - Simulator::Schedule (Seconds (9),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); Simulator::Schedule (Seconds (12),&Ipv4::SetDown,ipv41, ipv4ifIndex1); - Simulator::Schedule (Seconds (13),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); Simulator::Schedule (Seconds (14),&Ipv4::SetUp,ipv41, ipv4ifIndex1); - Simulator::Schedule (Seconds (15),&Ipv4GlobalRoutingHelper::RecomputeRoutingTables); NS_LOG_INFO ("Run Simulation."); Simulator::Run (); diff -r b2b5d61f5946 -r d9990845c9ff src/routing/global-routing/global-routing.h --- a/src/routing/global-routing/global-routing.h Tue May 11 08:56:28 2010 +0100 +++ b/src/routing/global-routing/global-routing.h Wed May 12 11:56:50 2010 -0700 @@ -33,22 +33,28 @@ * The model assumes that all nodes on an ns-3 channel are reachable to * one another, regardless of whether the nodes can use the channel * successfully (in the case of wireless). Therefore, this model - * should typically be used only on wired topologies. API does not - * yet exist to control the subset of a topology to which this global - * static routing is applied. + * should typically be used only on wired topologies. Layer-2 bridge + * devices are supported. API does not yet exist to control the subset + * of a topology to which this global static routing is applied. * - * This model also does not yet deal with the possible presence of - * layer-2 relays such as switches, bridges, and hubs, although ns-3 does - * not have such devices yet. + * If the topology changes during the simulation, by default, routing + * will not adjust. There are two ways to make it adjust. + * - Set the attribute Ipv4GlobalRouting::RespondToInterfaceEvents to true + * - Manually call the sequence of GlobalRouteManager methods to delte global + * routes, build global routing database, and initialize routes. + * There is a helper method that encapsulates this + * (Ipv4GlobalRoutingHelper::RecomputeRoutingTables()) * * \section api API and Usage * * Users must include ns3/global-route-manager.h header file. After the * IPv4 topology has been built and addresses assigned, users call * ns3::GlobalRouteManager::PopulateRoutingTables (), prior to the - * ns3::Simulator::Run() call. There are no other attributes or - * public methods that are typically called, or ways to parameterize - * the behavior. + * ns3::Simulator::Run() call. + * + * There are two attributes of Ipv4GlobalRouting that govern behavior. + * - Ipv4GlobalRouting::RandomEcmpRouting + * - Ipv4GlobalRouting::RespondToInterfaceEvents * * \section impl Implementation * diff -r b2b5d61f5946 -r d9990845c9ff src/routing/global-routing/ipv4-global-routing.cc --- a/src/routing/global-routing/ipv4-global-routing.cc Tue May 11 08:56:28 2010 +0100 +++ b/src/routing/global-routing/ipv4-global-routing.cc Wed May 12 11:56:50 2010 -0700 @@ -17,6 +17,7 @@ // #include "ns3/log.h" +#include "ns3/simulator.h" #include "ns3/object.h" #include "ns3/packet.h" #include "ns3/net-device.h" @@ -24,6 +25,7 @@ #include "ns3/ipv4-routing-table-entry.h" #include "ns3/boolean.h" #include "ipv4-global-routing.h" +#include "global-route-manager.h" #include NS_LOG_COMPONENT_DEFINE ("Ipv4GlobalRouting"); @@ -42,12 +44,18 @@ BooleanValue(false), MakeBooleanAccessor (&Ipv4GlobalRouting::m_randomEcmpRouting), MakeBooleanChecker ()) + .AddAttribute ("RespondToInterfaceEvents", + "Set to true if you want to dynamically recompute the global routes upon Interface notification events (up/down, or add/remove address)", + BooleanValue(false), + MakeBooleanAccessor (&Ipv4GlobalRouting::m_respondToInterfaceEvents), + MakeBooleanChecker ()) ; return tid; } Ipv4GlobalRouting::Ipv4GlobalRouting () -: m_randomEcmpRouting (false) +: m_randomEcmpRouting (false), + m_respondToInterfaceEvents (false) { NS_LOG_FUNCTION_NOARGS (); } @@ -486,16 +494,52 @@ } void Ipv4GlobalRouting::NotifyInterfaceUp (uint32_t i) -{} +{ + NS_LOG_FUNCTION (this << i); + if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events + { + GlobalRouteManager::DeleteGlobalRoutes (); + GlobalRouteManager::BuildGlobalRoutingDatabase (); + GlobalRouteManager::InitializeRoutes (); + } +} + void Ipv4GlobalRouting::NotifyInterfaceDown (uint32_t i) -{} +{ + NS_LOG_FUNCTION (this << i); + if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events + { + GlobalRouteManager::DeleteGlobalRoutes (); + GlobalRouteManager::BuildGlobalRoutingDatabase (); + GlobalRouteManager::InitializeRoutes (); + } +} + void Ipv4GlobalRouting::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address) -{} +{ + NS_LOG_FUNCTION (this << interface << address); + if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events + { + GlobalRouteManager::DeleteGlobalRoutes (); + GlobalRouteManager::BuildGlobalRoutingDatabase (); + GlobalRouteManager::InitializeRoutes (); + } +} + void Ipv4GlobalRouting::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address) -{} +{ + NS_LOG_FUNCTION (this << interface << address); + if (m_respondToInterfaceEvents && Simulator::Now ().GetSeconds () > 0) // avoid startup events + { + GlobalRouteManager::DeleteGlobalRoutes (); + GlobalRouteManager::BuildGlobalRoutingDatabase (); + GlobalRouteManager::InitializeRoutes (); + } +} + void Ipv4GlobalRouting::SetIpv4 (Ptr ipv4) { diff -r b2b5d61f5946 -r d9990845c9ff src/routing/global-routing/ipv4-global-routing.h --- a/src/routing/global-routing/ipv4-global-routing.h Tue May 11 08:56:28 2010 +0100 +++ b/src/routing/global-routing/ipv4-global-routing.h Wed May 12 11:56:50 2010 -0700 @@ -81,6 +81,7 @@ Ipv4GlobalRouting (); virtual ~Ipv4GlobalRouting (); + // These methods inherited from base class virtual Ptr RouteOutput (Ptr p, const Ipv4Header &header, Ptr oif, Socket::SocketErrno &sockerr); virtual bool RouteInput (Ptr p, const Ipv4Header &header, Ptr idev, @@ -215,6 +216,8 @@ private: /// Set to true if packets are randomly routed among ECMP; set to false for using only one route consistently bool m_randomEcmpRouting; + /// Set to true if this interface should respond to interface events by globallly recomputing routes + bool m_respondToInterfaceEvents; /// A uniform random number generator for randomly routing packets among ECMP UniformVariable m_rand;