bug 702: make global routing robust to link/device events

This commit is contained in:
Tom Henderson
2010-05-24 10:52:58 -07:00
parent a6a2797a69
commit d5624122d1
7 changed files with 96 additions and 40 deletions

View File

@@ -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
</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>

View File

@@ -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
------------

View File

@@ -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.

View File

@@ -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<Node> n6 = c.Get (6);
Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4> ();
@@ -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 ();

View File

@@ -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
*

View File

@@ -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 @@ 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<const Packet> 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> ipv4)
{

View File

@@ -81,6 +81,7 @@ public:
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 @@ 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;