bug 702: make global routing robust to link/device events
authorTom Henderson <tomh@tomh.org>
Mon, 24 May 2010 10:52:58 -0700
changeset 6317 e4a750adf12c
parent 6316 8c151e05a19f
child 6318 a1e00acc5986
bug 702: make global routing robust to link/device events
CHANGES.html
RELEASE_NOTES
doc/manual/routing.texi
examples/routing/dynamic-global-routing.cc
src/routing/global-routing/global-routing.h
src/routing/global-routing/ipv4-global-routing.cc
src/routing/global-routing/ipv4-global-routing.h
--- a/CHANGES.html	Mon May 24 08:08:25 2010 -0700
+++ b/CHANGES.html	Mon May 24 10:52:58 2010 -0700
@@ -62,6 +62,10 @@
 list corresponds not to the packet UID but to the sequence of received
 packets as observed by the error model.   See src/common/error-model.h
 </ul>
+<ul><b>Respond to interface events:"</b> New attribute for Ipv4GlobalRouting,
+"RespondToInterfaceEvents", which when enabled, will cause global routes
+to be recomputed upon any interface or address notification event from IPv4.
+</ul>
 
 <h2>Changes to existing API:</h2>
 
--- a/RELEASE_NOTES	Mon May 24 08:08:25 2010 -0700
+++ b/RELEASE_NOTES	Mon May 24 10:52:58 2010 -0700
@@ -40,6 +40,7 @@
                in IPv4 or IPv6 ascii traces
    - ICMPv4 objects not properly registered; affected serialization code
    - bug 875 - Set FCS included flag in Radiotap header
+   - bug 702 - Global routing doesn't respond to interface events
 
 Known issues
 ------------
--- a/doc/manual/routing.texi	Mon May 24 08:08:25 2010 -0700
+++ b/doc/manual/routing.texi	Mon May 24 10:52:58 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.
--- a/examples/routing/dynamic-global-routing.cc	Mon May 24 08:08:25 2010 -0700
+++ b/examples/routing/dynamic-global-routing.cc	Mon May 24 10:52:58 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 (true));
+
   // 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<Node> n6 = c.Get (6);
   Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4> ();
@@ -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 ();
--- a/src/routing/global-routing/global-routing.h	Mon May 24 08:08:25 2010 -0700
+++ b/src/routing/global-routing/global-routing.h	Mon May 24 10:52:58 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
  *
--- a/src/routing/global-routing/ipv4-global-routing.cc	Mon May 24 08:08:25 2010 -0700
+++ b/src/routing/global-routing/ipv4-global-routing.cc	Mon May 24 10:52:58 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 <vector>
 
 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 ();
 }
@@ -485,16 +493,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> ipv4)
 {
--- a/src/routing/global-routing/ipv4-global-routing.h	Mon May 24 08:08:25 2010 -0700
+++ b/src/routing/global-routing/ipv4-global-routing.h	Mon May 24 10:52:58 2010 -0700
@@ -81,6 +81,7 @@
   Ipv4GlobalRouting ();
   virtual ~Ipv4GlobalRouting ();
 
+  // These methods inherited from base class
   virtual Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr);
 
   virtual bool RouteInput  (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> 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;