A Discrete-Event Network Simulator
API
rip-simple-network.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Universita' di Firenze, Italy
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
18  */
19 
20 // Network topology
21 //
22 // SRC
23 // |<=== source network
24 // A-----B
25 // \ / \ all networks have cost 1, except
26 // \ / | for the direct link from C to D, which
27 // C / has cost 10
28 // | /
29 // |/
30 // D
31 // |<=== target network
32 // DST
33 //
34 //
35 // A, B, C and D are RIPng routers.
36 // A and D are configured with static addresses.
37 // SRC and DST will exchange packets.
38 //
39 // After about 3 seconds, the topology is built, and Echo Reply will be received.
40 // After 40 seconds, the link between B and D will break, causing a route failure.
41 // After 44 seconds from the failure, the routers will recovery from the failure.
42 // Split Horizoning should affect the recovery time, but it is not. See the manual
43 // for an explanation of this effect.
44 //
45 // If "showPings" is enabled, the user will see:
46 // 1) if the ping has been acknowledged
47 // 2) if a Destination Unreachable has been received by the sender
48 // 3) nothing, when the Echo Request has been received by the destination but
49 // the Echo Reply is unable to reach the sender.
50 // Examining the .pcap files with Wireshark can confirm this effect.
51 
52 #include "ns3/core-module.h"
53 #include "ns3/csma-module.h"
54 #include "ns3/internet-apps-module.h"
55 #include "ns3/internet-module.h"
56 #include "ns3/ipv4-routing-table-entry.h"
57 #include "ns3/ipv4-static-routing-helper.h"
58 
59 #include <fstream>
60 
61 using namespace ns3;
62 
63 NS_LOG_COMPONENT_DEFINE("RipSimpleRouting");
64 
65 void
66 TearDownLink(Ptr<Node> nodeA, Ptr<Node> nodeB, uint32_t interfaceA, uint32_t interfaceB)
67 {
68  nodeA->GetObject<Ipv4>()->SetDown(interfaceA);
69  nodeB->GetObject<Ipv4>()->SetDown(interfaceB);
70 }
71 
72 int
73 main(int argc, char** argv)
74 {
75  bool verbose = false;
76  bool printRoutingTables = false;
77  bool showPings = false;
78  std::string SplitHorizon("PoisonReverse");
79 
80  CommandLine cmd(__FILE__);
81  cmd.AddValue("verbose", "turn on log components", verbose);
82  cmd.AddValue("printRoutingTables",
83  "Print routing tables at 30, 60 and 90 seconds",
84  printRoutingTables);
85  cmd.AddValue("showPings", "Show Ping6 reception", showPings);
86  cmd.AddValue("splitHorizonStrategy",
87  "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)",
88  SplitHorizon);
89  cmd.Parse(argc, argv);
90 
91  if (verbose)
92  {
94  LogComponentEnable("RipSimpleRouting", LOG_LEVEL_INFO);
96  LogComponentEnable("Ipv4Interface", LOG_LEVEL_ALL);
97  LogComponentEnable("Icmpv4L4Protocol", LOG_LEVEL_ALL);
98  LogComponentEnable("Ipv4L3Protocol", LOG_LEVEL_ALL);
99  LogComponentEnable("ArpCache", LOG_LEVEL_ALL);
101  }
102 
103  if (SplitHorizon == "NoSplitHorizon")
104  {
105  Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::NO_SPLIT_HORIZON));
106  }
107  else if (SplitHorizon == "SplitHorizon")
108  {
109  Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::SPLIT_HORIZON));
110  }
111  else
112  {
113  Config::SetDefault("ns3::Rip::SplitHorizon", EnumValue(RipNg::POISON_REVERSE));
114  }
115 
116  NS_LOG_INFO("Create nodes.");
117  Ptr<Node> src = CreateObject<Node>();
118  Names::Add("SrcNode", src);
119  Ptr<Node> dst = CreateObject<Node>();
120  Names::Add("DstNode", dst);
121  Ptr<Node> a = CreateObject<Node>();
122  Names::Add("RouterA", a);
123  Ptr<Node> b = CreateObject<Node>();
124  Names::Add("RouterB", b);
125  Ptr<Node> c = CreateObject<Node>();
126  Names::Add("RouterC", c);
127  Ptr<Node> d = CreateObject<Node>();
128  Names::Add("RouterD", d);
129  NodeContainer net1(src, a);
130  NodeContainer net2(a, b);
131  NodeContainer net3(a, c);
132  NodeContainer net4(b, c);
133  NodeContainer net5(c, d);
134  NodeContainer net6(b, d);
135  NodeContainer net7(d, dst);
136  NodeContainer routers(a, b, c, d);
137  NodeContainer nodes(src, dst);
138 
139  NS_LOG_INFO("Create channels.");
141  csma.SetChannelAttribute("DataRate", DataRateValue(5000000));
142  csma.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
143  NetDeviceContainer ndc1 = csma.Install(net1);
144  NetDeviceContainer ndc2 = csma.Install(net2);
145  NetDeviceContainer ndc3 = csma.Install(net3);
146  NetDeviceContainer ndc4 = csma.Install(net4);
147  NetDeviceContainer ndc5 = csma.Install(net5);
148  NetDeviceContainer ndc6 = csma.Install(net6);
149  NetDeviceContainer ndc7 = csma.Install(net7);
150 
151  NS_LOG_INFO("Create IPv4 and routing");
152  RipHelper ripRouting;
153 
154  // Rule of thumb:
155  // Interfaces are added sequentially, starting from 0
156  // However, interface 0 is always the loopback...
157  ripRouting.ExcludeInterface(a, 1);
158  ripRouting.ExcludeInterface(d, 3);
159 
160  ripRouting.SetInterfaceMetric(c, 3, 10);
161  ripRouting.SetInterfaceMetric(d, 1, 10);
162 
163  Ipv4ListRoutingHelper listRH;
164  listRH.Add(ripRouting, 0);
165  // Ipv4StaticRoutingHelper staticRh;
166  // listRH.Add (staticRh, 5);
167 
169  internet.SetIpv6StackInstall(false);
170  internet.SetRoutingHelper(listRH);
171  internet.Install(routers);
172 
173  InternetStackHelper internetNodes;
174  internetNodes.SetIpv6StackInstall(false);
175  internetNodes.Install(nodes);
176 
177  // Assign addresses.
178  // The source and destination networks have global addresses
179  // The "core" network just needs link-local addresses for routing.
180  // We assign global addresses to the routers as well to receive
181  // ICMPv6 errors.
182  NS_LOG_INFO("Assign IPv4 Addresses.");
184 
185  ipv4.SetBase(Ipv4Address("10.0.0.0"), Ipv4Mask("255.255.255.0"));
186  Ipv4InterfaceContainer iic1 = ipv4.Assign(ndc1);
187 
188  ipv4.SetBase(Ipv4Address("10.0.1.0"), Ipv4Mask("255.255.255.0"));
189  Ipv4InterfaceContainer iic2 = ipv4.Assign(ndc2);
190 
191  ipv4.SetBase(Ipv4Address("10.0.2.0"), Ipv4Mask("255.255.255.0"));
192  Ipv4InterfaceContainer iic3 = ipv4.Assign(ndc3);
193 
194  ipv4.SetBase(Ipv4Address("10.0.3.0"), Ipv4Mask("255.255.255.0"));
195  Ipv4InterfaceContainer iic4 = ipv4.Assign(ndc4);
196 
197  ipv4.SetBase(Ipv4Address("10.0.4.0"), Ipv4Mask("255.255.255.0"));
198  Ipv4InterfaceContainer iic5 = ipv4.Assign(ndc5);
199 
200  ipv4.SetBase(Ipv4Address("10.0.5.0"), Ipv4Mask("255.255.255.0"));
201  Ipv4InterfaceContainer iic6 = ipv4.Assign(ndc6);
202 
203  ipv4.SetBase(Ipv4Address("10.0.6.0"), Ipv4Mask("255.255.255.0"));
204  Ipv4InterfaceContainer iic7 = ipv4.Assign(ndc7);
205 
206  Ptr<Ipv4StaticRouting> staticRouting;
207  staticRouting = Ipv4RoutingHelper::GetRouting<Ipv4StaticRouting>(
208  src->GetObject<Ipv4>()->GetRoutingProtocol());
209  staticRouting->SetDefaultRoute("10.0.0.2", 1);
210  staticRouting = Ipv4RoutingHelper::GetRouting<Ipv4StaticRouting>(
211  dst->GetObject<Ipv4>()->GetRoutingProtocol());
212  staticRouting->SetDefaultRoute("10.0.6.1", 1);
213 
214  if (printRoutingTables)
215  {
216  Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>(&std::cout);
217 
218  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(30.0), a, routingStream);
219  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(30.0), b, routingStream);
220  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(30.0), c, routingStream);
221  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(30.0), d, routingStream);
222 
223  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(60.0), a, routingStream);
224  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(60.0), b, routingStream);
225  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(60.0), c, routingStream);
226  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(60.0), d, routingStream);
227 
228  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(90.0), a, routingStream);
229  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(90.0), b, routingStream);
230  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(90.0), c, routingStream);
231  Ipv4RoutingHelper::PrintRoutingTableAt(Seconds(90.0), d, routingStream);
232  }
233 
234  NS_LOG_INFO("Create Applications.");
235  uint32_t packetSize = 1024;
236  Time interPacketInterval = Seconds(1.0);
237  PingHelper ping(Ipv4Address("10.0.6.2"));
238 
239  ping.SetAttribute("Interval", TimeValue(interPacketInterval));
240  ping.SetAttribute("Size", UintegerValue(packetSize));
241  if (showPings)
242  {
243  ping.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE));
244  }
245  ApplicationContainer apps = ping.Install(src);
246  apps.Start(Seconds(1.0));
247  apps.Stop(Seconds(110.0));
248 
249  AsciiTraceHelper ascii;
250  csma.EnableAsciiAll(ascii.CreateFileStream("rip-simple-routing.tr"));
251  csma.EnablePcapAll("rip-simple-routing", true);
252 
253  Simulator::Schedule(Seconds(40), &TearDownLink, b, d, 3, 2);
254 
255  /* Now, do the actual simulation. */
256  NS_LOG_INFO("Run Simulation.");
257  Simulator::Stop(Seconds(131.0));
258  Simulator::Run();
260  NS_LOG_INFO("Done.");
261 
262  return 0;
263 }
holds a vector of ns3::Application pointers.
void Start(Time start) const
Start all of the Applications in this container at the start time given as a parameter.
void Stop(Time stop) const
Arrange for all of the Applications in this container to Stop() at the Time given as a parameter.
Manage ASCII trace files for device models.
Definition: trace-helper.h:174
Ptr< OutputStreamWrapper > CreateFileStream(std::string filename, std::ios::openmode filemode=std::ios::out)
Create and initialize an output stream object we'll use to write the traced bits.
Parse command-line arguments.
Definition: command-line.h:232
build a set of CsmaNetDevice objects
Definition: csma-helper.h:48
Hold variables of type enum.
Definition: enum.h:62
aggregate IP/TCP/UDP functionality to existing Nodes.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
void SetIpv6StackInstall(bool enable)
Enable/disable IPv6 stack install.
A helper class to make life easier while doing simple IPv4 address assignment in scripts.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:42
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:80
virtual Ptr< Ipv4RoutingProtocol > GetRoutingProtocol() const =0
Get the routing protocol to be used by this Ipv4 stack.
holds a vector of std::pair of Ptr<Ipv4> and interface index.
Helper class that adds ns3::Ipv4ListRouting objects.
void Add(const Ipv4RoutingHelper &routing, int16_t priority)
a class to represent an Ipv4 address mask
Definition: ipv4-address.h:257
static void PrintRoutingTableAt(Time printTime, Ptr< Node > node, Ptr< OutputStreamWrapper > stream, Time::Unit unit=Time::S)
prints the routing tables of a node at a particular time.
static void Add(std::string name, Ptr< Object > object)
Add the association between the string "name" and the Ptr<Object> obj.
Definition: names.cc:775
holds a vector of ns3::NetDevice pointers
keep track of a set of node pointers.
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
Create a ping application and associate it to a node.
Definition: ping-helper.h:48
Helper class that adds RIP routing to nodes.
Definition: rip-helper.h:42
void ExcludeInterface(Ptr< Node > node, uint32_t interface)
Exclude an interface from RIP protocol.
Definition: rip-helper.cc:159
void SetInterfaceMetric(Ptr< Node > node, uint32_t interface, uint8_t metric)
Set a metric for an interface.
Definition: rip-helper.cc:177
@ SPLIT_HORIZON
Split Horizon.
Definition: ripng.h:226
@ POISON_REVERSE
Poison Reverse Split Horizon.
Definition: ripng.h:227
@ NO_SPLIT_HORIZON
No Split Horizon.
Definition: ripng.h:225
static EventId Schedule(const Time &delay, FUNC f, Ts &&... args)
Schedule an event to expire after delay.
Definition: simulator.h:571
static void Destroy()
Execute the events scheduled with ScheduleDestroy().
Definition: simulator.cc:142
static void Run()
Run the simulation.
Definition: simulator.cc:178
static void Stop()
Tell the Simulator the calling event should be the last one executed.
Definition: simulator.cc:186
Simulation virtual time values and global simulation resolution.
Definition: nstime.h:105
Hold an unsigned integer type.
Definition: uinteger.h:45
void SetDefault(std::string name, const AttributeValue &value)
Definition: config.cc:890
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_INFO(msg)
Use NS_LOG to output a message of level LOG_INFO.
Definition: log.h:275
Time Seconds(double value)
Construct a Time in the indicated unit.
Definition: nstime.h:1326
Time MilliSeconds(uint64_t value)
Construct a Time in the indicated unit.
Definition: nstime.h:1338
NodeContainer nodes
Every class exported by the ns3 library is enclosed in the ns3 namespace.
void LogComponentEnable(const std::string &name, LogLevel level)
Enable the logging output associated with that log component.
Definition: log.cc:302
LogLevel
Logging severity classes and levels.
Definition: log.h:94
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
@ LOG_PREFIX_TIME
Prefix all trace prints with simulation time.
Definition: log.h:119
@ LOG_PREFIX_NODE
Prefix all trace prints with simulation node.
Definition: log.h:120
@ LOG_LEVEL_INFO
LOG_INFO and above.
Definition: log.h:104
void LogComponentEnableAll(LogLevel level)
Enable the logging output for all registered log components.
Definition: log.cc:320
csma
Definition: second.py:63
cmd
Definition: second.py:40
bool verbose
void TearDownLink(Ptr< Node > nodeA, Ptr< Node > nodeB, uint32_t interfaceA, uint32_t interfaceB)
static const uint32_t packetSize
Packet size generated at the AP.