diff --git a/CHANGES.html b/CHANGES.html
index c2bc57afb..7f5510c69 100644
--- a/CHANGES.html
+++ b/CHANGES.html
@@ -62,6 +62,10 @@ the user to specify a list of received packets that should be errored. The
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
+
Respond to interface events:" New attribute for Ipv4GlobalRouting,
+"RespondToInterfaceEvents", which when enabled, will cause global routes
+to be recomputed upon any interface or address notification event from IPv4.
+
Changes to existing API:
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index a6c1b3945..59720faec 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -40,6 +40,7 @@ many cases referencing the Bugzilla bug number
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
------------
diff --git a/doc/manual/routing.texi b/doc/manual/routing.texi
index 0888af350..116449544 100644
--- a/doc/manual/routing.texi
+++ b/doc/manual/routing.texi
@@ -147,6 +147,16 @@ at time 5 seconds:
&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 --git a/examples/routing/dynamic-global-routing.cc b/examples/routing/dynamic-global-routing.cc
index 2c1648fc7..e1a7f4db5 100644
--- a/examples/routing/dynamic-global-routing.cc
+++ b/examples/routing/dynamic-global-routing.cc
@@ -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 @@ NS_LOG_COMPONENT_DEFINE ("DynamicGlobalRoutingExample");
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 @@ main (int argc, char *argv[])
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 @@ main (int argc, char *argv[])
// 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 --git a/src/routing/global-routing/global-routing.h b/src/routing/global-routing/global-routing.h
index ad9851505..7cfc37273 100644
--- a/src/routing/global-routing/global-routing.h
+++ b/src/routing/global-routing/global-routing.h
@@ -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 --git a/src/routing/global-routing/ipv4-global-routing.cc b/src/routing/global-routing/ipv4-global-routing.cc
index 7d2f2b021..e5e88760b 100644
--- a/src/routing/global-routing/ipv4-global-routing.cc
+++ b/src/routing/global-routing/ipv4-global-routing.cc
@@ -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 @@ Ipv4GlobalRouting::GetTypeId (void)
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 @@ Ipv4GlobalRouting::RouteInput (Ptr p, const Ipv4Header &header, P
}
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 --git a/src/routing/global-routing/ipv4-global-routing.h b/src/routing/global-routing/ipv4-global-routing.h
index 2f088b062..64c573909 100644
--- a/src/routing/global-routing/ipv4-global-routing.h
+++ b/src/routing/global-routing/ipv4-global-routing.h
@@ -81,6 +81,7 @@ public:
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 @@ protected:
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;