View | Details | Raw Unified | Return to bug 2289
Collapse All | Expand All

(-)a/examples/routing/rip-simple-network.cc (+258 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
// Network topology
22
//
23
//    SRC
24
//     |<=== source network
25
//     A-----B
26
//      \   / \   all networks have cost 1, except
27
//       \ /  |   for the direct link from C to D, which
28
//        C  /    has cost 10
29
//        | /
30
//        |/
31
//        D
32
//        |<=== target network
33
//       DST
34
//
35
//
36
// A, B, C and D are RIPng routers.
37
// A and D are configured with static addresses.
38
// SRC and DST will exchange packets.
39
//
40
// After about 3 seconds, the topology is built, and Echo Reply will be received.
41
// After 40 seconds, the link between B and D will break, causing a route failure.
42
// After 44 seconds from the failure, the routers will recovery from the failure.
43
// Split Horizoning should affect the recovery time, but it is not. See the manual
44
// for an explanation of this effect.
45
//
46
// If "showPings" is enabled, the user will see:
47
// 1) if the ping has been acknowledged
48
// 2) if a Destination Unreachable has been received by the sender
49
// 3) nothing, when the Echo Request has been received by the destination but
50
//    the Echo Reply is unable to reach the sender.
51
// Examining the .pcap files with Wireshark can confirm this effect.
52
53
54
#include <fstream>
55
#include "ns3/core-module.h"
56
#include "ns3/internet-module.h"
57
#include "ns3/csma-module.h"
58
#include "ns3/internet-apps-module.h"
59
#include "ns3/ipv4-static-routing-helper.h"
60
#include "ns3/ipv4-routing-table-entry.h"
61
62
using namespace ns3;
63
64
NS_LOG_COMPONENT_DEFINE ("RipSimpleRouting");
65
66
void 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 main (int argc, char **argv)
73
{
74
  bool verbose = false;
75
  bool printRoutingTables = false;
76
  bool showPings = false;
77
  std::string SplitHorizon ("PoisonReverse");
78
79
  CommandLine cmd;
80
  cmd.AddValue ("verbose", "turn on log components", verbose);
81
  cmd.AddValue ("printRoutingTables", "Print routing tables at 30, 60 and 90 seconds", printRoutingTables);
82
  cmd.AddValue ("showPings", "Show Ping6 reception", showPings);
83
  cmd.AddValue ("splitHorizonStrategy", "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)", SplitHorizon);
84
  cmd.Parse (argc, argv);
85
86
  if (verbose)
87
    {
88
      LogComponentEnableAll (LogLevel (LOG_PREFIX_TIME | LOG_PREFIX_NODE));
89
      LogComponentEnable ("RipSimpleRouting", LOG_LEVEL_INFO);
90
      LogComponentEnable ("Rip", LOG_LEVEL_ALL);
91
      LogComponentEnable ("Ipv4Interface", LOG_LEVEL_ALL);
92
      LogComponentEnable ("Icmpv4L4Protocol", LOG_LEVEL_ALL);
93
      LogComponentEnable ("Ipv4L3Protocol", LOG_LEVEL_ALL);
94
      LogComponentEnable ("ArpCache", LOG_LEVEL_ALL);
95
      LogComponentEnable ("V4Ping", LOG_LEVEL_ALL);
96
    }
97
98
  if (SplitHorizon == "NoSplitHorizon")
99
    {
100
      Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::NO_SPLIT_HORIZON));
101
    }
102
  else if (SplitHorizon == "SplitHorizon")
103
    {
104
      Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::SPLIT_HORIZON));
105
    }
106
  else
107
    {
108
      Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::POISON_REVERSE));
109
    }
110
111
  NS_LOG_INFO ("Create nodes.");
112
  Ptr<Node> src = CreateObject<Node> ();
113
  Names::Add ("SrcNode", src);
114
  Ptr<Node> dst = CreateObject<Node> ();
115
  Names::Add ("DstNode", dst);
116
  Ptr<Node> a = CreateObject<Node> ();
117
  Names::Add ("RouterA", a);
118
  Ptr<Node> b = CreateObject<Node> ();
119
  Names::Add ("RouterB", b);
120
  Ptr<Node> c = CreateObject<Node> ();
121
  Names::Add ("RouterC", c);
122
  Ptr<Node> d = CreateObject<Node> ();
123
  Names::Add ("RouterD", d);
124
  NodeContainer net1 (src, a);
125
  NodeContainer net2 (a, b);
126
  NodeContainer net3 (a, c);
127
  NodeContainer net4 (b, c);
128
  NodeContainer net5 (c, d);
129
  NodeContainer net6 (b, d);
130
  NodeContainer net7 (d, dst);
131
  NodeContainer routers (a, b, c, d);
132
  NodeContainer nodes (src, dst);
133
134
135
  NS_LOG_INFO ("Create channels.");
136
  CsmaHelper csma;
137
  csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
138
  csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
139
  NetDeviceContainer ndc1 = csma.Install (net1);
140
  NetDeviceContainer ndc2 = csma.Install (net2);
141
  NetDeviceContainer ndc3 = csma.Install (net3);
142
  NetDeviceContainer ndc4 = csma.Install (net4);
143
  NetDeviceContainer ndc5 = csma.Install (net5);
144
  NetDeviceContainer ndc6 = csma.Install (net6);
145
  NetDeviceContainer ndc7 = csma.Install (net7);
146
147
  NS_LOG_INFO ("Create IPv4 and routing");
148
  RipHelper ripRouting;
149
150
  // Rule of thumb:
151
  // Interfaces are added sequentially, starting from 0
152
  // However, interface 0 is always the loopback...
153
  ripRouting.ExcludeInterface (a, 1);
154
  ripRouting.ExcludeInterface (d, 3);
155
156
  ripRouting.SetInterfaceMetric (c, 3, 10);
157
  ripRouting.SetInterfaceMetric (d, 1, 10);
158
159
  Ipv4ListRoutingHelper listRH;
160
  listRH.Add (ripRouting, 0);
161
//  Ipv4StaticRoutingHelper staticRh;
162
//  listRH.Add (staticRh, 5);
163
164
  InternetStackHelper internet;
165
  internet.SetIpv6StackInstall (false);
166
  internet.SetRoutingHelper (listRH);
167
  internet.Install (routers);
168
169
  InternetStackHelper internetNodes;
170
  internetNodes.SetIpv6StackInstall (false);
171
  internetNodes.Install (nodes);
172
173
  // Assign addresses.
174
  // The source and destination networks have global addresses
175
  // The "core" network just needs link-local addresses for routing.
176
  // We assign global addresses to the routers as well to receive
177
  // ICMPv6 errors.
178
  NS_LOG_INFO ("Assign IPv4 Addresses.");
179
  Ipv4AddressHelper ipv4;
180
181
  ipv4.SetBase (Ipv4Address ("10.0.0.0"), Ipv4Mask ("255.255.255.0"));
182
  Ipv4InterfaceContainer iic1 = ipv4.Assign (ndc1);
183
184
  ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
185
  Ipv4InterfaceContainer iic2 = ipv4.Assign (ndc2);
186
187
  ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
188
  Ipv4InterfaceContainer iic3 = ipv4.Assign (ndc3);
189
190
  ipv4.SetBase (Ipv4Address ("10.0.3.0"), Ipv4Mask ("255.255.255.0"));
191
  Ipv4InterfaceContainer iic4 = ipv4.Assign (ndc4);
192
193
  ipv4.SetBase (Ipv4Address ("10.0.4.0"), Ipv4Mask ("255.255.255.0"));
194
  Ipv4InterfaceContainer iic5 = ipv4.Assign (ndc5);
195
196
  ipv4.SetBase (Ipv4Address ("10.0.5.0"), Ipv4Mask ("255.255.255.0"));
197
  Ipv4InterfaceContainer iic6 = ipv4.Assign (ndc6);
198
199
  ipv4.SetBase (Ipv4Address ("10.0.6.0"), Ipv4Mask ("255.255.255.0"));
200
  Ipv4InterfaceContainer iic7 = ipv4.Assign (ndc7);
201
202
  Ptr<Ipv4StaticRouting> staticRouting;
203
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (src->GetObject<Ipv4> ()->GetRoutingProtocol ());
204
  staticRouting->SetDefaultRoute ("10.0.0.2", 1 );
205
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (dst->GetObject<Ipv4> ()->GetRoutingProtocol ());
206
  staticRouting->SetDefaultRoute ("10.0.6.1", 1 );
207
208
  if (printRoutingTables)
209
    {
210
      RipHelper routingHelper;
211
212
      Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> (&std::cout);
213
214
      routingHelper.PrintRoutingTableAt (Seconds (30.0), a, routingStream);
215
      routingHelper.PrintRoutingTableAt (Seconds (30.0), b, routingStream);
216
      routingHelper.PrintRoutingTableAt (Seconds (30.0), c, routingStream);
217
      routingHelper.PrintRoutingTableAt (Seconds (30.0), d, routingStream);
218
219
      routingHelper.PrintRoutingTableAt (Seconds (60.0), a, routingStream);
220
      routingHelper.PrintRoutingTableAt (Seconds (60.0), b, routingStream);
221
      routingHelper.PrintRoutingTableAt (Seconds (60.0), c, routingStream);
222
      routingHelper.PrintRoutingTableAt (Seconds (60.0), d, routingStream);
223
224
      routingHelper.PrintRoutingTableAt (Seconds (90.0), a, routingStream);
225
      routingHelper.PrintRoutingTableAt (Seconds (90.0), b, routingStream);
226
      routingHelper.PrintRoutingTableAt (Seconds (90.0), c, routingStream);
227
      routingHelper.PrintRoutingTableAt (Seconds (90.0), d, routingStream);
228
    }
229
230
  NS_LOG_INFO ("Create Applications.");
231
  uint32_t packetSize = 1024;
232
  Time interPacketInterval = Seconds (1.0);
233
  V4PingHelper ping ("10.0.6.2");
234
235
  ping.SetAttribute ("Interval", TimeValue (interPacketInterval));
236
  ping.SetAttribute ("Size", UintegerValue (packetSize));
237
  if (showPings)
238
    {
239
      ping.SetAttribute ("Verbose", BooleanValue (true));
240
    }
241
  ApplicationContainer apps = ping.Install (src);
242
  apps.Start (Seconds (1.0));
243
  apps.Stop (Seconds (110.0));
244
245
  AsciiTraceHelper ascii;
246
  csma.EnableAsciiAll (ascii.CreateFileStream ("rip-simple-routing.tr"));
247
  csma.EnablePcapAll ("rip-simple-routing", true);
248
249
  Simulator::Schedule (Seconds (40), &TearDownLink, b, d, 3, 2);
250
251
  /* Now, do the actual simulation. */
252
  NS_LOG_INFO ("Run Simulation.");
253
  Simulator::Stop (Seconds (131.0));
254
  Simulator::Run ();
255
  Simulator::Destroy ();
256
  NS_LOG_INFO ("Done.");
257
}
258
(-)a/examples/routing/wscript (+6 lines)
 Lines 42-44    Link Here 
42
    obj.source = 'ripng-simple-network.cc'
42
    obj.source = 'ripng-simple-network.cc'
43
43
44
    bld.register_ns3_script('simple-routing-ping6.py', ['csma', 'internet', 'internet-apps'])
44
    bld.register_ns3_script('simple-routing-ping6.py', ['csma', 'internet', 'internet-apps'])
45
46
    obj = bld.create_ns3_program('rip-simple-network',
47
                                 ['csma', 'internet', 'internet-apps'])
48
    obj.source = 'rip-simple-network.cc'
49
50
    
(-)a/src/internet/doc/routing-overview.rst (-18 / +28 lines)
 Lines 215-221    Link Here 
215
Unicast routing
215
Unicast routing
216
***************
216
***************
217
217
218
There are presently seven unicast routing protocols defined for IPv4 and three for
218
There are presently eigth unicast routing protocols defined for IPv4 and three for
219
IPv6:
219
IPv6:
220
220
221
* class Ipv4StaticRouting (covering both unicast and multicast)
221
* class Ipv4StaticRouting (covering both unicast and multicast)
 Lines 230-235    Link Here 
230
  manager, if that is used)
230
  manager, if that is used)
231
* class Ipv4NixVectorRouting (a more efficient version of global routing that
231
* class Ipv4NixVectorRouting (a more efficient version of global routing that
232
  stores source routes in a packet header field)
232
  stores source routes in a packet header field)
233
* class Rip - the IPv4 RIPv2 protocol (:rfc:`2453`)
233
* class Ipv6ListRouting (used to store a prioritized list of routing protocols)
234
* class Ipv6ListRouting (used to store a prioritized list of routing protocols)
234
* class Ipv6StaticRouting 
235
* class Ipv6StaticRouting 
235
* class RipNg - the IPv6 RIPng protocol (:rfc:`2080`)
236
* class RipNg - the IPv6 RIPng protocol (:rfc:`2080`)
 Lines 334-360    Link Here 
334
notifications; i.e. the topology changes are due to loss/gain of connectivity
335
notifications; i.e. the topology changes are due to loss/gain of connectivity
335
over a wireless channel.
336
over a wireless channel.
336
337
337
RIPng
338
RIP and RIPng
338
+++++
339
+++++++++++++
340
341
The RIPv2 protocol for IPv4 is described in the :rfc:`2453`, and it consolidates
342
a number of improvements over the base protocol defined in :rfc:`1058`.
339
343
340
This IPv6 routing protocol (:rfc:`2080`) is the evolution of the well-known 
344
This IPv6 routing protocol (:rfc:`2080`) is the evolution of the well-known 
341
RIPv1 anf RIPv2 (see :rfc:`1058` and :rfc:`1723`) routing protocols for IPv4.
345
RIPv1 (see :rfc:`1058` and :rfc:`1723`) routing protocol for IPv4.
342
346
343
The protocol is very simple, and it is normally suitable for flat, simple 
347
The protocols are very simple, and are normally suitable for flat, simple 
344
network topologies.
348
network topologies.
345
349
346
RIPng is strongly based on RIPv1 and RIPv2, and it have the very same goals and
350
RIPv1, RIPv2, and RIPng have the very same goals and limitations. 
347
limitations. In particular, RIP considers any route with a metric equal or greater 
351
In particular, RIP considers any route with a metric equal or greater 
348
than 16 as unreachable. As a consequence, the maximum number of hops is the
352
than 16 as unreachable. As a consequence, the maximum number of hops is the
349
network must be less than 15 (the number of routers is not set).
353
network must be less than 15 (the number of routers is not set).
350
Users are encouraged to read :rfc:`2080` and :rfc:`1058` to fully understand
354
Users are encouraged to read :rfc:`2080` and :rfc:`1058` to fully understand
351
RIPng behaviour and limitations.
355
RIP behaviour and limitations.
352
356
353
357
354
Routing convergence
358
Routing convergence
355
~~~~~~~~~~~~~~~~~~~
359
~~~~~~~~~~~~~~~~~~~
356
360
357
RIPng uses a Distance-Vector algorithm, and routes are updated according to
361
RIP uses a Distance-Vector algorithm, and routes are updated according to
358
the Bellman-Ford algorithm (sometimes known as Ford-Fulkerson algorithm).
362
the Bellman-Ford algorithm (sometimes known as Ford-Fulkerson algorithm).
359
The algorithm has a convergence time of O(\|V\|*\|E\|) where \|V\| and \|E\| 
363
The algorithm has a convergence time of O(\|V\|*\|E\|) where \|V\| and \|E\| 
360
are the number of vertices (routers) and edges (links) respectively.
364
are the number of vertices (routers) and edges (links) respectively.
 Lines 365-371    Link Here 
365
369
366
Users should be aware that, during routing tables construction, the routers 
370
Users should be aware that, during routing tables construction, the routers 
367
might drop packets. Data traffic should be sent only after a time long
371
might drop packets. Data traffic should be sent only after a time long
368
enough to allow RIPng to build the network topology.
372
enough to allow RIP to build the network topology.
369
Usually 80 seconds should be enough to have a suboptimal (but working)
373
Usually 80 seconds should be enough to have a suboptimal (but working)
370
routing setup. This includes the time needed to propagate the routes to the
374
routing setup. This includes the time needed to propagate the routes to the
371
most distant router (16 hops) with Triggered Updates.
375
most distant router (16 hops) with Triggered Updates.
 Lines 375-387    Link Here 
375
setup time. Moreover, the network topology recovery is affected by
379
setup time. Moreover, the network topology recovery is affected by
376
the Split Horizoning strategy.
380
the Split Horizoning strategy.
377
381
378
The example ``examples/routing/ripng-simple-network.cc`` shows both the
382
The examples ``examples/routing/ripng-simple-network.cc`` and 
379
network setup and network recovery phases.
383
``examples/routing/rip-simple-network.cc``
384
shows both the network setup and network recovery phases.
380
385
381
Split Horizoning
386
Split Horizoning
382
~~~~~~~~~~~~~~~~
387
~~~~~~~~~~~~~~~~
383
388
384
Split Horizon is a strategy to prevent routing instability. Three options are possible:
389
Split Horizon is a strategy to prevent routing instability.
390
Three options are possible:
385
391
386
* No Split Horizon
392
* No Split Horizon
387
* Split Horizon
393
* Split Horizon
 Lines 394-400    Link Here 
394
was learned, but with a metric of 16 (infinity).
400
was learned, but with a metric of 16 (infinity).
395
For a full analysis of the three techniques, see :rfc:`1058`, section 2.2.
401
For a full analysis of the three techniques, see :rfc:`1058`, section 2.2.
396
402
397
The example ``ripng-simple-network.cc`` is based on the network toplogy
403
The examples are based on the network toplogy
398
described in the RFC, but it does not show the effect described there.
404
described in the RFC, but it does not show the effect described there.
399
405
400
The reason are the Triggered Updates, together with the fact that when a 
406
The reason are the Triggered Updates, together with the fact that when a 
 Lines 410-427    Link Here 
410
Default routes
416
Default routes
411
~~~~~~~~~~~~~~
417
~~~~~~~~~~~~~~
412
418
413
RIPng protocol should be installed *only* on routers. As a consequence, 
419
RIP protocol should be installed *only* on routers. As a consequence, 
414
nodes will not know what is the default router.
420
nodes will not know what is the default router.
415
421
416
To overcome this limitation, users should either install the default route
422
To overcome this limitation, users should either install the default route
417
manually (e.g., by resorting to Ipv6StaticRouting), or by using RADVd.
423
manually (e.g., by resorting to Ipv4StaticRouting or Ipv6StaticRouting), or 
424
by using RADVd (in case of IPv6).
418
RADVd is available in |ns3| in the Applications module, and it is strongly 
425
RADVd is available in |ns3| in the Applications module, and it is strongly 
419
suggested.
426
suggested.
420
 
427
 
421
Protocol parameters and options
428
Protocol parameters and options
422
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
429
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
423
430
424
The RIPng |ns3| implementation allows to change all the timers associated 
431
The RIP |ns3| implementations allow to change all the timers associated 
425
with route updates and routes lifetime.
432
with route updates and routes lifetime.
426
433
427
Moreover, users can change the interface metrics on a per-node basis.
434
Moreover, users can change the interface metrics on a per-node basis.
 Lines 431-441    Link Here 
431
"split horizon" and "poison reverse". See :rfc:`2080` for further details,
438
"split horizon" and "poison reverse". See :rfc:`2080` for further details,
432
and :rfc:`1058` for a complete discussion on the split horizoning strategies.
439
and :rfc:`1058` for a complete discussion on the split horizoning strategies.
433
440
441
Moreover, it is possible to use a non-standard value for Link Down Value (i.e.,
442
the value after which a link is considered down). The defaul is value is 16. 
443
434
Limitations
444
Limitations
435
~~~~~~~~~~~
445
~~~~~~~~~~~
436
446
437
There is no support for the Next Hop option (:rfc:`2080`, Section 2.1.1).
447
There is no support for the Next Hop option (:rfc:`2080`, Section 2.1.1).
438
The Next Hop option is useful when RIPng is not being run on all of the 
448
The Next Hop option is useful when RIP is not being run on all of the 
439
routers on a network.
449
routers on a network.
440
Support for this option may be considered in the future.
450
Support for this option may be considered in the future.
441
451
(-)a/src/internet/helper/rip-helper.cc (+182 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#include "ns3/node.h"
22
#include "ns3/node-list.h"
23
#include "ns3/ipv4-list-routing.h"
24
#include "ns3/rip.h"
25
#include "rip-helper.h"
26
27
namespace ns3 {
28
29
RipHelper::RipHelper ()
30
{
31
  m_factory.SetTypeId ("ns3::Rip");
32
}
33
34
RipHelper::RipHelper (const RipHelper &o)
35
  : m_factory (o.m_factory)
36
{
37
  m_interfaceExclusions = o.m_interfaceExclusions;
38
  m_interfaceMetrics = o.m_interfaceMetrics;
39
}
40
41
RipHelper::~RipHelper ()
42
{
43
  m_interfaceExclusions.clear ();
44
  m_interfaceMetrics.clear ();
45
}
46
47
RipHelper*
48
RipHelper::Copy (void) const
49
{
50
  return new RipHelper (*this);
51
}
52
53
Ptr<Ipv4RoutingProtocol>
54
RipHelper::Create (Ptr<Node> node) const
55
{
56
  Ptr<Rip> rip = m_factory.Create<Rip> ();
57
58
  std::map<Ptr<Node>, std::set<uint32_t> >::const_iterator it = m_interfaceExclusions.find (node);
59
60
  if(it != m_interfaceExclusions.end ())
61
    {
62
      rip->SetInterfaceExclusions (it->second);
63
    }
64
65
  std::map< Ptr<Node>, std::map<uint32_t, uint8_t> >::const_iterator iter = m_interfaceMetrics.find (node);
66
67
  if(iter != m_interfaceMetrics.end ())
68
    {
69
      std::map<uint32_t, uint8_t>::const_iterator subiter;
70
      for (subiter = iter->second.begin (); subiter != iter->second.end (); subiter++)
71
        {
72
          rip->SetInterfaceMetric (subiter->first, subiter->second);
73
        }
74
    }
75
76
  node->AggregateObject (rip);
77
  return rip;
78
}
79
80
void
81
RipHelper::Set (std::string name, const AttributeValue &value)
82
{
83
  m_factory.Set (name, value);
84
}
85
86
87
int64_t
88
RipHelper::AssignStreams (NodeContainer c, int64_t stream)
89
{
90
  int64_t currentStream = stream;
91
  Ptr<Node> node;
92
  for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
93
    {
94
      node = (*i);
95
      Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
96
      NS_ASSERT_MSG (ipv4, "Ipv4 not installed on node");
97
      Ptr<Ipv4RoutingProtocol> proto = ipv4->GetRoutingProtocol ();
98
      NS_ASSERT_MSG (proto, "Ipv4 routing not installed on node");
99
      Ptr<Rip> rip = DynamicCast<Rip> (proto);
100
      if (rip)
101
        {
102
          currentStream += rip->AssignStreams (currentStream);
103
          continue;
104
        }
105
      // RIP may also be in a list
106
      Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (proto);
107
      if (list)
108
        {
109
          int16_t priority;
110
          Ptr<Ipv4RoutingProtocol> listProto;
111
          Ptr<Rip> listRip;
112
          for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++)
113
            {
114
              listProto = list->GetRoutingProtocol (i, priority);
115
              listRip = DynamicCast<Rip> (listProto);
116
              if (listRip)
117
                {
118
                  currentStream += listRip->AssignStreams (currentStream);
119
                  break;
120
                }
121
            }
122
        }
123
    }
124
  return (currentStream - stream);
125
}
126
127
void RipHelper::SetDefaultRouter (Ptr<Node> node, Ipv4Address nextHop, uint32_t interface)
128
{
129
  Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
130
  NS_ASSERT_MSG (ipv4, "Ipv4 not installed on node");
131
  Ptr<Ipv4RoutingProtocol> proto = ipv4->GetRoutingProtocol ();
132
  NS_ASSERT_MSG (proto, "Ipv4 routing not installed on node");
133
  Ptr<Rip> rip = DynamicCast<Rip> (proto);
134
  if (rip)
135
    {
136
      rip->AddDefaultRouteTo (nextHop, interface);
137
    }
138
  // RIP may also be in a list
139
  Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (proto);
140
  if (list)
141
    {
142
      int16_t priority;
143
      Ptr<Ipv4RoutingProtocol> listProto;
144
      Ptr<Rip> listRip;
145
      for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++)
146
        {
147
          listProto = list->GetRoutingProtocol (i, priority);
148
          listRip = DynamicCast<Rip> (listProto);
149
          if (listRip)
150
            {
151
              listRip->AddDefaultRouteTo (nextHop, interface);
152
              break;
153
            }
154
        }
155
    }
156
}
157
158
void
159
RipHelper::ExcludeInterface (Ptr<Node> node, uint32_t interface)
160
{
161
  std::map< Ptr<Node>, std::set<uint32_t> >::iterator it = m_interfaceExclusions.find (node);
162
163
  if (it == m_interfaceExclusions.end ())
164
    {
165
      std::set<uint32_t> interfaces;
166
      interfaces.insert (interface);
167
168
      m_interfaceExclusions.insert (std::make_pair (node, interfaces));
169
    }
170
  else
171
    {
172
      it->second.insert (interface);
173
    }
174
}
175
176
void RipHelper::SetInterfaceMetric (Ptr<Node> node, uint32_t interface, uint8_t metric)
177
{
178
  m_interfaceMetrics[node][interface] = metric;
179
}
180
181
}
182
(-)a/src/internet/helper/rip-helper.h (+148 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#ifndef RIP_HELPER_H
22
#define RIP_HELPER_H
23
24
#include "ns3/object-factory.h"
25
#include "ns3/ipv4-routing-helper.h"
26
#include "ns3/node-container.h"
27
#include "ns3/node.h"
28
29
namespace ns3 {
30
31
/**
32
 * \brief Helper class that adds RIP routing to nodes.
33
 *
34
 * This class is expected to be used in conjunction with
35
 * ns3::InternetStackHelper::SetRoutingHelper
36
 *
37
 */
38
class RipHelper : public Ipv4RoutingHelper
39
{
40
public:
41
  /*
42
   * Construct an RipHelper to make life easier while adding RIP
43
   * routing to nodes.
44
   */
45
  RipHelper ();
46
47
  /**
48
   * \brief Construct an RipHelper from another previously
49
   * initialized instance (Copy Constructor).
50
   */
51
  RipHelper (const RipHelper &);
52
53
  virtual ~RipHelper ();
54
55
  /**
56
   * \returns pointer to clone of this RipHelper
57
   *
58
   * This method is mainly for internal use by the other helpers;
59
   * clients are expected to free the dynamic memory allocated by this method
60
   */
61
  RipHelper* Copy (void) const;
62
63
  /**
64
   * \param node the node on which the routing protocol will run
65
   * \returns a newly-created routing protocol
66
   *
67
   * This method will be called by ns3::InternetStackHelper::Install
68
   */
69
  virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const;
70
71
  /**
72
   * \param name the name of the attribute to set
73
   * \param value the value of the attribute to set.
74
   *
75
   * This method controls the attributes of ns3::Ripng
76
   */
77
  void Set (std::string name, const AttributeValue &value);
78
79
  /**
80
   * Assign a fixed random variable stream number to the random variables
81
   * used by this model. Return the number of streams (possibly zero) that
82
   * have been assigned. The Install() method should have previously been
83
   * called by the user.
84
   *
85
   * \param c NetDeviceContainer of the set of net devices for which the
86
   *          SixLowPanNetDevice should be modified to use a fixed stream
87
   * \param stream first stream index to use
88
   * \return the number of stream indices assigned by this helper
89
   */
90
  int64_t AssignStreams (NodeContainer c, int64_t stream);
91
92
  /**
93
   * \brief Install a default route in the node.
94
   *
95
   * The traffic will be routed to the nextHop, located on the specified
96
   * interface, unless a more specific route is found.
97
   *
98
   * \param node the node
99
   * \param nextHop the next hop
100
   * \param interface the network interface
101
   */
102
  void SetDefaultRouter (Ptr<Node> node, Ipv4Address nextHop, uint32_t interface);
103
104
  /**
105
   * \brief Exclude an interface from RIP protocol.
106
   *
107
   * You have to call this function \a before installing RIP in the nodes.
108
   *
109
   * Note: the exclusion means that RIP will not be propagated on that interface.
110
   * The network prefix on that interface will be still considered in RIP.
111
   *
112
   * \param node the node
113
   * \param interface the network interface to be excluded
114
   */
115
  void ExcludeInterface (Ptr<Node> node, uint32_t interface);
116
117
  /**
118
   * \brief Set a metric for an interface.
119
   *
120
   * You have to call this function \a before installing RIP in the nodes.
121
   *
122
   * Note: RIP will apply the metric on route message reception.
123
   * As a consequence, interface metric should be set on the receiver.
124
   *
125
   * \param node the node
126
   * \param interface the network interface
127
   * \param metric the interface metric
128
   */
129
  void SetInterfaceMetric (Ptr<Node> node, uint32_t interface, uint8_t metric);
130
131
private:
132
  /**
133
   * \brief Assignment operator declared private and not implemented to disallow
134
   * assignment and prevent the compiler from happily inserting its own.
135
   */
136
  RipHelper &operator = (const RipHelper &o);
137
138
  ObjectFactory m_factory; //!< Object Factory
139
140
  std::map< Ptr<Node>, std::set<uint32_t> > m_interfaceExclusions; //!< Interface Exclusion set
141
  std::map< Ptr<Node>, std::map<uint32_t, uint8_t> > m_interfaceMetrics; //!< Interface Metric set
142
};
143
144
} // namespace ns3
145
146
147
#endif /* RIP_HELPER_H */
148
(-)a/src/internet/model/rip-header.cc (+278 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#include "rip-header.h"
22
23
namespace ns3 {
24
25
/*
26
 * RipRte
27
 */
28
NS_OBJECT_ENSURE_REGISTERED (RipRte);
29
30
31
RipRte::RipRte ()
32
  : m_tag (0), m_prefix ("127.0.0.1"), m_subnetMask ("0.0.0.0"), m_nextHop ("0.0.0.0"), m_metric (16)
33
{
34
}
35
36
TypeId RipRte::GetTypeId (void)
37
{
38
  static TypeId tid = TypeId ("ns3::RipRte")
39
    .SetParent<Header> ()
40
    .SetGroupName ("Internet")
41
    .AddConstructor<RipRte> ();
42
  return tid;
43
}
44
45
TypeId RipRte::GetInstanceTypeId (void) const
46
{
47
  return GetTypeId ();
48
}
49
50
void RipRte::Print (std::ostream & os) const
51
{
52
  os << "prefix " << m_prefix << "/" << m_subnetMask.GetPrefixLength () << " Metric " << int(m_metric);
53
  os << " Tag " << int(m_tag) << " Next Hop " << m_nextHop;
54
}
55
56
uint32_t RipRte::GetSerializedSize () const
57
{
58
  return 20;
59
}
60
61
void RipRte::Serialize (Buffer::Iterator i) const
62
{
63
  i.WriteHtonU16 (2);
64
  i.WriteHtonU16 (m_tag);
65
66
  i.WriteHtonU32 (m_prefix.Get ());
67
  i.WriteHtonU32 (m_subnetMask.Get ());
68
  i.WriteHtonU32 (m_nextHop.Get ());
69
  i.WriteHtonU32 (m_metric);
70
}
71
72
uint32_t RipRte::Deserialize (Buffer::Iterator i)
73
{
74
  uint16_t tmp;
75
76
  tmp = i.ReadNtohU16 ();
77
  if (tmp != 2)
78
    {
79
      return 0;
80
    }
81
82
  m_tag = i.ReadNtohU16 ();
83
  m_prefix.Set (i.ReadNtohU32 ());
84
  m_subnetMask.Set (i.ReadNtohU32 ());
85
  m_nextHop.Set (i.ReadNtohU32 ());
86
87
  m_metric = i.ReadNtohU32 ();
88
89
  return GetSerializedSize ();
90
}
91
92
void RipRte::SetPrefix (Ipv4Address prefix)
93
{
94
  m_prefix = prefix;
95
}
96
97
Ipv4Address RipRte::GetPrefix () const
98
{
99
  return m_prefix;
100
}
101
102
void RipRte::SetSubnetMask (Ipv4Mask subnetMask)
103
{
104
  m_subnetMask = subnetMask;
105
}
106
107
Ipv4Mask RipRte::GetSubnetMask () const
108
{
109
  return m_subnetMask;
110
}
111
112
void RipRte::SetRouteTag (uint16_t routeTag)
113
{
114
  m_tag = routeTag;
115
}
116
117
uint16_t RipRte::GetRouteTag () const
118
{
119
  return m_tag;
120
}
121
122
void RipRte::SetRouteMetric (uint32_t routeMetric)
123
{
124
  m_metric = routeMetric;
125
}
126
127
uint32_t RipRte::GetRouteMetric () const
128
{
129
  return m_metric;
130
}
131
132
void RipRte::SetNextHop (Ipv4Address nextHop)
133
{
134
  m_nextHop = nextHop;
135
}
136
137
Ipv4Address RipRte::GetNextHop () const
138
{
139
  return m_nextHop;
140
}
141
142
143
std::ostream & operator << (std::ostream & os, const RipRte & h)
144
{
145
  h.Print (os);
146
  return os;
147
}
148
149
/*
150
 * RipHeader
151
 */
152
NS_OBJECT_ENSURE_REGISTERED (RipHeader)
153
  ;
154
155
RipHeader::RipHeader ()
156
  : m_command (0)
157
{
158
}
159
160
TypeId RipHeader::GetTypeId (void)
161
{
162
  static TypeId tid = TypeId ("ns3::RipHeader")
163
    .SetParent<Header> ()
164
    .SetGroupName ("Internet")
165
    .AddConstructor<RipHeader> ();
166
  return tid;
167
}
168
169
TypeId RipHeader::GetInstanceTypeId (void) const
170
{
171
  return GetTypeId ();
172
}
173
174
void RipHeader::Print (std::ostream & os) const
175
{
176
  os << "command " << int(m_command);
177
  for (std::list<RipRte>::const_iterator iter = m_rteList.begin ();
178
      iter != m_rteList.end (); iter ++)
179
    {
180
      os << " | ";
181
      iter->Print (os);
182
    }
183
}
184
185
uint32_t RipHeader::GetSerializedSize () const
186
{
187
  RipRte rte;
188
  return 4 + m_rteList.size () * rte.GetSerializedSize ();
189
}
190
191
void RipHeader::Serialize (Buffer::Iterator start) const
192
{
193
  Buffer::Iterator i = start;
194
195
  i.WriteU8 (uint8_t (m_command));
196
  i.WriteU8 (1);
197
  i.WriteU16 (0);
198
199
  for (std::list<RipRte>::const_iterator iter = m_rteList.begin ();
200
      iter != m_rteList.end (); iter ++)
201
    {
202
      iter->Serialize (i);
203
      i.Next(iter->GetSerializedSize ());
204
    }
205
}
206
207
uint32_t RipHeader::Deserialize (Buffer::Iterator start)
208
{
209
  Buffer::Iterator i = start;
210
211
  uint8_t temp;
212
  temp = i.ReadU8 ();
213
  if ((temp == REQUEST) || (temp == RESPONSE))
214
    {
215
      m_command = temp;
216
    }
217
  else
218
    {
219
      return 0;
220
    }
221
222
  temp = i.ReadU8 ();
223
  NS_ASSERT_MSG (temp == 1, "RIP received a message with mismatch version, aborting.");
224
225
  uint16_t temp16 = i.ReadU16 ();
226
  NS_ASSERT_MSG (temp16 == 0, "RIP received a message with invalid filled flags, aborting.");
227
228
  uint8_t rteNumber = (i.GetSize () - 4)/20;
229
  for (uint8_t n=0; n<rteNumber; n++)
230
    {
231
      RipRte rte;
232
      i.Next (rte.Deserialize (i));
233
      m_rteList.push_back (rte);
234
    }
235
236
  return GetSerializedSize ();
237
}
238
239
void RipHeader::SetCommand (RipHeader::Command_e command)
240
{
241
  m_command = command;
242
}
243
244
RipHeader::Command_e RipHeader::GetCommand () const
245
{
246
  return RipHeader::Command_e (m_command);
247
}
248
249
void RipHeader::AddRte (RipRte rte)
250
{
251
  m_rteList.push_back (rte);
252
}
253
254
void RipHeader::ClearRtes ()
255
{
256
  m_rteList.clear ();
257
}
258
259
uint16_t RipHeader::GetRteNumber (void) const
260
{
261
  return m_rteList.size ();
262
}
263
264
std::list<RipRte> RipHeader::GetRteList (void) const
265
{
266
  return m_rteList;
267
}
268
269
270
std::ostream & operator << (std::ostream & os, const RipHeader & h)
271
{
272
  h.Print (os);
273
  return os;
274
}
275
276
277
}
278
(-)a/src/internet/model/rip-header.h (+256 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#ifndef RIP_HEADER_H
22
#define RIP_HEADER_H
23
24
#include <list>
25
#include "ns3/header.h"
26
#include "ns3/ipv4-address.h"
27
#include "ns3/packet.h"
28
#include "ns3/ipv4-header.h"
29
30
31
namespace ns3 {
32
33
/**
34
 * \ingroup rip
35
 * \brief Rip v2 Routing Table Entry (RTE) - see \RFC{2453}.
36
 */
37
class RipRte : public Header
38
{
39
public:
40
  RipRte (void);
41
42
  /**
43
   * \brief Get the type ID.
44
   * \return The object TypeId.
45
   */
46
  static TypeId GetTypeId (void);
47
48
  /**
49
   * \brief Return the instance type identifier.
50
   * \return Instance type ID.
51
   */
52
  virtual TypeId GetInstanceTypeId (void) const;
53
54
  virtual void Print (std::ostream& os) const;
55
56
  /**
57
   * \brief Get the serialized size of the packet.
58
   * \return Size.
59
   */
60
  virtual uint32_t GetSerializedSize (void) const;
61
62
  /**
63
   * \brief Serialize the packet.
64
   * \param start Buffer iterator.
65
   */
66
  virtual void Serialize (Buffer::Iterator start) const;
67
68
  /**
69
   * \brief Deserialize the packet.
70
   * \param start Buffer iterator.
71
   * \return Size of the packet.
72
   */
73
  virtual uint32_t Deserialize (Buffer::Iterator start);
74
75
  /**
76
   * \brief Set the prefix.
77
   * \param prefix The prefix.
78
   */
79
  void SetPrefix (Ipv4Address prefix);
80
81
  /**
82
   * \brief Get the prefix.
83
   * \returns The prefix.
84
   */
85
  Ipv4Address GetPrefix (void) const;
86
87
  /**
88
   * \brief Set the subnet mask.
89
   * \param subnetMask The subnet mask.
90
   */
91
  void SetSubnetMask (Ipv4Mask subnetMask);
92
93
  /**
94
   * \brief Get the subnet mask.
95
   * \returns The subnet mask.
96
   */
97
  Ipv4Mask GetSubnetMask (void) const;
98
99
  /**
100
   * \brief Set the route tag.
101
   * \param routeTag The route tag.
102
   */
103
  void SetRouteTag (uint16_t routeTag);
104
105
  /**
106
   * \brief Get the route tag.
107
   * \returns The route tag.
108
   */
109
  uint16_t GetRouteTag (void) const;
110
111
  /**
112
   * \brief Set the route metric.
113
   * \param routeMetric The route metric.
114
   */
115
  void SetRouteMetric (uint32_t routeMetric);
116
117
  /**
118
   * \brief Get the route metric.
119
   * \returns The route metric.
120
   */
121
  uint32_t GetRouteMetric (void) const;
122
123
  /**
124
   * \brief Set the route metric.
125
   * \param routeMetric The route metric.
126
   */
127
  void SetNextHop (Ipv4Address nextHop);
128
129
  /**
130
   * \brief Get the route metric.
131
   * \returns The route metric.
132
   */
133
  Ipv4Address GetNextHop (void) const;
134
135
136
private:
137
  uint16_t m_tag; //!< Route tag.
138
  Ipv4Address m_prefix; //!< Advertised prefix.
139
  Ipv4Mask m_subnetMask; //!< Subnet mask.
140
  Ipv4Address m_nextHop; //!< Next hop.
141
  uint32_t m_metric; //!< Route metric.
142
};
143
144
/**
145
 * \brief Stream insertion operator.
146
 *
147
 * \param os the reference to the output stream
148
 * \param h the Routing Table Entry
149
 * \returns the reference to the output stream
150
 */
151
std::ostream & operator << (std::ostream & os, const RipRte & h);
152
153
/**
154
 * \ingroup rip
155
 * \brief RipHeader - see \RFC{2453}
156
 */
157
class RipHeader : public Header
158
{
159
public:
160
  RipHeader (void);
161
162
  /**
163
   * \brief Get the type ID.
164
   * \return the object TypeId
165
   */
166
  static TypeId GetTypeId (void);
167
168
  /**
169
   * \brief Return the instance type identifier.
170
   * \return instance type ID
171
   */
172
  virtual TypeId GetInstanceTypeId (void) const;
173
174
  virtual void Print (std::ostream& os) const;
175
176
  /**
177
   * \brief Get the serialized size of the packet.
178
   * \return size
179
   */
180
  virtual uint32_t GetSerializedSize (void) const;
181
182
  /**
183
   * \brief Serialize the packet.
184
   * \param start Buffer iterator
185
   */
186
  virtual void Serialize (Buffer::Iterator start) const;
187
188
  /**
189
   * \brief Deserialize the packet.
190
   * \param start Buffer iterator
191
   * \return size of the packet
192
   */
193
  virtual uint32_t Deserialize (Buffer::Iterator start);
194
195
  /**
196
   * Commands to be used in Rip headers
197
   */
198
  enum Command_e
199
  {
200
    REQUEST = 0x1,
201
    RESPONSE = 0x2,
202
  };
203
204
  /**
205
   * \brief Set the command
206
   * \param command the command
207
   */
208
  void SetCommand (Command_e command);
209
210
  /**
211
   * \brief Get the command
212
   * \returns the command
213
   */
214
  Command_e GetCommand (void) const;
215
216
  /**
217
   * \brief Add a RTE to the message
218
   * \param rte the RTE
219
   */
220
  void AddRte (RipRte rte);
221
222
  /**
223
   * \brief Clear all the RTEs from the header
224
   */
225
  void ClearRtes ();
226
227
  /**
228
   * \brief Get the number of RTE included in the message
229
   * \returns the number of RTE in the message
230
   */
231
  uint16_t GetRteNumber (void) const;
232
233
  /**
234
   * \brief Get the list of the RTEs included in the message
235
   * \returns the list of the RTEs in the message
236
   */
237
  std::list<RipRte> GetRteList (void) const;
238
239
private:
240
  uint8_t m_command; //!< command type
241
  std::list<RipRte> m_rteList; //!< list of the RTEs in the message
242
};
243
244
/**
245
 * \brief Stream insertion operator.
246
 *
247
 * \param os the reference to the output stream
248
 * \param h the Rip header
249
 * \returns the reference to the output stream
250
 */
251
std::ostream & operator << (std::ostream & os, const RipHeader & h);
252
253
}
254
255
#endif /* Rip_HEADER_H */
256
(-)a/src/internet/model/rip.cc (+1369 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#include <iomanip>
22
#include "rip.h"
23
#include "ns3/log.h"
24
#include "ns3/abort.h"
25
#include "ns3/assert.h"
26
#include "ns3/unused.h"
27
#include "ns3/random-variable-stream.h"
28
#include "ns3/ipv4-route.h"
29
#include "ns3/node.h"
30
#include "ns3/names.h"
31
#include "ns3/rip-header.h"
32
#include "ns3/udp-header.h"
33
#include "ns3/enum.h"
34
#include "ns3/uinteger.h"
35
#include "ns3/ipv4-packet-info-tag.h"
36
#include "ns3/loopback-net-device.h"
37
38
#define RIP_ALL_NODE "224.0.0.9"
39
#define RIP_PORT 520
40
41
namespace ns3 {
42
43
NS_LOG_COMPONENT_DEFINE ("Rip");
44
45
NS_OBJECT_ENSURE_REGISTERED (Rip);
46
47
Rip::Rip ()
48
  : m_ipv4 (0), m_splitHorizonStrategy (Rip::POISON_REVERSE), m_initialized (false)
49
{
50
  m_rng = CreateObject<UniformRandomVariable> ();
51
}
52
53
Rip::~Rip ()
54
{
55
}
56
57
TypeId
58
Rip::GetTypeId (void)
59
{
60
  static TypeId tid = TypeId ("ns3::Rip")
61
    .SetParent<Ipv4RoutingProtocol> ()
62
    .SetGroupName ("Internet")
63
    .AddConstructor<Rip> ()
64
    .AddAttribute ("UnsolicitedRoutingUpdate", "The time between two Unsolicited Routing Updates.",
65
                   TimeValue (Seconds(30)),
66
                   MakeTimeAccessor (&Rip::m_unsolicitedUpdate),
67
                   MakeTimeChecker ())
68
    .AddAttribute ("StartupDelay", "Maximum random delay for protocol startup (send route requests).",
69
                   TimeValue (Seconds(1)),
70
                   MakeTimeAccessor (&Rip::m_startupDelay),
71
                   MakeTimeChecker ())
72
    .AddAttribute ("TimeoutDelay", "The delay to invalidate a route.",
73
                   TimeValue (Seconds(180)),
74
                   MakeTimeAccessor (&Rip::m_timeoutDelay),
75
                   MakeTimeChecker ())
76
    .AddAttribute ("GarbageCollectionDelay", "The delay to delete an expired route.",
77
                   TimeValue (Seconds(120)),
78
                   MakeTimeAccessor (&Rip::m_garbageCollectionDelay),
79
                   MakeTimeChecker ())
80
    .AddAttribute ("MinTriggeredCooldown", "Min cooldown delay after a Triggered Update.",
81
                   TimeValue (Seconds(1)),
82
                   MakeTimeAccessor (&Rip::m_minTriggeredUpdateDelay),
83
                   MakeTimeChecker ())
84
    .AddAttribute ("MaxTriggeredCooldown", "Max cooldown delay after a Triggered Update.",
85
                   TimeValue (Seconds(5)),
86
                   MakeTimeAccessor (&Rip::m_maxTriggeredUpdateDelay),
87
                   MakeTimeChecker ())
88
    .AddAttribute ("SplitHorizon", "Split Horizon strategy.",
89
                   EnumValue (Rip::POISON_REVERSE),
90
                   MakeEnumAccessor (&Rip::m_splitHorizonStrategy),
91
                   MakeEnumChecker (Rip::NO_SPLIT_HORIZON, "NoSplitHorizon",
92
                                    Rip::SPLIT_HORIZON, "SplitHorizon",
93
                                    Rip::POISON_REVERSE, "PoisonReverse"))
94
    .AddAttribute ("LinkDownValue", "Value for link down in count to infinity.",
95
                   UintegerValue (16),
96
                   MakeUintegerAccessor (&Rip::m_linkDown),
97
                   MakeUintegerChecker<uint32_t> ())
98
    ;
99
  return tid;
100
}
101
102
int64_t Rip::AssignStreams (int64_t stream)
103
{
104
  NS_LOG_FUNCTION (this << stream);
105
106
  m_rng->SetStream (stream);
107
  return 1;
108
}
109
110
void Rip::DoInitialize ()
111
{
112
  NS_LOG_FUNCTION (this);
113
114
  bool addedGlobal = false;
115
116
  m_initialized = true;
117
118
  Time delay = m_unsolicitedUpdate + Seconds (m_rng->GetValue (0, 0.5*m_unsolicitedUpdate.GetSeconds ()) );
119
  m_nextUnsolicitedUpdate = Simulator::Schedule (delay, &Rip::SendUnsolicitedRouteUpdate, this);
120
121
122
  for (uint32_t i = 0 ; i < m_ipv4->GetNInterfaces (); i++)
123
    {
124
      Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice> (m_ipv4->GetNetDevice (i));
125
      if (check)
126
        {
127
          continue;
128
        }
129
130
      bool activeInterface = false;
131
      if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
132
        {
133
          activeInterface = true;
134
          m_ipv4->SetForwarding (i, true);
135
        }
136
137
      for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
138
        {
139
          Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
140
          if (address.GetScope() != Ipv4InterfaceAddress::HOST && activeInterface == true)
141
            {
142
              NS_LOG_LOGIC ("RIP: adding socket to " << address.GetLocal ());
143
              TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
144
              Ptr<Node> theNode = GetObject<Node> ();
145
              Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
146
              InetSocketAddress local = InetSocketAddress (address.GetLocal (), RIP_PORT);
147
              int ret = socket->Bind (local);
148
              NS_ASSERT_MSG (ret == 0, "Bind unsuccessful");
149
              socket->BindToNetDevice (m_ipv4->GetNetDevice (i));
150
              socket->SetIpRecvTtl (true);
151
              m_sendSocketList[socket] = i;
152
            }
153
          else if (m_ipv4->GetAddress (i, j).GetScope() == Ipv4InterfaceAddress::GLOBAL)
154
            {
155
              addedGlobal = true;
156
            }
157
        }
158
    }
159
160
  if (!m_recvSocket)
161
    {
162
      NS_LOG_LOGIC ("RIP: adding receiving socket");
163
      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
164
      Ptr<Node> theNode = GetObject<Node> ();
165
      m_recvSocket = Socket::CreateSocket (theNode, tid);
166
      InetSocketAddress local = InetSocketAddress (RIP_ALL_NODE, RIP_PORT);
167
      m_recvSocket->Bind (local);
168
      m_recvSocket->SetRecvCallback (MakeCallback (&Rip::Receive, this));
169
      m_recvSocket->SetIpRecvTtl (true);
170
      m_recvSocket->SetRecvPktInfo (true);
171
    }
172
173
174
  if (addedGlobal)
175
    {
176
      Time delay = Seconds (m_rng->GetValue (m_minTriggeredUpdateDelay.GetSeconds (), m_maxTriggeredUpdateDelay.GetSeconds ()));
177
      m_nextTriggeredUpdate = Simulator::Schedule (delay, &Rip::DoSendRouteUpdate, this, false);
178
    }
179
180
  delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ()));
181
  m_nextTriggeredUpdate = Simulator::Schedule (delay, &Rip::SendRouteRequest, this);
182
183
  Ipv4RoutingProtocol::DoInitialize ();
184
}
185
186
Ptr<Ipv4Route> Rip::RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr)
187
{
188
  NS_LOG_FUNCTION (this << header << oif);
189
190
  Ipv4Address destination = header.GetDestination ();
191
  Ptr<Ipv4Route> rtentry = 0;
192
193
  if (destination.IsMulticast ())
194
    {
195
      // Note:  Multicast routes for outbound packets are stored in the
196
      // normal unicast table.  An implication of this is that it is not
197
      // possible to source multicast datagrams on multiple interfaces.
198
      // This is a well-known property of sockets implementation on
199
      // many Unix variants.
200
      // So, we just log it and fall through to LookupStatic ()
201
      NS_LOG_LOGIC ("RouteOutput (): Multicast destination");
202
    }
203
204
  rtentry = Lookup (destination, oif);
205
  if (rtentry)
206
    {
207
      sockerr = Socket::ERROR_NOTERROR;
208
    }
209
  else
210
    {
211
      sockerr = Socket::ERROR_NOROUTETOHOST;
212
    }
213
  return rtentry;
214
}
215
216
bool Rip::RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
217
                        UnicastForwardCallback ucb, MulticastForwardCallback mcb,
218
                        LocalDeliverCallback lcb, ErrorCallback ecb)
219
{
220
  NS_LOG_FUNCTION (this << p << header << header.GetSource () << header.GetDestination () << idev);
221
222
  NS_ASSERT (m_ipv4 != 0);
223
  // Check if input device supports IP
224
  NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
225
  uint32_t iif = m_ipv4->GetInterfaceForDevice (idev);
226
  Ipv4Address dst = header.GetDestination ();
227
228
    if (m_ipv4->IsDestinationAddress (header.GetDestination (), iif))
229
    {
230
      if (!lcb.IsNull ())
231
        {
232
          NS_LOG_LOGIC ("Local delivery to " << header.GetDestination ());
233
          lcb (p, header, iif);
234
          return true;
235
        }
236
      else
237
        {
238
          // The local delivery callback is null.  This may be a multicast
239
          // or broadcast packet, so return false so that another
240
          // multicast routing protocol can handle it.  It should be possible
241
          // to extend this to explicitly check whether it is a unicast
242
          // packet, and invoke the error callback if so
243
          return false;
244
        }
245
    }
246
247
    if (dst.IsMulticast ())
248
      {
249
        NS_LOG_LOGIC ("Multicast route not supported by RIP");
250
        return false; // Let other routing protocols try to handle this
251
      }
252
253
  if (header.GetDestination ().IsBroadcast ())
254
    {
255
      NS_LOG_LOGIC ("Dropping packet not for me and with dst Broadcast");
256
      if (!ecb.IsNull ())
257
        {
258
          ecb (p, header, Socket::ERROR_NOROUTETOHOST);
259
        }
260
      return false;
261
    }
262
263
  // Check if input device supports IP forwarding
264
  if (m_ipv4->IsForwarding (iif) == false)
265
    {
266
      NS_LOG_LOGIC ("Forwarding disabled for this interface");
267
      if (!ecb.IsNull ())
268
        {
269
          ecb (p, header, Socket::ERROR_NOROUTETOHOST);
270
        }
271
      return false;
272
    }
273
  // Next, try to find a route
274
  NS_LOG_LOGIC ("Unicast destination");
275
  Ptr<Ipv4Route> rtentry = Lookup (header.GetDestination ());
276
277
  if (rtentry != 0)
278
    {
279
      NS_LOG_LOGIC ("Found unicast destination - calling unicast callback");
280
      ucb (rtentry, p, header);  // unicast forwarding callback
281
      return true;
282
    }
283
  else
284
    {
285
      NS_LOG_LOGIC ("Did not find unicast destination - returning false");
286
      return false; // Let other routing protocols try to handle this
287
    }
288
}
289
290
void Rip::NotifyInterfaceUp (uint32_t i)
291
{
292
  NS_LOG_FUNCTION (this << i);
293
294
  Ptr<LoopbackNetDevice> check = DynamicCast<LoopbackNetDevice> (m_ipv4->GetNetDevice (i));
295
  if (check)
296
    {
297
      return;
298
    }
299
300
  for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
301
    {
302
      Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
303
      Ipv4Mask networkMask = address.GetMask ();
304
      Ipv4Address networkAddress = address.GetLocal ().CombineMask (networkMask);
305
306
      if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
307
        {
308
          AddNetworkRouteTo (networkAddress, networkMask, i);
309
        }
310
    }
311
312
  if (!m_initialized)
313
    {
314
      return;
315
    }
316
317
318
  bool sendSocketFound = false;
319
  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
320
    {
321
      if (iter->second == i)
322
        {
323
          sendSocketFound = true;
324
          break;
325
        }
326
    }
327
328
  bool activeInterface = false;
329
  if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ())
330
    {
331
      activeInterface = true;
332
      m_ipv4->SetForwarding (i, true);
333
    }
334
335
  for (uint32_t j = 0; j < m_ipv4->GetNAddresses (i); j++)
336
    {
337
      Ipv4InterfaceAddress address = m_ipv4->GetAddress (i, j);
338
339
      if (address.GetScope() != Ipv4InterfaceAddress::HOST && sendSocketFound == false && activeInterface == true)
340
        {
341
          NS_LOG_LOGIC ("RIP: adding sending socket to " << address.GetLocal ());
342
          TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
343
          Ptr<Node> theNode = GetObject<Node> ();
344
          Ptr<Socket> socket = Socket::CreateSocket (theNode, tid);
345
          InetSocketAddress local = InetSocketAddress (address.GetLocal (), RIP_PORT);
346
          socket->Bind (local);
347
          socket->BindToNetDevice (m_ipv4->GetNetDevice (i));
348
          socket->SetIpRecvTtl (true);
349
          m_sendSocketList[socket] = i;
350
        }
351
      if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
352
        {
353
          SendTriggeredRouteUpdate ();
354
        }
355
    }
356
357
  if (!m_recvSocket)
358
    {
359
      NS_LOG_LOGIC ("RIP: adding receiving socket");
360
      TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
361
      Ptr<Node> theNode = GetObject<Node> ();
362
      m_recvSocket = Socket::CreateSocket (theNode, tid);
363
      InetSocketAddress local = InetSocketAddress (RIP_ALL_NODE, RIP_PORT);
364
      m_recvSocket->Bind (local);
365
      m_recvSocket->SetRecvCallback (MakeCallback (&Rip::Receive, this));
366
      m_recvSocket->SetIpRecvTtl (true);
367
      m_recvSocket->SetRecvPktInfo (true);
368
    }
369
}
370
371
void Rip::NotifyInterfaceDown (uint32_t interface)
372
{
373
  NS_LOG_FUNCTION (this << interface);
374
375
  /* remove all routes that are going through this interface */
376
  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
377
    {
378
      if (it->first->GetInterface () == interface)
379
        {
380
          InvalidateRoute (it->first);
381
        }
382
    }
383
384
  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
385
    {
386
      NS_LOG_INFO ("Checking socket for interface " << interface);
387
      if (iter->second == interface)
388
        {
389
          NS_LOG_INFO ("Removed socket for interface " << interface);
390
          iter->first->Close ();
391
          m_sendSocketList.erase (iter);
392
          break;
393
        }
394
    }
395
396
  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
397
    {
398
      SendTriggeredRouteUpdate ();
399
    }
400
}
401
402
void Rip::NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address)
403
{
404
  NS_LOG_FUNCTION (this << interface << address);
405
406
  if (!m_ipv4->IsUp (interface))
407
    {
408
      return;
409
    }
410
411
  if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ())
412
    {
413
      return;
414
    }
415
416
  Ipv4Address networkAddress = address.GetLocal ().CombineMask (address.GetMask ());
417
  Ipv4Mask networkMask = address.GetMask ();
418
419
  if (address.GetScope () == Ipv4InterfaceAddress::GLOBAL)
420
    {
421
      AddNetworkRouteTo (networkAddress, networkMask, interface);
422
    }
423
424
  SendTriggeredRouteUpdate ();
425
}
426
427
void Rip::NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address)
428
{
429
  NS_LOG_FUNCTION (this << interface << address);
430
431
  if (!m_ipv4->IsUp (interface))
432
    {
433
      return;
434
    }
435
436
  if (address.GetScope() != Ipv4InterfaceAddress::GLOBAL)
437
    {
438
      return;
439
    }
440
441
  Ipv4Address networkAddress = address.GetLocal ().CombineMask (address.GetMask ());
442
  Ipv4Mask networkMask = address.GetMask ();
443
444
  // Remove all routes that are going through this interface
445
  // which reference this network
446
  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
447
    {
448
      if (it->first->GetInterface () == interface
449
          && it->first->IsNetwork ()
450
          && it->first->GetDestNetwork () == networkAddress
451
          && it->first->GetDestNetworkMask () == networkMask)
452
        {
453
          InvalidateRoute (it->first);
454
        }
455
    }
456
457
  if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
458
    {
459
      SendTriggeredRouteUpdate ();
460
    }
461
462
}
463
464
void Rip::SetIpv4 (Ptr<Ipv4> ipv4)
465
{
466
  NS_LOG_FUNCTION (this << ipv4);
467
468
  NS_ASSERT (m_ipv4 == 0 && ipv4 != 0);
469
  uint32_t i = 0;
470
  m_ipv4 = ipv4;
471
472
  for (i = 0; i < m_ipv4->GetNInterfaces (); i++)
473
    {
474
      if (m_ipv4->IsUp (i))
475
        {
476
          NotifyInterfaceUp (i);
477
        }
478
      else
479
        {
480
          NotifyInterfaceDown (i);
481
        }
482
    }
483
}
484
485
void Rip::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
486
{
487
  NS_LOG_FUNCTION (this << stream);
488
489
  std::ostream* os = stream->GetStream ();
490
491
  *os << "Node: " << m_ipv4->GetObject<Node> ()->GetId ()
492
      << ", Time: " << Now().As (Time::S)
493
      << ", Local time: " << GetObject<Node> ()->GetLocalTime ().As (Time::S)
494
      << ", IPv4 RIP table" << std::endl;
495
496
  if (!m_routes.empty ())
497
    {
498
      *os << "Destination     Gateway         Genmask         Flags Metric Ref    Use Iface" << std::endl;
499
      for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++)
500
        {
501
          RipRoutingTableEntry* route = it->first;
502
          RipRoutingTableEntry::Status_e status = route->GetRouteStatus();
503
504
          if (status == RipRoutingTableEntry::RIP_VALID)
505
            {
506
              std::ostringstream dest, gw, mask, flags;
507
              dest << route->GetDest ();
508
              *os << std::setiosflags (std::ios::left) << std::setw (16) << dest.str ();
509
              gw << route->GetGateway ();
510
              *os << std::setiosflags (std::ios::left) << std::setw (16) << gw.str ();
511
              mask << route->GetDestNetworkMask ();
512
              *os << std::setiosflags (std::ios::left) << std::setw (16) << mask.str ();
513
              flags << "U";
514
              if (route->IsHost ())
515
                {
516
                  flags << "HS";
517
                }
518
              else if (route->IsGateway ())
519
                {
520
                  flags << "GS";
521
                }
522
              *os << std::setiosflags (std::ios::left) << std::setw (6) << flags.str ();
523
              *os << std::setiosflags (std::ios::left) << std::setw (7) << int(route->GetRouteMetric ());
524
              // Ref ct not implemented
525
              *os << "-" << "      ";
526
              // Use not implemented
527
              *os << "-" << "   ";
528
              if (Names::FindName (m_ipv4->GetNetDevice (route->GetInterface ())) != "")
529
                {
530
                  *os << Names::FindName (m_ipv4->GetNetDevice (route->GetInterface ()));
531
                }
532
              else
533
                {
534
                  *os << route->GetInterface ();
535
                }
536
              *os << std::endl;
537
            }
538
        }
539
    }
540
  *os << std::endl;
541
}
542
543
void Rip::DoDispose ()
544
{
545
  NS_LOG_FUNCTION (this);
546
547
  for (RoutesI j = m_routes.begin ();  j != m_routes.end (); j = m_routes.erase (j))
548
    {
549
      delete j->first;
550
    }
551
  m_routes.clear ();
552
553
  m_nextTriggeredUpdate.Cancel ();
554
  m_nextUnsolicitedUpdate.Cancel ();
555
  m_nextTriggeredUpdate = EventId ();
556
  m_nextUnsolicitedUpdate = EventId ();
557
558
  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
559
    {
560
      iter->first->Close ();
561
    }
562
  m_sendSocketList.clear ();
563
564
  m_recvSocket->Close ();
565
  m_recvSocket = 0;
566
567
  m_ipv4 = 0;
568
569
  Ipv4RoutingProtocol::DoDispose ();
570
}
571
572
573
Ptr<Ipv4Route> Rip::Lookup (Ipv4Address dst, Ptr<NetDevice> interface)
574
{
575
  NS_LOG_FUNCTION (this << dst << interface);
576
577
  Ptr<Ipv4Route> rtentry = 0;
578
  uint16_t longestMask = 0;
579
580
  /* when sending on local multicast, there have to be interface specified */
581
  if (dst.IsLocalMulticast ())
582
    {
583
      NS_ASSERT_MSG (interface, "Try to send on local multicast address, and no interface index is given!");
584
      rtentry = Create<Ipv4Route> ();
585
      rtentry->SetSource (m_ipv4->SourceAddressSelection (m_ipv4->GetInterfaceForDevice (interface), dst));
586
      rtentry->SetDestination (dst);
587
      rtentry->SetGateway (Ipv4Address::GetZero ());
588
      rtentry->SetOutputDevice (interface);
589
      return rtentry;
590
    }
591
592
  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
593
    {
594
      RipRoutingTableEntry* j = it->first;
595
596
      if (j->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID)
597
        {
598
          Ipv4Mask mask = j->GetDestNetworkMask ();
599
          uint16_t maskLen = mask.GetPrefixLength ();
600
          Ipv4Address entry = j->GetDestNetwork ();
601
602
          NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen);
603
604
          if (mask.IsMatch (dst, entry))
605
            {
606
              NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen);
607
608
              /* if interface is given, check the route will output on this interface */
609
              if (!interface || interface == m_ipv4->GetNetDevice (j->GetInterface ()))
610
                {
611
                  if (maskLen < longestMask)
612
                    {
613
                      NS_LOG_LOGIC ("Previous match longer, skipping");
614
                      continue;
615
                    }
616
617
                  longestMask = maskLen;
618
619
                  Ipv4RoutingTableEntry* route = j;
620
                  uint32_t interfaceIdx = route->GetInterface ();
621
                  rtentry = Create<Ipv4Route> ();
622
623
                  if (route->GetDest ().IsAny ()) /* default route */
624
                    {
625
                      rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetGateway ()));
626
                    }
627
                  else
628
                    {
629
                      rtentry->SetSource (m_ipv4->SourceAddressSelection (interfaceIdx, route->GetDest ()));
630
                    }
631
632
                  rtentry->SetDestination (route->GetDest ());
633
                  rtentry->SetGateway (route->GetGateway ());
634
                  rtentry->SetOutputDevice (m_ipv4->GetNetDevice (interfaceIdx));
635
                }
636
            }
637
        }
638
    }
639
640
  if (rtentry)
641
    {
642
      NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end");
643
    }
644
  return rtentry;
645
}
646
647
void Rip::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
648
{
649
  NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface);
650
651
  RipRoutingTableEntry* route = new RipRoutingTableEntry (network, networkPrefix, nextHop, interface);
652
  route->SetRouteMetric (1);
653
  route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
654
  route->SetRouteChanged (true);
655
656
  m_routes.push_back (std::make_pair (route, EventId ()));
657
}
658
659
void Rip::AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface)
660
{
661
  NS_LOG_FUNCTION (this << network << networkPrefix << interface);
662
663
  RipRoutingTableEntry* route = new RipRoutingTableEntry (network, networkPrefix, interface);
664
  route->SetRouteMetric (1);
665
  route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
666
  route->SetRouteChanged (true);
667
668
  m_routes.push_back (std::make_pair (route, EventId ()));
669
}
670
671
void Rip::InvalidateRoute (RipRoutingTableEntry *route)
672
{
673
  NS_LOG_FUNCTION (this << *route);
674
675
  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
676
    {
677
      if (it->first == route)
678
        {
679
          route->SetRouteStatus (RipRoutingTableEntry::RIP_INVALID);
680
          route->SetRouteMetric (m_linkDown);
681
          route->SetRouteChanged (true);
682
          if (it->second.IsRunning ())
683
            {
684
              it->second.Cancel ();
685
            }
686
          it->second = Simulator::Schedule (m_garbageCollectionDelay, &Rip::DeleteRoute, this, route);
687
          return;
688
        }
689
    }
690
  NS_ABORT_MSG ("RIP::InvalidateRoute - cannot find the route to update");
691
}
692
693
void Rip::DeleteRoute (RipRoutingTableEntry *route)
694
{
695
  NS_LOG_FUNCTION (this << *route);
696
697
  for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++)
698
    {
699
      if (it->first == route)
700
        {
701
          delete route;
702
          m_routes.erase (it);
703
          return;
704
        }
705
    }
706
  NS_ABORT_MSG ("RIP::DeleteRoute - cannot find the route to delete");
707
}
708
709
710
void Rip::Receive (Ptr<Socket> socket)
711
{
712
  NS_LOG_FUNCTION (this << socket);
713
714
  Ptr<Packet> packet = socket->Recv ();
715
  NS_LOG_INFO ("Received " << *packet);
716
717
  Ipv4PacketInfoTag interfaceInfo;
718
  if (!packet->RemovePacketTag (interfaceInfo))
719
    {
720
      NS_ABORT_MSG ("No incoming interface on RIP message, aborting.");
721
    }
722
  uint32_t incomingIf = interfaceInfo.GetRecvIf ();
723
  Ptr<Node> node = this->GetObject<Node> ();
724
  Ptr<NetDevice> dev = node->GetDevice (incomingIf);
725
  uint32_t ipInterfaceIndex = m_ipv4->GetInterfaceForDevice (dev);
726
727
  SocketIpTtlTag hoplimitTag;
728
  if (!packet->RemovePacketTag (hoplimitTag))
729
    {
730
      NS_ABORT_MSG ("No incoming Hop Count on RIP message, aborting.");
731
    }
732
  uint8_t hopLimit = hoplimitTag.GetTtl ();
733
734
  SocketAddressTag tag;
735
  if (!packet->RemovePacketTag (tag))
736
    {
737
      NS_ABORT_MSG ("No incoming sender address on RIP message, aborting.");
738
    }
739
  Ipv4Address senderAddress = InetSocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv4 ();
740
  uint16_t senderPort = InetSocketAddress::ConvertFrom (tag.GetAddress ()).GetPort ();
741
742
  int32_t interfaceForAddress = m_ipv4->GetInterfaceForAddress (senderAddress);
743
  if (interfaceForAddress != -1)
744
    {
745
      NS_LOG_LOGIC ("Ignoring a packet sent by myself.");
746
      return;
747
    }
748
749
  RipHeader hdr;
750
  packet->RemoveHeader (hdr);
751
752
  if (hdr.GetCommand () == RipHeader::RESPONSE)
753
    {
754
      HandleResponses (hdr, senderAddress, ipInterfaceIndex, hopLimit);
755
    }
756
  else if (hdr.GetCommand () == RipHeader::REQUEST)
757
    {
758
      HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit);
759
    }
760
  else
761
    {
762
      NS_LOG_LOGIC ("Ignoring message with unknown command: " << int (hdr.GetCommand ()));
763
    }
764
  return;
765
}
766
767
void Rip::HandleRequests (RipHeader requestHdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit)
768
{
769
  NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr);
770
771
  std::list<RipRte> rtes = requestHdr.GetRteList ();
772
773
  if (rtes.empty ())
774
    {
775
      return;
776
    }
777
778
  // check if it's a request for the full table from a neighbor
779
  if (rtes.size () == 1)
780
    {
781
      if (rtes.begin ()->GetPrefix () == Ipv4Address::GetAny () &&
782
          rtes.begin ()->GetSubnetMask ().GetPrefixLength () == 0 &&
783
          rtes.begin ()->GetRouteMetric () == m_linkDown)
784
        {
785
          // Output whole thing. Use Split Horizon
786
          if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ())
787
            {
788
              // we use one of the sending sockets, as they're bound to the right interface
789
              // and the local address might be used on different interfaces.
790
              Ptr<Socket> sendingSoket;
791
              for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
792
                {
793
                  if (iter->second == incomingInterface)
794
                    {
795
                      sendingSoket = iter->first;
796
                    }
797
                }
798
              NS_ASSERT_MSG (sendingSoket, "HandleRequest - Impossible to find a socket to send the reply");
799
800
              uint16_t mtu = m_ipv4->GetMtu (incomingInterface);
801
              uint16_t maxRte = (mtu - Ipv4Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipHeader ().GetSerializedSize ()) / RipRte ().GetSerializedSize ();
802
803
              Ptr<Packet> p = Create<Packet> ();
804
              SocketIpTtlTag tag;
805
              p->RemovePacketTag (tag);
806
              if (senderAddress == Ipv4Address(RIP_ALL_NODE))
807
                {
808
                  tag.SetTtl (1);
809
                }
810
              else
811
                {
812
                  tag.SetTtl (255);
813
                }
814
              p->AddPacketTag (tag);
815
816
              RipHeader hdr;
817
              hdr.SetCommand (RipHeader::RESPONSE);
818
819
              for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
820
                {
821
                  bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface);
822
823
                  Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
824
825
                  bool isGlobal = (rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL);
826
                  bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv4Address::GetAny ()) &&
827
                      (rtIter->first->GetDestNetworkMask () == Ipv4Mask::GetZero ()) &&
828
                      (rtIter->first->GetInterface () != incomingInterface));
829
830
                  if ((isGlobal || isDefaultRoute) &&
831
                      (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID) )
832
                    {
833
                      RipRte rte;
834
                      rte.SetPrefix (rtIter->first->GetDestNetwork ());
835
                      rte.SetSubnetMask (rtIter->first->GetDestNetworkMask ());
836
                      if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
837
                        {
838
                          rte.SetRouteMetric (m_linkDown);
839
                        }
840
                      else
841
                        {
842
                          rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
843
                        }
844
                      rte.SetRouteTag (rtIter->first->GetRouteTag ());
845
                      if ((m_splitHorizonStrategy != SPLIT_HORIZON) ||
846
                          (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning))
847
                        {
848
                          hdr.AddRte (rte);
849
                        }
850
                    }
851
                  if (hdr.GetRteNumber () == maxRte)
852
                    {
853
                      p->AddHeader (hdr);
854
                      NS_LOG_DEBUG ("SendTo: " << *p);
855
                      sendingSoket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
856
                      p->RemoveHeader (hdr);
857
                      hdr.ClearRtes ();
858
                    }
859
                }
860
              if (hdr.GetRteNumber () > 0)
861
                {
862
                  p->AddHeader (hdr);
863
                  NS_LOG_DEBUG ("SendTo: " << *p);
864
                  sendingSoket->SendTo (p, 0, InetSocketAddress (senderAddress, RIP_PORT));
865
                }
866
            }
867
        }
868
    }
869
  else
870
    {
871
      // note: we got the request as a single packet, so no check is necessary for MTU limit
872
873
      Ptr<Packet> p = Create<Packet> ();
874
      SocketIpTtlTag tag;
875
      p->RemovePacketTag (tag);
876
      if (senderAddress == Ipv4Address(RIP_ALL_NODE))
877
        {
878
          tag.SetTtl (1);
879
        }
880
      else
881
        {
882
          tag.SetTtl (255);
883
        }
884
      p->AddPacketTag (tag);
885
886
      RipHeader hdr;
887
      hdr.SetCommand (RipHeader::RESPONSE);
888
889
      for (std::list<RipRte>::iterator iter = rtes.begin ();
890
          iter != rtes.end (); iter++)
891
        {
892
          bool found = false;
893
          for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
894
            {
895
896
              Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress (rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
897
              if ((rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL) &&
898
                  (rtIter->first->GetRouteStatus () == RipRoutingTableEntry::RIP_VALID))
899
                {
900
                  Ipv4Address requestedAddress = iter->GetPrefix ();
901
                  requestedAddress.CombineMask (iter->GetSubnetMask ());
902
                  Ipv4Address rtAddress = rtIter->first->GetDestNetwork ();
903
                  rtAddress.CombineMask (rtIter->first->GetDestNetworkMask ());
904
905
                  if (requestedAddress == rtAddress)
906
                    {
907
                      iter->SetRouteMetric (rtIter->first->GetRouteMetric ());
908
                      iter->SetRouteTag (rtIter->first->GetRouteTag ());
909
                      hdr.AddRte (*iter);
910
                      found = true;
911
                      break;
912
                    }
913
                }
914
            }
915
          if (!found)
916
            {
917
              iter->SetRouteMetric (m_linkDown);
918
              iter->SetRouteTag (0);
919
              hdr.AddRte (*iter);
920
            }
921
        }
922
      p->AddHeader (hdr);
923
      NS_LOG_DEBUG ("SendTo: " << *p);
924
      m_recvSocket->SendTo (p, 0, InetSocketAddress (senderAddress, senderPort));
925
    }
926
927
}
928
929
void Rip::HandleResponses (RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit)
930
{
931
  NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr);
932
933
  if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ())
934
    {
935
      NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface);
936
      return;
937
    }
938
939
  std::list<RipRte> rtes = hdr.GetRteList ();
940
941
  // validate the RTEs before processing
942
  for (std::list<RipRte>::iterator iter = rtes.begin ();
943
      iter != rtes.end (); iter++)
944
    {
945
      if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > m_linkDown)
946
        {
947
          NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ()));
948
          return;
949
        }
950
      if (iter->GetPrefix ().IsLocalhost () ||
951
          iter->GetPrefix ().IsBroadcast () ||
952
          iter->GetPrefix ().IsMulticast ())
953
        {
954
          NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ());
955
          return;
956
        }
957
    }
958
959
  bool changed = false;
960
961
  for (std::list<RipRte>::iterator iter = rtes.begin ();
962
      iter != rtes.end (); iter++)
963
    {
964
      Ipv4Mask rtePrefixMask = iter->GetSubnetMask ();
965
      Ipv4Address rteAddr = iter->GetPrefix ().CombineMask (rtePrefixMask);
966
967
      NS_LOG_LOGIC ("Processing RTE " << *iter);
968
969
      uint32_t interfaceMetric = 1;
970
      if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ())
971
        {
972
          interfaceMetric = m_interfaceMetrics[incomingInterface];
973
        }
974
      uint64_t rteMetric = iter->GetRouteMetric () + interfaceMetric;
975
      if (rteMetric > m_linkDown)
976
        {
977
          rteMetric = m_linkDown;
978
        }
979
980
      RoutesI it;
981
      bool found = false;
982
      for (it = m_routes.begin (); it != m_routes.end (); it++)
983
        {
984
          if (it->first->GetDestNetwork () == rteAddr &&
985
              it->first->GetDestNetworkMask () == rtePrefixMask)
986
            {
987
              found = true;
988
              if (rteMetric < it->first->GetRouteMetric ())
989
                {
990
                  if (senderAddress != it->first->GetGateway ())
991
                    {
992
                      RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
993
                      delete it->first;
994
                      it->first = route;
995
                    }
996
                  it->first->SetRouteMetric (rteMetric);
997
                  it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
998
                  it->first->SetRouteTag (iter->GetRouteTag ());
999
                  it->first->SetRouteChanged (true);
1000
                  it->second.Cancel ();
1001
                  it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1002
                  changed = true;
1003
                }
1004
              else if (rteMetric == it->first->GetRouteMetric ())
1005
                {
1006
                  if (senderAddress == it->first->GetGateway ())
1007
                    {
1008
                      it->second.Cancel ();
1009
                      it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1010
                    }
1011
                  else
1012
                    {
1013
                      if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2)
1014
                        {
1015
                          RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1016
                          route->SetRouteMetric (rteMetric);
1017
                          route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
1018
                          route->SetRouteTag (iter->GetRouteTag ());
1019
                          route->SetRouteChanged (true);
1020
                          delete it->first;
1021
                          it->first = route;
1022
                          it->second.Cancel ();
1023
                          it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
1024
                          changed = true;
1025
                        }
1026
                    }
1027
                }
1028
              else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ())
1029
                {
1030
                  it->second.Cancel ();
1031
                  if (rteMetric < m_linkDown)
1032
                    {
1033
                      it->first->SetRouteMetric (rteMetric);
1034
                      it->first->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
1035
                      it->first->SetRouteTag (iter->GetRouteTag ());
1036
                      it->first->SetRouteChanged (true);
1037
                      it->second.Cancel ();
1038
                      it->second = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, it->first);
1039
                    }
1040
                  else
1041
                    {
1042
                      InvalidateRoute (it->first);
1043
                    }
1044
                  changed = true;
1045
                }
1046
            }
1047
        }
1048
      if (!found && rteMetric != m_linkDown)
1049
        {
1050
          NS_LOG_LOGIC ("Received a RTE with new route, adding.");
1051
1052
          RipRoutingTableEntry* route = new RipRoutingTableEntry (rteAddr, rtePrefixMask, senderAddress, incomingInterface);
1053
          route->SetRouteMetric (rteMetric);
1054
          route->SetRouteStatus (RipRoutingTableEntry::RIP_VALID);
1055
          route->SetRouteChanged (true);
1056
          m_routes.push_front (std::make_pair (route, EventId ()));
1057
          EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &Rip::InvalidateRoute, this, route);
1058
          (m_routes.begin ())->second = invalidateEvent;
1059
          changed = true;
1060
        }
1061
    }
1062
1063
  if (changed)
1064
    {
1065
      SendTriggeredRouteUpdate ();
1066
    }
1067
}
1068
1069
void Rip::DoSendRouteUpdate (bool periodic)
1070
{
1071
  NS_LOG_FUNCTION (this << (periodic ? " periodic" : " triggered"));
1072
1073
  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1074
    {
1075
      uint32_t interface = iter->second;
1076
1077
      if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1078
        {
1079
          uint16_t mtu = m_ipv4->GetMtu (interface);
1080
          uint16_t maxRte = (mtu - Ipv4Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipHeader ().GetSerializedSize ()) / RipRte ().GetSerializedSize ();
1081
1082
          Ptr<Packet> p = Create<Packet> ();
1083
          SocketIpTtlTag tag;
1084
          tag.SetTtl (1);
1085
          p->AddPacketTag (tag);
1086
1087
          RipHeader hdr;
1088
          hdr.SetCommand (RipHeader::RESPONSE);
1089
1090
          for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1091
            {
1092
              bool splitHorizoning = (rtIter->first->GetInterface () == interface);
1093
              Ipv4InterfaceAddress rtDestAddr = Ipv4InterfaceAddress(rtIter->first->GetDestNetwork (), rtIter->first->GetDestNetworkMask ());
1094
1095
              NS_LOG_DEBUG ("Processing RT " << rtDestAddr << " " << int(rtIter->first->IsRouteChanged ()));
1096
1097
              bool isGlobal = (rtDestAddr.GetScope () == Ipv4InterfaceAddress::GLOBAL);
1098
              bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv4Address::GetAny ()) &&
1099
                  (rtIter->first->GetDestNetworkMask () == Ipv4Mask::GetZero ()) &&
1100
                  (rtIter->first->GetInterface () != interface));
1101
1102
              bool sameNetwork = false;
1103
              for (uint32_t index = 0; index < m_ipv4->GetNAddresses (interface); index++)
1104
                {
1105
                  Ipv4InterfaceAddress addr = m_ipv4->GetAddress (interface, index);
1106
                  if (addr.GetLocal ().CombineMask (addr.GetMask ()) == rtIter->first->GetDestNetwork ())
1107
                    {
1108
                      sameNetwork = true;
1109
                    }
1110
                }
1111
1112
              if ((isGlobal || isDefaultRoute) &&
1113
                  (periodic || rtIter->first->IsRouteChanged ()) &&
1114
                  !sameNetwork)
1115
                {
1116
                  RipRte rte;
1117
                  rte.SetPrefix (rtIter->first->GetDestNetwork ());
1118
                  rte.SetSubnetMask (rtIter->first->GetDestNetworkMask ());
1119
                  if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning)
1120
                    {
1121
                      rte.SetRouteMetric (m_linkDown);
1122
                    }
1123
                  else
1124
                    {
1125
                      rte.SetRouteMetric (rtIter->first->GetRouteMetric ());
1126
                    }
1127
                  rte.SetRouteTag (rtIter->first->GetRouteTag ());
1128
                  if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)
1129
                    {
1130
                      hdr.AddRte (rte);
1131
                    }
1132
                  else if (m_splitHorizonStrategy != SPLIT_HORIZON)
1133
                    {
1134
                      hdr.AddRte (rte);
1135
                    }
1136
                }
1137
              if (hdr.GetRteNumber () == maxRte)
1138
                {
1139
                  p->AddHeader (hdr);
1140
                  NS_LOG_DEBUG ("SendTo: " << *p);
1141
                  iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1142
                  p->RemoveHeader (hdr);
1143
                  hdr.ClearRtes ();
1144
                }
1145
            }
1146
          if (hdr.GetRteNumber () > 0)
1147
            {
1148
              p->AddHeader (hdr);
1149
              NS_LOG_DEBUG ("SendTo: " << *p);
1150
              iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1151
            }
1152
        }
1153
    }
1154
  for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++)
1155
    {
1156
      rtIter->first->SetRouteChanged (false);
1157
    }
1158
}
1159
1160
void Rip::SendTriggeredRouteUpdate ()
1161
{
1162
  NS_LOG_FUNCTION (this);
1163
1164
  if (m_nextTriggeredUpdate.IsRunning())
1165
    {
1166
      NS_LOG_LOGIC ("Skipping Triggered Update due to cooldown");
1167
      return;
1168
    }
1169
1170
  // DoSendRouteUpdate (false);
1171
1172
  // note: The RFC states:
1173
  //     After a triggered
1174
  //     update is sent, a timer should be set for a random interval between 1
1175
  //     and 5 seconds.  If other changes that would trigger updates occur
1176
  //     before the timer expires, a single update is triggered when the timer
1177
  //     expires.  The timer is then reset to another random value between 1
1178
  //     and 5 seconds.  Triggered updates may be suppressed if a regular
1179
  //     update is due by the time the triggered update would be sent.
1180
  // Here we rely on this:
1181
  // When an update occurs (either Triggered or Periodic) the "IsChanged ()"
1182
  // route field will be cleared.
1183
  // Hence, the following Triggered Update will be fired, but will not send
1184
  // any route update.
1185
1186
  Time delay = Seconds (m_rng->GetValue (m_minTriggeredUpdateDelay.GetSeconds (), m_maxTriggeredUpdateDelay.GetSeconds ()));
1187
  m_nextTriggeredUpdate = Simulator::Schedule (delay, &Rip::DoSendRouteUpdate, this, false);
1188
}
1189
1190
void Rip::SendUnsolicitedRouteUpdate ()
1191
{
1192
  NS_LOG_FUNCTION (this);
1193
1194
  if (m_nextTriggeredUpdate.IsRunning())
1195
    {
1196
      m_nextTriggeredUpdate.Cancel ();
1197
    }
1198
1199
  DoSendRouteUpdate (true);
1200
1201
  Time delay = m_unsolicitedUpdate + Seconds (m_rng->GetValue (0, 0.5*m_unsolicitedUpdate.GetSeconds ()) );
1202
  m_nextUnsolicitedUpdate = Simulator::Schedule (delay, &Rip::SendUnsolicitedRouteUpdate, this);
1203
}
1204
1205
std::set<uint32_t> Rip::GetInterfaceExclusions () const
1206
{
1207
  return m_interfaceExclusions;
1208
}
1209
1210
void Rip::SetInterfaceExclusions (std::set<uint32_t> exceptions)
1211
{
1212
  NS_LOG_FUNCTION (this);
1213
1214
  m_interfaceExclusions = exceptions;
1215
}
1216
1217
uint8_t Rip::GetInterfaceMetric (uint32_t interface) const
1218
{
1219
  NS_LOG_FUNCTION (this << interface);
1220
1221
  std::map<uint32_t, uint8_t>::const_iterator iter = m_interfaceMetrics.find (interface);
1222
  if (iter != m_interfaceMetrics.end ())
1223
    {
1224
      return iter->second;
1225
    }
1226
  return 1;
1227
}
1228
1229
void Rip::SetInterfaceMetric (uint32_t interface, uint8_t metric)
1230
{
1231
  NS_LOG_FUNCTION (this << interface << int (metric));
1232
1233
  if (metric < m_linkDown)
1234
    {
1235
      m_interfaceMetrics[interface] = metric;
1236
    }
1237
}
1238
1239
void Rip::SendRouteRequest ()
1240
{
1241
  NS_LOG_FUNCTION (this);
1242
1243
  Ptr<Packet> p = Create<Packet> ();
1244
  SocketIpTtlTag tag;
1245
  p->RemovePacketTag (tag);
1246
  tag.SetTtl (1);
1247
  p->AddPacketTag (tag);
1248
1249
  RipHeader hdr;
1250
  hdr.SetCommand (RipHeader::REQUEST);
1251
1252
  RipRte rte;
1253
  rte.SetPrefix (Ipv4Address::GetAny ());
1254
  rte.SetSubnetMask (Ipv4Mask::GetZero ());
1255
  rte.SetRouteMetric (m_linkDown);
1256
1257
  hdr.AddRte (rte);
1258
  p->AddHeader (hdr);
1259
1260
  for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ )
1261
    {
1262
      uint32_t interface = iter->second;
1263
1264
      if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ())
1265
        {
1266
          NS_LOG_DEBUG ("SendTo: " << *p);
1267
          iter->first->SendTo (p, 0, InetSocketAddress (RIP_ALL_NODE, RIP_PORT));
1268
        }
1269
    }
1270
}
1271
1272
void Rip::AddDefaultRouteTo (Ipv4Address nextHop, uint32_t interface)
1273
{
1274
  NS_LOG_FUNCTION (this << interface);
1275
1276
  AddNetworkRouteTo (Ipv4Address ("0.0.0.0"), Ipv4Mask::GetZero (), nextHop, interface);
1277
}
1278
1279
1280
/*
1281
 * RipRoutingTableEntry
1282
 */
1283
1284
RipRoutingTableEntry::RipRoutingTableEntry ()
1285
  : m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1286
{
1287
}
1288
1289
RipRoutingTableEntry::RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface)
1290
  : Ipv4RoutingTableEntry ( Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface) ),
1291
    m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1292
{
1293
}
1294
1295
RipRoutingTableEntry::RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface)
1296
  : Ipv4RoutingTableEntry ( Ipv4RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface) ),
1297
    m_tag (0), m_metric (0), m_status (RIP_INVALID), m_changed (false)
1298
{
1299
}
1300
1301
RipRoutingTableEntry::~RipRoutingTableEntry ()
1302
{
1303
}
1304
1305
1306
void RipRoutingTableEntry::SetRouteTag (uint16_t routeTag)
1307
{
1308
  if (m_tag != routeTag)
1309
    {
1310
      m_tag = routeTag;
1311
      m_changed = true;
1312
    }
1313
}
1314
1315
uint16_t RipRoutingTableEntry::GetRouteTag () const
1316
{
1317
  return m_tag;
1318
}
1319
1320
void RipRoutingTableEntry::SetRouteMetric (uint8_t routeMetric)
1321
{
1322
  if (m_metric != routeMetric)
1323
    {
1324
      m_metric = routeMetric;
1325
      m_changed = true;
1326
    }
1327
}
1328
1329
uint8_t RipRoutingTableEntry::GetRouteMetric () const
1330
{
1331
  return m_metric;
1332
}
1333
1334
void RipRoutingTableEntry::SetRouteStatus (Status_e status)
1335
{
1336
  if (m_status != status)
1337
    {
1338
      m_status = status;
1339
      m_changed = true;
1340
    }
1341
}
1342
1343
RipRoutingTableEntry::Status_e RipRoutingTableEntry::GetRouteStatus (void) const
1344
{
1345
  return m_status;
1346
}
1347
1348
void RipRoutingTableEntry::SetRouteChanged (bool changed)
1349
{
1350
  m_changed = changed;
1351
}
1352
1353
bool RipRoutingTableEntry::IsRouteChanged (void) const
1354
{
1355
  return m_changed;
1356
}
1357
1358
1359
std::ostream & operator << (std::ostream& os, const RipRoutingTableEntry& rte)
1360
{
1361
  os << static_cast<const Ipv4RoutingTableEntry &>(rte);
1362
  os << ", metric: " << int (rte.GetRouteMetric ()) << ", tag: " << int (rte.GetRouteTag ());
1363
1364
  return os;
1365
}
1366
1367
1368
}
1369
(-)a/src/internet/model/rip.h (+409 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze, Italy
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#ifndef RIP_H
22
#define RIP_H
23
24
#include <list>
25
26
#include "ns3/ipv4-routing-protocol.h"
27
#include "ns3/ipv4-interface.h"
28
#include "ns3/inet-socket-address.h"
29
#include "ns3/ipv4-l3-protocol.h"
30
#include "ns3/ipv4-routing-table-entry.h"
31
#include "ns3/random-variable-stream.h"
32
#include "ns3/rip-header.h"
33
34
namespace ns3 {
35
36
/**
37
 * \defgroup rip RIP
38
 *
39
 * The RIP protocol (\RFC{2453}) is a unicast-only IPv4 IGP (Interior Gateway Protocol).
40
 * Its convergence time is rather long. As a consequence, it is suggested to
41
 * carefully check the network topology and the route status before sending
42
 * data flows.
43
 *
44
 * RIP implements the Bellman-Ford algorithm (although the RFC does not state it).
45
 * Bellman-Ford algorithm convergence time is O(|V|*|E|) where |V| and |E| are the
46
 * number of vertices (routers) and edges (links) respectively. Since unsolicited
47
 * updates are exchanged every 30 seconds, the convergence might require a long time.
48
 *
49
 * For the RIP protocol, the exact convergence time is shorter, thanks to the
50
 * use of triggered updates, which are sent when a route changes.
51
 * Even with triggered updates, the convergence is in the order of magnitude of
52
 * O(|V|*|E|) * 5 seconds, which is still quite long for complex topologies.
53
 *
54
 * \todo: Add routing table compression (CIDR). The most evident result: without
55
 * it a router will announce to be the default router *and* more RTEs, which is silly.
56
 */
57
58
/**
59
 * \ingroup rip
60
 * \brief Rip Routing Table Entry
61
 */
62
class RipRoutingTableEntry : public Ipv4RoutingTableEntry
63
{
64
public:
65
66
  /**
67
   * Route status
68
   */
69
  enum Status_e {
70
    RIP_VALID,
71
    RIP_INVALID,
72
  };
73
74
  RipRoutingTableEntry (void);
75
76
  /**
77
   * \brief Constructor
78
   * \param network network address
79
   * \param networkPrefix network prefix
80
   * \param nextHop next hop address to route the packet
81
   * \param interface interface index
82
   */
83
  RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface);
84
85
  /**
86
   * \brief Constructor
87
   * \param network network address
88
   * \param networkPrefix network prefix
89
   * \param interface interface index
90
   */
91
  RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface);
92
93
  virtual ~RipRoutingTableEntry ();
94
95
  /**
96
   * \brief Set the route tag
97
   * \param routeTag the route tag
98
   */
99
  void SetRouteTag (uint16_t routeTag);
100
101
  /**
102
   * \brief Get the route tag
103
   * \returns the route tag
104
   */
105
  uint16_t GetRouteTag (void) const;
106
107
  /**
108
   * \brief Set the route metric
109
   * \param routeMetric the route metric
110
   */
111
  void SetRouteMetric (uint8_t routeMetric);
112
113
  /**
114
   * \brief Get the route metric
115
   * \returns the route metric
116
   */
117
  uint8_t GetRouteMetric (void) const;
118
119
  /**
120
   * \brief Set the route status
121
   * \param status the route status
122
   */
123
  void SetRouteStatus (Status_e status);
124
125
  /**
126
   * \brief Get the route status
127
   * \returns the route status
128
   */
129
  Status_e GetRouteStatus (void) const;
130
131
  /**
132
   * \brief Set the route as changed
133
   *
134
   * The changed routes are scheduled for a Triggered Update.
135
   * After a Triggered Update, all the changed flags are cleared
136
   * from the routing table.
137
   *
138
   * \param changed true if route is changed
139
   */
140
  void SetRouteChanged (bool changed);
141
142
  /**
143
   * \brief Get the route changed status
144
   *
145
   * \returns true if route is changed
146
   */
147
  bool IsRouteChanged (void) const;
148
149
private:
150
  uint16_t m_tag; //!< route tag
151
  uint8_t m_metric; //!< route metric
152
  Status_e m_status; //!< route status
153
  bool m_changed; //!< route has been updated
154
};
155
156
/**
157
 * \brief Stream insertion operator.
158
 *
159
 * \param os the reference to the output stream
160
 * \param route the Ipv4 routing table entry
161
 * \returns the reference to the output stream
162
 */
163
std::ostream& operator<< (std::ostream& os, RipRoutingTableEntry const& route);
164
165
166
167
/**
168
 * \ingroup rip
169
 *
170
 * \brief RIP Routing Protocol, defined in \RFC{2453}.
171
 */
172
class Rip : public Ipv4RoutingProtocol
173
{
174
public:
175
  // /< C-tor
176
  Rip ();
177
  virtual ~Rip ();
178
179
  /**
180
   * \brief Get the type ID
181
   * \return type ID
182
   */
183
  static TypeId GetTypeId (void);
184
185
  // From Ipv4RoutingProtocol
186
  Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif,
187
                              Socket::SocketErrno &sockerr);
188
  bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
189
                   UnicastForwardCallback ucb, MulticastForwardCallback mcb,
190
                   LocalDeliverCallback lcb, ErrorCallback ecb);
191
  virtual void NotifyInterfaceUp (uint32_t interface);
192
  virtual void NotifyInterfaceDown (uint32_t interface);
193
  virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
194
  virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
195
  virtual void SetIpv4 (Ptr<Ipv4> ipv4);
196
  virtual void PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const;
197
198
  /**
199
   * Split Horizon strategy type. See \RFC{2453}.
200
   */
201
  enum SplitHorizonType_e {
202
    NO_SPLIT_HORIZON,//!< No Split Horizon
203
    SPLIT_HORIZON,   //!< Split Horizon
204
    POISON_REVERSE,  //!< Poison Reverse Split Horizon
205
  };
206
207
  /**
208
   * Assign a fixed random variable stream number to the random variables
209
   * used by this model.  Return the number of streams (possibly zero) that
210
   * have been assigned.
211
   *
212
   * \param stream first stream index to use
213
   * \return the number of stream indices assigned by this model
214
   */
215
  int64_t AssignStreams (int64_t stream);
216
217
  /**
218
   * \brief Get the set of interface excluded from the protocol
219
   * \return the set of excluded interfaces
220
   */
221
  std::set<uint32_t> GetInterfaceExclusions () const;
222
223
  /**
224
   * \brief Set the set of interface excluded from the protocol
225
   * \param exceptions the set of excluded interfaces
226
   */
227
  void SetInterfaceExclusions (std::set<uint32_t> exceptions);
228
229
  /**
230
   * \brief Get the metric for an interface
231
   * \param interface the interface
232
   * \returns the interface metric
233
   */
234
  uint8_t GetInterfaceMetric (uint32_t interface) const;
235
236
  /**
237
   * \brief Set the metric for an interface
238
   * \param interface the interface
239
   * \param metric the interface metric
240
   */
241
  void SetInterfaceMetric (uint32_t interface, uint8_t metric);
242
243
  /**
244
   * \brief Add a default route to the router through the nextHop located on interface.
245
   *
246
   * The default route is usually installed manually, or it is the result of
247
   * some "other" routing protocol (e.g., BGP).
248
   *
249
   * \param nextHop the next hop
250
   * \param interface the interface
251
   */
252
  void AddDefaultRouteTo (Ipv4Address nextHop, uint32_t interface);
253
254
protected:
255
  /**
256
   * \brief Dispose this object.
257
   */
258
  virtual void DoDispose ();
259
260
  /**
261
   * Start protocol operation
262
   */
263
  void DoInitialize ();
264
265
private:
266
  /// Container for the network routes - pair RipRoutingTableEntry *, EventId (update event)
267
  typedef std::list<std::pair <RipRoutingTableEntry *, EventId> > Routes;
268
269
  /// Const Iterator for container for the network routes
270
  typedef std::list<std::pair <RipRoutingTableEntry *, EventId> >::const_iterator RoutesCI;
271
272
  /// Iterator for container for the network routes
273
  typedef std::list<std::pair <RipRoutingTableEntry *, EventId> >::iterator RoutesI;
274
275
276
  /**
277
   * \brief Receive RIP packets.
278
   *
279
   * \param socket the socket the packet was received to.
280
   */
281
  void Receive (Ptr<Socket> socket);
282
283
  /**
284
   * \brief Handle RIP requests.
285
   *
286
   * \param hdr message header (including RTEs)
287
   * \param senderAddress sender address
288
   * \param senderPort sender port
289
   * \param incomingInterface incoming interface
290
   * \param hopLimit packet's hop limit
291
   */
292
  void HandleRequests (RipHeader hdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit);
293
294
  /**
295
   * \brief Handle RIP responses.
296
   *
297
   * \param hdr message header (including RTEs)
298
   * \param senderAddress sender address
299
   * \param incomingInterface incoming interface
300
   * \param hopLimit packet's hop limit
301
   */
302
  void HandleResponses (RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit);
303
304
  /**
305
   * \brief Lookup in the forwarding table for destination.
306
   * \param dest destination address
307
   * \param interface output interface if any (put 0 otherwise)
308
   * \return Ipv4Route to route the packet to reach dest address
309
   */
310
  Ptr<Ipv4Route> Lookup (Ipv4Address dest, Ptr<NetDevice> = 0);
311
312
  /**
313
   * Receive and process unicast packet
314
   * \param socket socket where packet is arrived
315
   */
316
  void RecvUnicastRip (Ptr<Socket> socket);
317
  /**
318
   * Receive and process multicast packet
319
   * \param socket socket where packet is arrived
320
   */
321
  void RecvMulticastRip (Ptr<Socket> socket);
322
323
  /**
324
   * \brief Add route to network.
325
   * \param network network address
326
   * \param networkPrefix network prefix
327
   * \param nextHop next hop address to route the packet.
328
   * \param interface interface index
329
   */
330
  void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface);
331
332
  /**
333
   * \brief Add route to network.
334
   * \param network network address
335
   * \param networkPrefix network prefix
336
   * \param interface interface index
337
   */
338
  void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface);
339
340
  /**
341
   * \brief Send Routing Updates on all interfaces.
342
   */
343
  void DoSendRouteUpdate (bool periodic);
344
345
  /**
346
   * \brief Send Routing Request on all interfaces.
347
   */
348
  void SendRouteRequest ();
349
350
  /**
351
   * \brief Send Triggered Routing Updates on all interfaces.
352
   */
353
  void SendTriggeredRouteUpdate ();
354
355
  /**
356
   * \brief Send Unsolicited Routing Updates on all interfaces.
357
   */
358
  void SendUnsolicitedRouteUpdate (void);
359
360
  /**
361
   * \brief Invalidate a route.
362
   * \param route the route to be removed
363
   */
364
  void InvalidateRoute (RipRoutingTableEntry *route);
365
366
  /**
367
   * \brief Delete a route.
368
   * \param route the route to be removed
369
   */
370
  void DeleteRoute (RipRoutingTableEntry *route);
371
372
  Routes m_routes; //!<  the forwarding table for network.
373
  Ptr<Ipv4> m_ipv4; //!< IPv4 reference
374
  Time m_startupDelay; //!< Random delay before protocol startup.
375
  Time m_minTriggeredUpdateDelay; //!< Min cooldown delay after a Triggered Update.
376
  Time m_maxTriggeredUpdateDelay; //!< Max cooldown delay after a Triggered Update.
377
  Time m_unsolicitedUpdate; //!< time between two Unsolicited Routing Updates
378
  Time m_timeoutDelay; //!< Delay before invalidating a route
379
  Time m_garbageCollectionDelay; //!< Delay before deleting an INVALID route
380
381
  // note: we can not trust the result of socket->GetBoundNetDevice ()->GetIfIndex ();
382
  // it is dependent on the interface initialization (i.e., if the loopback is already up).
383
  /// Socket list type
384
  typedef std::map< Ptr<Socket>, uint32_t> SocketList;
385
  /// Socket list type iterator
386
  typedef std::map<Ptr<Socket>, uint32_t>::iterator SocketListI;
387
  /// Socket list type const iterator
388
  typedef std::map<Ptr<Socket>, uint32_t>::const_iterator SocketListCI;
389
390
  SocketList m_sendSocketList; //!< list of sockets for sending (socket, interface index)
391
  Ptr<Socket> m_recvSocket; //!< receive socket
392
393
  EventId m_nextUnsolicitedUpdate; //!< Next Unsolicited Update event
394
  EventId m_nextTriggeredUpdate; //!< Next Triggered Update event
395
396
  Ptr<UniformRandomVariable> m_rng; //!< Rng stream.
397
398
  std::set<uint32_t> m_interfaceExclusions; //!< Set of excluded interfaces
399
  std::map<uint32_t, uint8_t> m_interfaceMetrics; //!< Map of interface metrics
400
401
  SplitHorizonType_e m_splitHorizonStrategy; //!< Split Horizon strategy
402
403
  bool m_initialized; //!< flag to allow socket's late-creation.
404
  uint32_t m_linkDown; //!< Link down value.
405
};
406
407
} // namespace ns3
408
#endif /* RIP_H */
409
(-)a/src/internet/test/ipv4-rip-test.cc (+647 lines)
Line 0    Link Here 
1
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2
/*
3
 * Copyright (c) 2016 Universita' di Firenze
4
 * 
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License version 2 as
7
 * published by the Free Software Foundation;
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program; if not, write to the Free Software
16
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
 *
18
 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
19
 */
20
21
#include "ns3/test.h"
22
#include "ns3/socket-factory.h"
23
#include "ns3/udp-socket-factory.h"
24
#include "ns3/simulator.h"
25
#include "ns3/simple-channel.h"
26
#include "ns3/simple-net-device.h"
27
#include "ns3/drop-tail-queue.h"
28
#include "ns3/socket.h"
29
#include "ns3/boolean.h"
30
#include "ns3/enum.h"
31
32
#include "ns3/log.h"
33
#include "ns3/node.h"
34
#include "ns3/inet-socket-address.h"
35
36
#include "ns3/internet-stack-helper.h"
37
#include "ns3/ipv4-address-helper.h"
38
#include "ns3/ipv4-l3-protocol.h"
39
#include "ns3/icmpv4-l4-protocol.h"
40
#include "ns3/udp-l4-protocol.h"
41
#include "ns3/rip.h"
42
#include "ns3/rip-helper.h"
43
#include "ns3/node-container.h"
44
#include "ns3/ipv4-static-routing.h"
45
46
#include <string>
47
#include <limits>
48
49
using namespace ns3;
50
51
// Ipv4RipTest
52
53
class Ipv4RipTest : public TestCase
54
{
55
  Ptr<Packet> m_receivedPacket;
56
  void DoSendData (Ptr<Socket> socket, std::string to);
57
  void SendData (Ptr<Socket> socket, std::string to);
58
59
public:
60
  virtual void DoRun (void);
61
  Ipv4RipTest ();
62
63
  void ReceivePkt (Ptr<Socket> socket);
64
};
65
66
Ipv4RipTest::Ipv4RipTest ()
67
  : TestCase ("RIP")
68
{
69
}
70
71
void Ipv4RipTest::ReceivePkt (Ptr<Socket> socket)
72
{
73
  uint32_t availableData;
74
  availableData = socket->GetRxAvailable ();
75
  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
76
  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
77
  //cast availableData to void, to suppress 'availableData' set but not used
78
  //compiler warning
79
  (void) availableData;
80
}
81
82
void
83
Ipv4RipTest::DoSendData (Ptr<Socket> socket, std::string to)
84
{
85
  Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 1234);
86
  NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
87
                         123, "100");
88
}
89
90
void
91
Ipv4RipTest::SendData (Ptr<Socket> socket, std::string to)
92
{
93
  m_receivedPacket = Create<Packet> ();
94
  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
95
                                  &Ipv4RipTest::DoSendData, this, socket, to);
96
  Simulator::Stop (Seconds (66));
97
  Simulator::Run ();
98
}
99
100
void
101
Ipv4RipTest::DoRun (void)
102
{
103
  // Create topology
104
105
  Ptr<Node> txNode = CreateObject<Node> ();
106
  Ptr<Node> rxNode = CreateObject<Node> ();
107
  Ptr<Node> routerA = CreateObject<Node> ();
108
  Ptr<Node> routerB = CreateObject<Node> ();
109
  Ptr<Node> routerC = CreateObject<Node> ();
110
111
  NodeContainer nodes (txNode, rxNode);
112
  NodeContainer routers (routerA, routerB, routerC);
113
  NodeContainer all (nodes, routers);
114
115
  RipHelper ripRouting;
116
  InternetStackHelper internetRouters;
117
  internetRouters.SetRoutingHelper (ripRouting);
118
  internetRouters.Install (routers);
119
120
  InternetStackHelper internetNodes;
121
  internetNodes.Install (nodes);
122
123
  NetDeviceContainer net1;
124
  NetDeviceContainer net2;
125
  NetDeviceContainer net3;
126
  NetDeviceContainer net4;
127
128
  // Sender Node
129
  Ptr<SimpleNetDevice> txDev;
130
  {
131
    txDev = CreateObject<SimpleNetDevice> ();
132
    txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
133
    txNode->AddDevice (txDev);
134
  }
135
  net1.Add (txDev);
136
137
  // Router A
138
  Ptr<SimpleNetDevice> fwDev1routerA, fwDev2routerA;
139
  { // first interface
140
    fwDev1routerA = CreateObject<SimpleNetDevice> ();
141
    fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
142
    routerA->AddDevice (fwDev1routerA);
143
  }
144
  net1.Add (fwDev1routerA);
145
146
  { // second interface
147
    fwDev2routerA = CreateObject<SimpleNetDevice> ();
148
    fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
149
    routerA->AddDevice (fwDev2routerA);
150
  }
151
  net2.Add (fwDev2routerA);
152
153
  // Router B
154
  Ptr<SimpleNetDevice> fwDev1routerB, fwDev2routerB;
155
  { // first interface
156
    fwDev1routerB = CreateObject<SimpleNetDevice> ();
157
    fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
158
    routerB->AddDevice (fwDev1routerB);
159
  }
160
  net2.Add (fwDev1routerB);
161
162
  { // second interface
163
    fwDev2routerB = CreateObject<SimpleNetDevice> ();
164
    fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05"));
165
    routerB->AddDevice (fwDev2routerB);
166
  }
167
  net3.Add (fwDev2routerB);
168
169
  // Router C
170
  Ptr<SimpleNetDevice> fwDev1routerC, fwDev2routerC;
171
  { // first interface
172
    fwDev1routerC = CreateObject<SimpleNetDevice> ();
173
    fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06"));
174
    routerC->AddDevice (fwDev1routerC);
175
  }
176
  net3.Add (fwDev1routerC);
177
178
  { // second interface
179
    fwDev2routerC = CreateObject<SimpleNetDevice> ();
180
    fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07"));
181
    routerC->AddDevice (fwDev2routerC);
182
  }
183
  net4.Add (fwDev2routerC);
184
185
  // Rx node
186
  Ptr<SimpleNetDevice> rxDev;
187
  { // first interface
188
    rxDev = CreateObject<SimpleNetDevice> ();
189
    rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08"));
190
    rxNode->AddDevice (rxDev);
191
  }
192
  net4.Add (rxDev);
193
194
  // link the channels
195
  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
196
  txDev->SetChannel (channel1);
197
  fwDev1routerA->SetChannel (channel1);
198
199
  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
200
  fwDev2routerA->SetChannel (channel2);
201
  fwDev1routerB->SetChannel (channel2);
202
203
  Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel> ();
204
  fwDev2routerB->SetChannel (channel3);
205
  fwDev1routerC->SetChannel (channel3);
206
207
  Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel> ();
208
  fwDev2routerC->SetChannel (channel4);
209
  rxDev->SetChannel (channel4);
210
211
  // Setup IPv4 addresses and forwarding
212
  Ipv4AddressHelper ipv4;
213
214
  ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
215
  Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
216
217
  ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
218
  Ipv4InterfaceContainer iic2 = ipv4.Assign (net2);
219
220
  ipv4.SetBase (Ipv4Address ("192.168.1.0"), Ipv4Mask ("255.255.255.0"));
221
  Ipv4InterfaceContainer iic3 = ipv4.Assign (net3);
222
223
  ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
224
  Ipv4InterfaceContainer iic4 = ipv4.Assign (net4);
225
226
  Ptr<Ipv4StaticRouting> staticRouting;
227
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (txNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
228
  staticRouting->SetDefaultRoute ("10.0.1.2", 1 );
229
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (rxNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
230
  staticRouting->SetDefaultRoute ("10.0.2.1", 1 );
231
232
  // Create the UDP sockets
233
  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
234
  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
235
  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.2.2"), 1234)), 0, "trivial");
236
  rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipTest::ReceivePkt, this));
237
238
  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
239
  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
240
  txSocket->SetAllowBroadcast (true);
241
242
  // ------ Now the tests ------------
243
244
  // Unicast test
245
  SendData (txSocket, "10.0.2.2");
246
  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "IPv4 RIP should work.");
247
248
  m_receivedPacket->RemoveAllByteTags ();
249
250
  Simulator::Destroy ();
251
}
252
253
// Ipv4RipCountToInfinityTest
254
255
class Ipv4RipCountToInfinityTest : public TestCase
256
{
257
  Ptr<Packet> m_receivedPacket;
258
  void DoSendData (Ptr<Socket> socket, std::string to);
259
  void SendData (Ptr<Socket> socket, std::string to);
260
261
public:
262
  virtual void DoRun (void);
263
  Ipv4RipCountToInfinityTest ();
264
265
  void ReceivePkt (Ptr<Socket> socket);
266
};
267
268
Ipv4RipCountToInfinityTest::Ipv4RipCountToInfinityTest ()
269
  : TestCase ("RIP counting to infinity")
270
{
271
}
272
273
void Ipv4RipCountToInfinityTest::ReceivePkt (Ptr<Socket> socket)
274
{
275
  uint32_t availableData;
276
  availableData = socket->GetRxAvailable ();
277
  m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
278
  NS_ASSERT (availableData == m_receivedPacket->GetSize ());
279
  //cast availableData to void, to suppress 'availableData' set but not used
280
  //compiler warning
281
  (void) availableData;
282
}
283
284
void
285
Ipv4RipCountToInfinityTest::DoSendData (Ptr<Socket> socket, std::string to)
286
{
287
  Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 1234);
288
  NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
289
                         123, "100");
290
}
291
292
void
293
Ipv4RipCountToInfinityTest::SendData (Ptr<Socket> socket, std::string to)
294
{
295
  m_receivedPacket = Create<Packet> ();
296
  Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
297
                                  &Ipv4RipCountToInfinityTest::DoSendData, this, socket, to);
298
  Simulator::Stop (Seconds (66));
299
  Simulator::Run ();
300
}
301
302
void
303
Ipv4RipCountToInfinityTest::DoRun (void)
304
{
305
  // Create topology
306
307
  Ptr<Node> txNode = CreateObject<Node> ();
308
  Ptr<Node> rxNode = CreateObject<Node> ();
309
  Ptr<Node> routerA = CreateObject<Node> ();
310
  Ptr<Node> routerB = CreateObject<Node> ();
311
  Ptr<Node> routerC = CreateObject<Node> ();
312
313
  NodeContainer nodes (txNode, rxNode);
314
  NodeContainer routers (routerA, routerB, routerC);
315
  NodeContainer all (nodes, routers);
316
317
  RipHelper ripNgRouting;
318
  // Change the router's interface metric to 10, must not send packets (count to infinity)
319
  // note: Interface 0 is the loopback.
320
  ripNgRouting.SetInterfaceMetric (routerA, 2, 10);
321
  ripNgRouting.SetInterfaceMetric (routerB, 1, 10);
322
  ripNgRouting.SetInterfaceMetric (routerB, 2, 10);
323
  ripNgRouting.SetInterfaceMetric (routerC, 1, 10);
324
325
  InternetStackHelper internetv6routers;
326
  internetv6routers.SetRoutingHelper (ripNgRouting);
327
  internetv6routers.Install (routers);
328
329
  InternetStackHelper internetv6nodes;
330
  internetv6nodes.Install (nodes);
331
332
  NetDeviceContainer net1;
333
  NetDeviceContainer net2;
334
  NetDeviceContainer net3;
335
  NetDeviceContainer net4;
336
337
  // Sender Node
338
  Ptr<SimpleNetDevice> txDev;
339
  {
340
    txDev = CreateObject<SimpleNetDevice> ();
341
    txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
342
    txNode->AddDevice (txDev);
343
  }
344
  net1.Add (txDev);
345
346
  // Router A
347
  Ptr<SimpleNetDevice> fwDev1routerA, fwDev2routerA;
348
  { // first interface
349
    fwDev1routerA = CreateObject<SimpleNetDevice> ();
350
    fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
351
    routerA->AddDevice (fwDev1routerA);
352
  }
353
  net1.Add (fwDev1routerA);
354
355
  { // second interface
356
    fwDev2routerA = CreateObject<SimpleNetDevice> ();
357
    fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
358
    routerA->AddDevice (fwDev2routerA);
359
  }
360
  net2.Add (fwDev2routerA);
361
362
  // Router B
363
  Ptr<SimpleNetDevice> fwDev1routerB, fwDev2routerB;
364
  { // first interface
365
    fwDev1routerB = CreateObject<SimpleNetDevice> ();
366
    fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
367
    routerB->AddDevice (fwDev1routerB);
368
  }
369
  net2.Add (fwDev1routerB);
370
371
  { // second interface
372
    fwDev2routerB = CreateObject<SimpleNetDevice> ();
373
    fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05"));
374
    routerB->AddDevice (fwDev2routerB);
375
  }
376
  net3.Add (fwDev2routerB);
377
378
  // Router C
379
  Ptr<SimpleNetDevice> fwDev1routerC, fwDev2routerC;
380
  { // first interface
381
    fwDev1routerC = CreateObject<SimpleNetDevice> ();
382
    fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06"));
383
    routerC->AddDevice (fwDev1routerC);
384
  }
385
  net3.Add (fwDev1routerC);
386
387
  { // second interface
388
    fwDev2routerC = CreateObject<SimpleNetDevice> ();
389
    fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07"));
390
    routerC->AddDevice (fwDev2routerC);
391
  }
392
  net4.Add (fwDev2routerC);
393
394
  // Rx node
395
  Ptr<SimpleNetDevice> rxDev;
396
  { // first interface
397
    rxDev = CreateObject<SimpleNetDevice> ();
398
    rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08"));
399
    rxNode->AddDevice (rxDev);
400
  }
401
  net4.Add (rxDev);
402
403
  // link the channels
404
  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
405
  txDev->SetChannel (channel1);
406
  fwDev1routerA->SetChannel (channel1);
407
408
  Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
409
  fwDev2routerA->SetChannel (channel2);
410
  fwDev1routerB->SetChannel (channel2);
411
412
  Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel> ();
413
  fwDev2routerB->SetChannel (channel3);
414
  fwDev1routerC->SetChannel (channel3);
415
416
  Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel> ();
417
  fwDev2routerC->SetChannel (channel4);
418
  rxDev->SetChannel (channel4);
419
420
  // Setup IPv4 addresses and forwarding
421
  Ipv4AddressHelper ipv4;
422
423
  ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
424
  Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
425
426
  ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
427
  Ipv4InterfaceContainer iic2 = ipv4.Assign (net2);
428
429
  ipv4.SetBase (Ipv4Address ("192.168.1.0"), Ipv4Mask ("255.255.255.0"));
430
  Ipv4InterfaceContainer iic3 = ipv4.Assign (net3);
431
432
  ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
433
  Ipv4InterfaceContainer iic4 = ipv4.Assign (net4);
434
435
  Ptr<Ipv4StaticRouting> staticRouting;
436
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (txNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
437
  staticRouting->SetDefaultRoute ("10.0.1.2", 1 );
438
  staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (rxNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
439
  staticRouting->SetDefaultRoute ("10.0.2.1", 1 );
440
441
442
  // Create the UDP sockets
443
  Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
444
  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
445
  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.2.2"), 1234)), 0, "trivial");
446
  rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipCountToInfinityTest::ReceivePkt, this));
447
448
  Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
449
  Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
450
  txSocket->SetAllowBroadcast (true);
451
452
  // ------ Now the tests ------------
453
454
  SendData (txSocket, "10.0.2.2");
455
  NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 0, "RIP counting to infinity.");
456
457
  Simulator::Destroy ();
458
}
459
460
// Ipv4RipSplitHorizonStrategyTest
461
462
class Ipv4RipSplitHorizonStrategyTest : public TestCase
463
{
464
  Rip::SplitHorizonType_e m_setStrategy;
465
  Rip::SplitHorizonType_e m_detectedStrategy;
466
467
public:
468
  virtual void DoRun (void);
469
  Ipv4RipSplitHorizonStrategyTest (Rip::SplitHorizonType_e strategy);
470
471
  void ReceivePktProbe (Ptr<Socket> socket);
472
};
473
474
Ipv4RipSplitHorizonStrategyTest::Ipv4RipSplitHorizonStrategyTest (Rip::SplitHorizonType_e strategy)
475
  : TestCase ("RIP Split Horizon strategy")
476
{
477
  m_setStrategy = strategy;
478
}
479
480
void Ipv4RipSplitHorizonStrategyTest::ReceivePktProbe (Ptr<Socket> socket)
481
{
482
  uint32_t availableData;
483
  availableData = socket->GetRxAvailable ();
484
  Ptr<Packet> receivedPacketProbe = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
485
  NS_ASSERT (availableData == receivedPacketProbe->GetSize ());
486
  SocketAddressTag tag;
487
  receivedPacketProbe->RemovePacketTag (tag);
488
  Ipv4Address senderAddress = InetSocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv4 ();
489
490
  if (senderAddress == "192.168.0.2")
491
    {
492
      RipHeader hdr;
493
      receivedPacketProbe->RemoveHeader (hdr);
494
495
      std::list<RipRte> rtes = hdr.GetRteList ();
496
497
      // validate the RTEs before processing
498
      for (std::list<RipRte>::iterator iter = rtes.begin ();
499
          iter != rtes.end (); iter++)
500
        {
501
          if (iter->GetPrefix () == "10.0.1.0")
502
            {
503
              bool correct = false;
504
              if (iter->GetRouteMetric () == 16)
505
                {
506
                  correct = true;
507
                  m_detectedStrategy = Rip::POISON_REVERSE;
508
                }
509
              else if (iter->GetRouteMetric () == 2)
510
                {
511
                  correct = true;
512
                  m_detectedStrategy = Rip::NO_SPLIT_HORIZON;
513
                }
514
              NS_TEST_EXPECT_MSG_EQ (correct, true, "RIP: unexpected metric value: " << iter->GetRouteMetric ());
515
            }
516
        }
517
    }
518
519
  //cast availableData to void, to suppress 'availableData' set but not used
520
  //compiler warning
521
  (void) availableData;
522
}
523
524
void
525
Ipv4RipSplitHorizonStrategyTest::DoRun (void)
526
{
527
  // Create topology
528
529
  Ptr<Node> fakeNode = CreateObject<Node> ();
530
  Ptr<Node> listener = CreateObject<Node> ();
531
532
  Ptr<Node> routerA = CreateObject<Node> ();
533
  Ptr<Node> routerB = CreateObject<Node> ();
534
535
  NodeContainer listeners (listener, fakeNode);
536
  NodeContainer routers (routerA, routerB);
537
  NodeContainer all (routers, listeners);
538
539
  RipHelper ripNgRouting;
540
  ripNgRouting.Set ("SplitHorizon", EnumValue (m_setStrategy));
541
542
  InternetStackHelper internetRouters;
543
  internetRouters.SetRoutingHelper (ripNgRouting);
544
  internetRouters.Install (routers);
545
546
  InternetStackHelper internetNodes;
547
  internetNodes.Install (listeners);
548
549
  NetDeviceContainer net0;
550
  NetDeviceContainer net1;
551
552
  // Fake Node
553
  Ptr<SimpleNetDevice> silentDev;
554
  {
555
    silentDev = CreateObject<SimpleNetDevice> ();
556
    silentDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
557
    fakeNode->AddDevice (silentDev);
558
  }
559
  net0.Add (silentDev);
560
561
  // Router A
562
  Ptr<SimpleNetDevice> silentDevRouterA, fwDevRouterA;
563
  { // silent interface
564
    silentDevRouterA = CreateObject<SimpleNetDevice> ();
565
    silentDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
566
    routerA->AddDevice (silentDevRouterA);
567
  }
568
  net0.Add (silentDevRouterA);
569
570
  { // first interface
571
    fwDevRouterA = CreateObject<SimpleNetDevice> ();
572
    fwDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
573
    routerA->AddDevice (fwDevRouterA);
574
  }
575
  net1.Add (fwDevRouterA);
576
577
  // Router B
578
  Ptr<SimpleNetDevice> fwDevRouterB;
579
  { // first interface
580
    fwDevRouterB = CreateObject<SimpleNetDevice> ();
581
    fwDevRouterB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
582
    routerB->AddDevice (fwDevRouterB);
583
  }
584
  net1.Add (fwDevRouterB);
585
586
  // listener A
587
  Ptr<SimpleNetDevice> listenerDev;
588
  {
589
    listenerDev = CreateObject<SimpleNetDevice> ();
590
    listenerDev->SetAddress (Mac48Address ("00:00:00:00:00:05"));
591
    listener->AddDevice (listenerDev);
592
  }
593
  net1.Add (listenerDev);
594
595
  // link the channels
596
  Ptr<SimpleChannel> channel0 = CreateObject<SimpleChannel> ();
597
  silentDev->SetChannel (channel0);
598
  silentDevRouterA->SetChannel (channel0);
599
600
  Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
601
  fwDevRouterA->SetChannel (channel1);
602
  fwDevRouterB->SetChannel (channel1);
603
  listenerDev->SetChannel (channel1);
604
605
  // Setup IPv6 addresses and forwarding
606
  Ipv4AddressHelper ipv4;
607
608
  ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
609
  Ipv4InterfaceContainer iic0 = ipv4.Assign (net0);
610
611
  ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
612
  Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
613
614
  // Create the UDP sockets
615
  Ptr<SocketFactory> rxSocketFactory = listener->GetObject<UdpSocketFactory> ();
616
  Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
617
  NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("224.0.0.9"), 520)), 0, "trivial");
618
  rxSocket->BindToNetDevice (listenerDev);
619
  rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipSplitHorizonStrategyTest::ReceivePktProbe, this));
620
621
  // ------ Now the tests ------------
622
623
  // If the strategy is Split Horizon, then no packet will be received.
624
  m_detectedStrategy = Rip::SPLIT_HORIZON;
625
626
  Simulator::Stop (Seconds (66));
627
  Simulator::Run ();
628
  NS_TEST_EXPECT_MSG_EQ (m_detectedStrategy, m_setStrategy, "RIP counting to infinity.");
629
630
  Simulator::Destroy ();
631
}
632
633
634
//-----------------------------------------------------------------------------
635
//-----------------------------------------------------------------------------
636
class Ipv4RipTestSuite : public TestSuite
637
{
638
public:
639
  Ipv4RipTestSuite () : TestSuite ("ipv4-rip", UNIT)
640
  {
641
    AddTestCase (new Ipv4RipTest, TestCase::QUICK);
642
    AddTestCase (new Ipv4RipCountToInfinityTest, TestCase::QUICK);
643
    AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::POISON_REVERSE), TestCase::QUICK);
644
    AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::SPLIT_HORIZON), TestCase::QUICK);
645
    AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::NO_SPLIT_HORIZON), TestCase::QUICK);
646
  }
647
} g_ipv4ripTestSuite;
(-)a/src/internet/wscript (+8 lines)
 Lines 206-211    Link Here 
206
        'model/ripng.cc',
206
        'model/ripng.cc',
207
        'model/ripng-header.cc',
207
        'model/ripng-header.cc',
208
        'helper/ripng-helper.cc',
208
        'helper/ripng-helper.cc',
209
        'model/rip.cc',
210
        'model/rip-header.cc',
211
        'helper/rip-helper.cc',
209
        ]
212
        ]
210
213
211
    internet_test = bld.create_ns3_module_test_library('internet')
214
    internet_test = bld.create_ns3_module_test_library('internet')
 Lines 256-261    Link Here 
256
        'test/codel-queue-test-suite.cc',
259
        'test/codel-queue-test-suite.cc',
257
        'test/tcp-endpoint-bug2211.cc',
260
        'test/tcp-endpoint-bug2211.cc',
258
        'test/tcp-datasentcb-test.cc',
261
        'test/tcp-datasentcb-test.cc',
262
        'test/ipv4-rip-test.cc',
263
        
259
        ]
264
        ]
260
    privateheaders = bld(features='ns3privateheader')
265
    privateheaders = bld(features='ns3privateheader')
261
    privateheaders.module = 'internet'
266
    privateheaders.module = 'internet'
 Lines 351-356    Link Here 
351
        'model/ripng.h',
356
        'model/ripng.h',
352
        'model/ripng-header.h',
357
        'model/ripng-header.h',
353
        'helper/ripng-helper.h',
358
        'helper/ripng-helper.h',
359
        'model/rip.h',
360
        'model/rip-header.h',
361
        'helper/rip-helper.h',
354
       ]
362
       ]
355
363
356
    if bld.env['NSC_ENABLED']:
364
    if bld.env['NSC_ENABLED']:

Return to bug 2289