Files
unison/examples/mtp/dynamic-global-routing-mtp.cc

226 lines
8.7 KiB
C++

/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contributed by: Luis Cortes (cortes@gatech.edu)
*/
// This script exercises global routing code in a mixed point-to-point
// 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
//
// n0
// \ p-p
// \ (shared csma/cd)
// n2 -------------------------n3
// / | |
// / p-p n4 n5 ---------- n6
// n1 p-p
// | |
// ----------------------------------------
// p-p
//
// - at time 1 CBR/UDP flow from n1 to n6's IP address on the n5/n6 link
// - at time 10, start similar flow from n1 to n6's address on the n1/n6 link
//
// Order of events
// At pre-simulation time, configure global routes. Shortest path from
// 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 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). 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 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 16s, stop the second flow.
// - Tracing of queues and packet receptions to file "dynamic-global-routing.tr"
#include "ns3/applications-module.h"
#include "ns3/core-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include "ns3/mtp-module.h"
#include "ns3/network-module.h"
#include "ns3/point-to-point-module.h"
#include <cassert>
#include <fstream>
#include <iostream>
#include <string>
using namespace ns3;
NS_LOG_COMPONENT_DEFINE("DynamicGlobalRoutingExample");
int
main(int argc, char* argv[])
{
MtpInterface::Enable();
// 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(__FILE__);
cmd.Parse(argc, argv);
NS_LOG_INFO("Create nodes.");
NodeContainer c;
c.Create(7);
NodeContainer n0n2 = NodeContainer(c.Get(0), c.Get(2));
NodeContainer n1n2 = NodeContainer(c.Get(1), c.Get(2));
NodeContainer n5n6 = NodeContainer(c.Get(5), c.Get(6));
NodeContainer n1n6 = NodeContainer(c.Get(1), c.Get(6));
NodeContainer n2345 = NodeContainer(c.Get(2), c.Get(3), c.Get(4), c.Get(5));
InternetStackHelper internet;
internet.Install(c);
// We create the channels first without any IP addressing information
NS_LOG_INFO("Create channels.");
PointToPointHelper p2p;
p2p.SetDeviceAttribute("DataRate", StringValue("5Mbps"));
p2p.SetChannelAttribute("Delay", StringValue("2ms"));
NetDeviceContainer d0d2 = p2p.Install(n0n2);
NetDeviceContainer d1d6 = p2p.Install(n1n6);
NetDeviceContainer d1d2 = p2p.Install(n1n2);
p2p.SetDeviceAttribute("DataRate", StringValue("1500kbps"));
p2p.SetChannelAttribute("Delay", StringValue("10ms"));
NetDeviceContainer d5d6 = p2p.Install(n5n6);
// We create the channels first without any IP addressing information
CsmaHelper csma;
csma.SetChannelAttribute("DataRate", StringValue("5Mbps"));
csma.SetChannelAttribute("Delay", StringValue("2ms"));
NetDeviceContainer d2345 = csma.Install(n2345);
// Later, we add IP addresses.
NS_LOG_INFO("Assign IP Addresses.");
Ipv4AddressHelper ipv4;
ipv4.SetBase("10.1.1.0", "255.255.255.0");
ipv4.Assign(d0d2);
ipv4.SetBase("10.1.2.0", "255.255.255.0");
ipv4.Assign(d1d2);
ipv4.SetBase("10.1.3.0", "255.255.255.0");
Ipv4InterfaceContainer i5i6 = ipv4.Assign(d5d6);
ipv4.SetBase("10.250.1.0", "255.255.255.0");
ipv4.Assign(d2345);
ipv4.SetBase("172.16.1.0", "255.255.255.0");
Ipv4InterfaceContainer i1i6 = ipv4.Assign(d1d6);
// Create router nodes, initialize routing database and set up the routing
// tables in the nodes.
Ipv4GlobalRoutingHelper::PopulateRoutingTables();
// Create the OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
NS_LOG_INFO("Create Applications.");
uint16_t port = 9; // Discard port (RFC 863)
OnOffHelper onoff("ns3::UdpSocketFactory", InetSocketAddress(i5i6.GetAddress(1), port));
onoff.SetConstantRate(DataRate("2kbps"));
onoff.SetAttribute("PacketSize", UintegerValue(50));
ApplicationContainer apps = onoff.Install(c.Get(1));
apps.Start(Seconds(1.0));
apps.Stop(Seconds(10.0));
// Create a second OnOff application to send UDP datagrams of size
// 210 bytes at a rate of 448 Kb/s
OnOffHelper onoff2("ns3::UdpSocketFactory", InetSocketAddress(i1i6.GetAddress(1), port));
onoff2.SetAttribute("OnTime", StringValue("ns3::ConstantRandomVariable[Constant=1]"));
onoff2.SetAttribute("OffTime", StringValue("ns3::ConstantRandomVariable[Constant=0]"));
onoff2.SetAttribute("DataRate", StringValue("2kbps"));
onoff2.SetAttribute("PacketSize", UintegerValue(50));
ApplicationContainer apps2 = onoff2.Install(c.Get(1));
apps2.Start(Seconds(11.0));
apps2.Stop(Seconds(16.0));
// Create an optional packet sink to receive these packets
PacketSinkHelper sink("ns3::UdpSocketFactory",
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
apps = sink.Install(c.Get(6));
apps.Start(Seconds(1.0));
apps.Stop(Seconds(10.0));
PacketSinkHelper sink2("ns3::UdpSocketFactory",
Address(InetSocketAddress(Ipv4Address::GetAny(), port)));
apps2 = sink2.Install(c.Get(6));
apps2.Start(Seconds(11.0));
apps2.Stop(Seconds(16.0));
AsciiTraceHelper ascii;
Ptr<OutputStreamWrapper> stream = ascii.CreateFileStream("dynamic-global-routing.tr");
p2p.EnableAsciiAll(stream);
csma.EnableAsciiAll(stream);
internet.EnableAsciiIpv4All(stream);
p2p.EnablePcapAll("dynamic-global-routing");
csma.EnablePcapAll("dynamic-global-routing", false);
Ptr<Node> n1 = c.Get(1);
Ptr<Ipv4> ipv41 = n1->GetObject<Ipv4>();
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
// then the next p2p is numbered 2
uint32_t ipv4ifIndex1 = 2;
Simulator::Schedule(Seconds(2), &Ipv4::SetDown, ipv41, ipv4ifIndex1);
Simulator::Schedule(Seconds(4), &Ipv4::SetUp, ipv41, ipv4ifIndex1);
Ptr<Node> n6 = c.Get(6);
Ptr<Ipv4> ipv46 = n6->GetObject<Ipv4>();
// The first ifIndex is 0 for loopback, then the first p2p is numbered 1,
// then the next p2p is numbered 2
uint32_t ipv4ifIndex6 = 2;
Simulator::Schedule(Seconds(6), &Ipv4::SetDown, ipv46, ipv4ifIndex6);
Simulator::Schedule(Seconds(8), &Ipv4::SetUp, ipv46, ipv4ifIndex6);
Simulator::Schedule(Seconds(12), &Ipv4::SetDown, ipv41, ipv4ifIndex1);
Simulator::Schedule(Seconds(14), &Ipv4::SetUp, ipv41, ipv4ifIndex1);
// Trace routing tables
Ptr<OutputStreamWrapper> routingStream =
Create<OutputStreamWrapper>("dynamic-global-routing.routes", std::ios::out);
Ipv4RoutingHelper::PrintRoutingTableAllAt(Seconds(12), routingStream);
NS_LOG_INFO("Run Simulation.");
Simulator::Run();
Simulator::Destroy();
NS_LOG_INFO("Done.");
return 0;
}