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/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 253-258    Link Here 
253
        'test/codel-queue-test-suite.cc',
256
        'test/codel-queue-test-suite.cc',
254
        'test/tcp-endpoint-bug2211.cc',
257
        'test/tcp-endpoint-bug2211.cc',
255
        'test/tcp-datasentcb-test.cc',
258
        'test/tcp-datasentcb-test.cc',
259
        'test/ipv4-rip-test.cc',
260
        
256
        ]
261
        ]
257
    privateheaders = bld(features='ns3privateheader')
262
    privateheaders = bld(features='ns3privateheader')
258
    privateheaders.module = 'internet'
263
    privateheaders.module = 'internet'
 Lines 348-353    Link Here 
348
        'model/ripng.h',
353
        'model/ripng.h',
349
        'model/ripng-header.h',
354
        'model/ripng-header.h',
350
        'helper/ripng-helper.h',
355
        'helper/ripng-helper.h',
356
        'model/rip.h',
357
        'model/rip-header.h',
358
        'helper/rip-helper.h',
351
       ]
359
       ]
352
360
353
    if bld.env['NSC_ENABLED']:
361
    if bld.env['NSC_ENABLED']:

Return to bug 2289