A Discrete-Event Network Simulator
API
ripng-simple-network.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 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/ipv6-routing-table-entry.h"
57 #include "ns3/ipv6-static-routing-helper.h"
58 
59 #include <fstream>
60 
61 using namespace ns3;
62 
63 NS_LOG_COMPONENT_DEFINE("RipNgSimpleRouting");
64 
65 void
66 TearDownLink(Ptr<Node> nodeA, Ptr<Node> nodeB, uint32_t interfaceA, uint32_t interfaceB)
67 {
68  nodeA->GetObject<Ipv6>()->SetDown(interfaceA);
69  nodeB->GetObject<Ipv6>()->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  {
93  LogComponentEnable("RipNgSimpleRouting", LOG_LEVEL_INFO);
95  LogComponentEnable("Icmpv6L4Protocol", LOG_LEVEL_INFO);
96  LogComponentEnable("Ipv6Interface", LOG_LEVEL_ALL);
97  LogComponentEnable("Icmpv6L4Protocol", LOG_LEVEL_ALL);
98  LogComponentEnable("NdiscCache", LOG_LEVEL_ALL);
100  }
101 
102  if (SplitHorizon == "NoSplitHorizon")
103  {
104  Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::NO_SPLIT_HORIZON));
105  }
106  else if (SplitHorizon == "SplitHorizon")
107  {
108  Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::SPLIT_HORIZON));
109  }
110  else
111  {
112  Config::SetDefault("ns3::RipNg::SplitHorizon", EnumValue(RipNg::POISON_REVERSE));
113  }
114 
115  NS_LOG_INFO("Create nodes.");
116  Ptr<Node> src = CreateObject<Node>();
117  Names::Add("SrcNode", src);
118  Ptr<Node> dst = CreateObject<Node>();
119  Names::Add("DstNode", dst);
120  Ptr<Node> a = CreateObject<Node>();
121  Names::Add("RouterA", a);
122  Ptr<Node> b = CreateObject<Node>();
123  Names::Add("RouterB", b);
124  Ptr<Node> c = CreateObject<Node>();
125  Names::Add("RouterC", c);
126  Ptr<Node> d = CreateObject<Node>();
127  Names::Add("RouterD", d);
128  NodeContainer net1(src, a);
129  NodeContainer net2(a, b);
130  NodeContainer net3(a, c);
131  NodeContainer net4(b, c);
132  NodeContainer net5(c, d);
133  NodeContainer net6(b, d);
134  NodeContainer net7(d, dst);
135  NodeContainer routers(a, b, c, d);
136  NodeContainer nodes(src, dst);
137 
138  NS_LOG_INFO("Create channels.");
140  csma.SetChannelAttribute("DataRate", DataRateValue(5000000));
141  csma.SetChannelAttribute("Delay", TimeValue(MilliSeconds(2)));
142  NetDeviceContainer ndc1 = csma.Install(net1);
143  NetDeviceContainer ndc2 = csma.Install(net2);
144  NetDeviceContainer ndc3 = csma.Install(net3);
145  NetDeviceContainer ndc4 = csma.Install(net4);
146  NetDeviceContainer ndc5 = csma.Install(net5);
147  NetDeviceContainer ndc6 = csma.Install(net6);
148  NetDeviceContainer ndc7 = csma.Install(net7);
149 
150  NS_LOG_INFO("Create IPv6 and routing");
151  RipNgHelper ripNgRouting;
152 
153  // Rule of thumb:
154  // Interfaces are added sequentially, starting from 0
155  // However, interface 0 is always the loopback...
156  ripNgRouting.ExcludeInterface(a, 1);
157  ripNgRouting.ExcludeInterface(d, 3);
158 
159  ripNgRouting.SetInterfaceMetric(c, 3, 10);
160  ripNgRouting.SetInterfaceMetric(d, 1, 10);
161 
162  Ipv6ListRoutingHelper listRH;
163  listRH.Add(ripNgRouting, 0);
164  Ipv6StaticRoutingHelper staticRh;
165  listRH.Add(staticRh, 5);
166 
167  InternetStackHelper internetv6;
168  internetv6.SetIpv4StackInstall(false);
169  internetv6.SetRoutingHelper(listRH);
170  internetv6.Install(routers);
171 
172  InternetStackHelper internetv6Nodes;
173  internetv6Nodes.SetIpv4StackInstall(false);
174  internetv6Nodes.Install(nodes);
175 
176  // Assign addresses.
177  // The source and destination networks have global addresses
178  // The "core" network just needs link-local addresses for routing.
179  // We assign global addresses to the routers as well to receive
180  // ICMPv6 errors.
181  NS_LOG_INFO("Assign IPv6 Addresses.");
182  Ipv6AddressHelper ipv6;
183 
184  ipv6.SetBase(Ipv6Address("2001:1::"), Ipv6Prefix(64));
185  Ipv6InterfaceContainer iic1 = ipv6.Assign(ndc1);
186  iic1.SetForwarding(1, true);
188 
189  ipv6.SetBase(Ipv6Address("2001:0:1::"), Ipv6Prefix(64));
190  Ipv6InterfaceContainer iic2 = ipv6.Assign(ndc2);
191  iic2.SetForwarding(0, true);
192  iic2.SetForwarding(1, true);
193 
194  ipv6.SetBase(Ipv6Address("2001:0:2::"), Ipv6Prefix(64));
195  Ipv6InterfaceContainer iic3 = ipv6.Assign(ndc3);
196  iic3.SetForwarding(0, true);
197  iic3.SetForwarding(1, true);
198 
199  ipv6.SetBase(Ipv6Address("2001:0:3::"), Ipv6Prefix(64));
200  Ipv6InterfaceContainer iic4 = ipv6.Assign(ndc4);
201  iic4.SetForwarding(0, true);
202  iic4.SetForwarding(1, true);
203 
204  ipv6.SetBase(Ipv6Address("2001:0:4::"), Ipv6Prefix(64));
205  Ipv6InterfaceContainer iic5 = ipv6.Assign(ndc5);
206  iic5.SetForwarding(0, true);
207  iic5.SetForwarding(1, true);
208 
209  ipv6.SetBase(Ipv6Address("2001:0:5::"), Ipv6Prefix(64));
210  Ipv6InterfaceContainer iic6 = ipv6.Assign(ndc6);
211  iic6.SetForwarding(0, true);
212  iic6.SetForwarding(1, true);
213 
214  ipv6.SetBase(Ipv6Address("2001:2::"), Ipv6Prefix(64));
215  Ipv6InterfaceContainer iic7 = ipv6.Assign(ndc7);
216  iic7.SetForwarding(0, true);
218 
219  if (printRoutingTables)
220  {
221  Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper>(&std::cout);
222 
223  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(30.0), a, routingStream);
224  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(30.0), b, routingStream);
225  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(30.0), c, routingStream);
226  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(30.0), d, routingStream);
227 
228  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(60.0), a, routingStream);
229  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(60.0), b, routingStream);
230  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(60.0), c, routingStream);
231  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(60.0), d, routingStream);
232 
233  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(90.0), a, routingStream);
234  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(90.0), b, routingStream);
235  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(90.0), c, routingStream);
236  Ipv6RoutingHelper::PrintRoutingTableAt(Seconds(90.0), d, routingStream);
237  }
238 
239  NS_LOG_INFO("Create Applications.");
240  uint32_t packetSize = 1024;
241  Time interPacketInterval = Seconds(1.0);
242  PingHelper ping(iic7.GetAddress(1, 1));
243 
244  ping.SetAttribute("Interval", TimeValue(interPacketInterval));
245  ping.SetAttribute("Size", UintegerValue(packetSize));
246  if (showPings)
247  {
248  ping.SetAttribute("VerboseMode", EnumValue(Ping::VerboseMode::VERBOSE));
249  }
250  ApplicationContainer apps = ping.Install(src);
251  apps.Start(Seconds(1.0));
252  apps.Stop(Seconds(110.0));
253 
254  AsciiTraceHelper ascii;
255  csma.EnableAsciiAll(ascii.CreateFileStream("ripng-simple-routing.tr"));
256  csma.EnablePcapAll("ripng-simple-routing", true);
257 
258  Simulator::Schedule(Seconds(40), &TearDownLink, b, d, 3, 2);
259 
260  /* Now, do the actual simulation. */
261  NS_LOG_INFO("Run Simulation.");
262  Simulator::Stop(Seconds(120));
263  Simulator::Run();
265  NS_LOG_INFO("Done.");
266 
267  return 0;
268 }
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 SetIpv4StackInstall(bool enable)
Enable/disable IPv4 stack install.
void Install(std::string nodeName) const
Aggregate implementations of the ns3::Ipv4, ns3::Ipv6, ns3::Udp, and ns3::Tcp classes onto the provid...
void SetRoutingHelper(const Ipv4RoutingHelper &routing)
Helper class to auto-assign global IPv6 unicast addresses.
void SetBase(Ipv6Address network, Ipv6Prefix prefix, Ipv6Address base=Ipv6Address("::1"))
Set the base network number, network prefix, and base interface ID.
Ipv6InterfaceContainer Assign(const NetDeviceContainer &c)
Allocate an Ipv6InterfaceContainer with auto-assigned addresses.
Describes an IPv6 address.
Definition: ipv6-address.h:49
Access to the IPv6 forwarding table, interfaces, and configuration.
Definition: ipv6.h:82
Keep track of a set of IPv6 interfaces.
void SetForwarding(uint32_t i, bool state)
Set the state of the stack (act as a router or as an host) for the specified index.
void SetDefaultRouteInAllNodes(uint32_t router)
Set the default route for all the devices (except the router itself).
Ipv6Address GetAddress(uint32_t i, uint32_t j) const
Get the address for the specified index.
Helper class that adds ns3::Ipv6ListRouting objects.
void Add(const Ipv6RoutingHelper &routing, int16_t priority)
Describes an IPv6 prefix.
Definition: ipv6-address.h:455
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.
Helper class that adds ns3::Ipv6StaticRouting objects.
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 RIPng routing to nodes.
Definition: ripng-helper.h:44
void ExcludeInterface(Ptr< Node > node, uint32_t interface)
Exclude an interface from RIPng protocol.
void SetInterfaceMetric(Ptr< Node > node, uint32_t interface, uint8_t metric)
Set a metric for an interface.
@ 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
@ LOG_LEVEL_ALL
Print everything.
Definition: log.h:116
@ LOG_LEVEL_INFO
LOG_INFO and above.
Definition: log.h:104
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.