internet: RIPv2 implementation
This commit is contained in:
258
examples/routing/rip-simple-network.cc
Normal file
258
examples/routing/rip-simple-network.cc
Normal file
@@ -0,0 +1,258 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
// Network topology
|
||||
//
|
||||
// SRC
|
||||
// |<=== source network
|
||||
// A-----B
|
||||
// \ / \ all networks have cost 1, except
|
||||
// \ / | for the direct link from C to D, which
|
||||
// C / has cost 10
|
||||
// | /
|
||||
// |/
|
||||
// D
|
||||
// |<=== target network
|
||||
// DST
|
||||
//
|
||||
//
|
||||
// A, B, C and D are RIPng routers.
|
||||
// A and D are configured with static addresses.
|
||||
// SRC and DST will exchange packets.
|
||||
//
|
||||
// After about 3 seconds, the topology is built, and Echo Reply will be received.
|
||||
// After 40 seconds, the link between B and D will break, causing a route failure.
|
||||
// After 44 seconds from the failure, the routers will recovery from the failure.
|
||||
// Split Horizoning should affect the recovery time, but it is not. See the manual
|
||||
// for an explanation of this effect.
|
||||
//
|
||||
// If "showPings" is enabled, the user will see:
|
||||
// 1) if the ping has been acknowledged
|
||||
// 2) if a Destination Unreachable has been received by the sender
|
||||
// 3) nothing, when the Echo Request has been received by the destination but
|
||||
// the Echo Reply is unable to reach the sender.
|
||||
// Examining the .pcap files with Wireshark can confirm this effect.
|
||||
|
||||
|
||||
#include <fstream>
|
||||
#include "ns3/core-module.h"
|
||||
#include "ns3/internet-module.h"
|
||||
#include "ns3/csma-module.h"
|
||||
#include "ns3/internet-apps-module.h"
|
||||
#include "ns3/ipv4-static-routing-helper.h"
|
||||
#include "ns3/ipv4-routing-table-entry.h"
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
NS_LOG_COMPONENT_DEFINE ("RipSimpleRouting");
|
||||
|
||||
void TearDownLink (Ptr<Node> nodeA, Ptr<Node> nodeB, uint32_t interfaceA, uint32_t interfaceB)
|
||||
{
|
||||
nodeA->GetObject<Ipv4> ()->SetDown (interfaceA);
|
||||
nodeB->GetObject<Ipv4> ()->SetDown (interfaceB);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
bool verbose = false;
|
||||
bool printRoutingTables = false;
|
||||
bool showPings = false;
|
||||
std::string SplitHorizon ("PoisonReverse");
|
||||
|
||||
CommandLine cmd;
|
||||
cmd.AddValue ("verbose", "turn on log components", verbose);
|
||||
cmd.AddValue ("printRoutingTables", "Print routing tables at 30, 60 and 90 seconds", printRoutingTables);
|
||||
cmd.AddValue ("showPings", "Show Ping6 reception", showPings);
|
||||
cmd.AddValue ("splitHorizonStrategy", "Split Horizon strategy to use (NoSplitHorizon, SplitHorizon, PoisonReverse)", SplitHorizon);
|
||||
cmd.Parse (argc, argv);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LogComponentEnableAll (LogLevel (LOG_PREFIX_TIME | LOG_PREFIX_NODE));
|
||||
LogComponentEnable ("RipSimpleRouting", LOG_LEVEL_INFO);
|
||||
LogComponentEnable ("Rip", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Ipv4Interface", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Icmpv4L4Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("Ipv4L3Protocol", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("ArpCache", LOG_LEVEL_ALL);
|
||||
LogComponentEnable ("V4Ping", LOG_LEVEL_ALL);
|
||||
}
|
||||
|
||||
if (SplitHorizon == "NoSplitHorizon")
|
||||
{
|
||||
Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::NO_SPLIT_HORIZON));
|
||||
}
|
||||
else if (SplitHorizon == "SplitHorizon")
|
||||
{
|
||||
Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::SPLIT_HORIZON));
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::SetDefault ("ns3::Rip::SplitHorizon", EnumValue (RipNg::POISON_REVERSE));
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Create nodes.");
|
||||
Ptr<Node> src = CreateObject<Node> ();
|
||||
Names::Add ("SrcNode", src);
|
||||
Ptr<Node> dst = CreateObject<Node> ();
|
||||
Names::Add ("DstNode", dst);
|
||||
Ptr<Node> a = CreateObject<Node> ();
|
||||
Names::Add ("RouterA", a);
|
||||
Ptr<Node> b = CreateObject<Node> ();
|
||||
Names::Add ("RouterB", b);
|
||||
Ptr<Node> c = CreateObject<Node> ();
|
||||
Names::Add ("RouterC", c);
|
||||
Ptr<Node> d = CreateObject<Node> ();
|
||||
Names::Add ("RouterD", d);
|
||||
NodeContainer net1 (src, a);
|
||||
NodeContainer net2 (a, b);
|
||||
NodeContainer net3 (a, c);
|
||||
NodeContainer net4 (b, c);
|
||||
NodeContainer net5 (c, d);
|
||||
NodeContainer net6 (b, d);
|
||||
NodeContainer net7 (d, dst);
|
||||
NodeContainer routers (a, b, c, d);
|
||||
NodeContainer nodes (src, dst);
|
||||
|
||||
|
||||
NS_LOG_INFO ("Create channels.");
|
||||
CsmaHelper csma;
|
||||
csma.SetChannelAttribute ("DataRate", DataRateValue (5000000));
|
||||
csma.SetChannelAttribute ("Delay", TimeValue (MilliSeconds (2)));
|
||||
NetDeviceContainer ndc1 = csma.Install (net1);
|
||||
NetDeviceContainer ndc2 = csma.Install (net2);
|
||||
NetDeviceContainer ndc3 = csma.Install (net3);
|
||||
NetDeviceContainer ndc4 = csma.Install (net4);
|
||||
NetDeviceContainer ndc5 = csma.Install (net5);
|
||||
NetDeviceContainer ndc6 = csma.Install (net6);
|
||||
NetDeviceContainer ndc7 = csma.Install (net7);
|
||||
|
||||
NS_LOG_INFO ("Create IPv4 and routing");
|
||||
RipHelper ripRouting;
|
||||
|
||||
// Rule of thumb:
|
||||
// Interfaces are added sequentially, starting from 0
|
||||
// However, interface 0 is always the loopback...
|
||||
ripRouting.ExcludeInterface (a, 1);
|
||||
ripRouting.ExcludeInterface (d, 3);
|
||||
|
||||
ripRouting.SetInterfaceMetric (c, 3, 10);
|
||||
ripRouting.SetInterfaceMetric (d, 1, 10);
|
||||
|
||||
Ipv4ListRoutingHelper listRH;
|
||||
listRH.Add (ripRouting, 0);
|
||||
// Ipv4StaticRoutingHelper staticRh;
|
||||
// listRH.Add (staticRh, 5);
|
||||
|
||||
InternetStackHelper internet;
|
||||
internet.SetIpv6StackInstall (false);
|
||||
internet.SetRoutingHelper (listRH);
|
||||
internet.Install (routers);
|
||||
|
||||
InternetStackHelper internetNodes;
|
||||
internetNodes.SetIpv6StackInstall (false);
|
||||
internetNodes.Install (nodes);
|
||||
|
||||
// Assign addresses.
|
||||
// The source and destination networks have global addresses
|
||||
// The "core" network just needs link-local addresses for routing.
|
||||
// We assign global addresses to the routers as well to receive
|
||||
// ICMPv6 errors.
|
||||
NS_LOG_INFO ("Assign IPv4 Addresses.");
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.0.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic1 = ipv4.Assign (ndc1);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic2 = ipv4.Assign (ndc2);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic3 = ipv4.Assign (ndc3);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.3.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic4 = ipv4.Assign (ndc4);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.4.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic5 = ipv4.Assign (ndc5);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.5.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic6 = ipv4.Assign (ndc6);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.6.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic7 = ipv4.Assign (ndc7);
|
||||
|
||||
Ptr<Ipv4StaticRouting> staticRouting;
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (src->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.0.2", 1 );
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (dst->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.6.1", 1 );
|
||||
|
||||
if (printRoutingTables)
|
||||
{
|
||||
RipHelper routingHelper;
|
||||
|
||||
Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> (&std::cout);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (30.0), d, routingStream);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (60.0), d, routingStream);
|
||||
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), a, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), b, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), c, routingStream);
|
||||
routingHelper.PrintRoutingTableAt (Seconds (90.0), d, routingStream);
|
||||
}
|
||||
|
||||
NS_LOG_INFO ("Create Applications.");
|
||||
uint32_t packetSize = 1024;
|
||||
Time interPacketInterval = Seconds (1.0);
|
||||
V4PingHelper ping ("10.0.6.2");
|
||||
|
||||
ping.SetAttribute ("Interval", TimeValue (interPacketInterval));
|
||||
ping.SetAttribute ("Size", UintegerValue (packetSize));
|
||||
if (showPings)
|
||||
{
|
||||
ping.SetAttribute ("Verbose", BooleanValue (true));
|
||||
}
|
||||
ApplicationContainer apps = ping.Install (src);
|
||||
apps.Start (Seconds (1.0));
|
||||
apps.Stop (Seconds (110.0));
|
||||
|
||||
AsciiTraceHelper ascii;
|
||||
csma.EnableAsciiAll (ascii.CreateFileStream ("rip-simple-routing.tr"));
|
||||
csma.EnablePcapAll ("rip-simple-routing", true);
|
||||
|
||||
Simulator::Schedule (Seconds (40), &TearDownLink, b, d, 3, 2);
|
||||
|
||||
/* Now, do the actual simulation. */
|
||||
NS_LOG_INFO ("Run Simulation.");
|
||||
Simulator::Stop (Seconds (131.0));
|
||||
Simulator::Run ();
|
||||
Simulator::Destroy ();
|
||||
NS_LOG_INFO ("Done.");
|
||||
}
|
||||
|
||||
@@ -42,3 +42,9 @@ def build(bld):
|
||||
obj.source = 'ripng-simple-network.cc'
|
||||
|
||||
bld.register_ns3_script('simple-routing-ping6.py', ['csma', 'internet', 'internet-apps'])
|
||||
|
||||
obj = bld.create_ns3_program('rip-simple-network',
|
||||
['csma', 'internet', 'internet-apps'])
|
||||
obj.source = 'rip-simple-network.cc'
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ is finally used to populate the routes themselves.
|
||||
Unicast routing
|
||||
***************
|
||||
|
||||
There are presently seven unicast routing protocols defined for IPv4 and three for
|
||||
There are presently eigth unicast routing protocols defined for IPv4 and three for
|
||||
IPv6:
|
||||
|
||||
* class Ipv4StaticRouting (covering both unicast and multicast)
|
||||
@@ -230,6 +230,7 @@ IPv6:
|
||||
manager, if that is used)
|
||||
* class Ipv4NixVectorRouting (a more efficient version of global routing that
|
||||
stores source routes in a packet header field)
|
||||
* class Rip - the IPv4 RIPv2 protocol (:rfc:`2453`)
|
||||
* class Ipv6ListRouting (used to store a prioritized list of routing protocols)
|
||||
* class Ipv6StaticRouting
|
||||
* class RipNg - the IPv6 RIPng protocol (:rfc:`2080`)
|
||||
@@ -334,27 +335,30 @@ respond to dynamic changes to a device's IP address or link up/down
|
||||
notifications; i.e. the topology changes are due to loss/gain of connectivity
|
||||
over a wireless channel.
|
||||
|
||||
RIPng
|
||||
+++++
|
||||
RIP and RIPng
|
||||
+++++++++++++
|
||||
|
||||
The RIPv2 protocol for IPv4 is described in the :rfc:`2453`, and it consolidates
|
||||
a number of improvements over the base protocol defined in :rfc:`1058`.
|
||||
|
||||
This IPv6 routing protocol (:rfc:`2080`) is the evolution of the well-known
|
||||
RIPv1 anf RIPv2 (see :rfc:`1058` and :rfc:`1723`) routing protocols for IPv4.
|
||||
RIPv1 (see :rfc:`1058` and :rfc:`1723`) routing protocol for IPv4.
|
||||
|
||||
The protocol is very simple, and it is normally suitable for flat, simple
|
||||
The protocols are very simple, and are normally suitable for flat, simple
|
||||
network topologies.
|
||||
|
||||
RIPng is strongly based on RIPv1 and RIPv2, and it have the very same goals and
|
||||
limitations. In particular, RIP considers any route with a metric equal or greater
|
||||
RIPv1, RIPv2, and RIPng have the very same goals and limitations.
|
||||
In particular, RIP considers any route with a metric equal or greater
|
||||
than 16 as unreachable. As a consequence, the maximum number of hops is the
|
||||
network must be less than 15 (the number of routers is not set).
|
||||
Users are encouraged to read :rfc:`2080` and :rfc:`1058` to fully understand
|
||||
RIPng behaviour and limitations.
|
||||
RIP behaviour and limitations.
|
||||
|
||||
|
||||
Routing convergence
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
RIPng uses a Distance-Vector algorithm, and routes are updated according to
|
||||
RIP uses a Distance-Vector algorithm, and routes are updated according to
|
||||
the Bellman-Ford algorithm (sometimes known as Ford-Fulkerson algorithm).
|
||||
The algorithm has a convergence time of O(\|V\|*\|E\|) where \|V\| and \|E\|
|
||||
are the number of vertices (routers) and edges (links) respectively.
|
||||
@@ -365,7 +369,7 @@ cooldown, the toplogy can require some time to be stabilized.
|
||||
|
||||
Users should be aware that, during routing tables construction, the routers
|
||||
might drop packets. Data traffic should be sent only after a time long
|
||||
enough to allow RIPng to build the network topology.
|
||||
enough to allow RIP to build the network topology.
|
||||
Usually 80 seconds should be enough to have a suboptimal (but working)
|
||||
routing setup. This includes the time needed to propagate the routes to the
|
||||
most distant router (16 hops) with Triggered Updates.
|
||||
@@ -375,13 +379,15 @@ time might be quite high, and it might be even higher than the initial
|
||||
setup time. Moreover, the network topology recovery is affected by
|
||||
the Split Horizoning strategy.
|
||||
|
||||
The example ``examples/routing/ripng-simple-network.cc`` shows both the
|
||||
network setup and network recovery phases.
|
||||
The examples ``examples/routing/ripng-simple-network.cc`` and
|
||||
``examples/routing/rip-simple-network.cc``
|
||||
shows both the network setup and network recovery phases.
|
||||
|
||||
Split Horizoning
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
Split Horizon is a strategy to prevent routing instability. Three options are possible:
|
||||
Split Horizon is a strategy to prevent routing instability.
|
||||
Three options are possible:
|
||||
|
||||
* No Split Horizon
|
||||
* Split Horizon
|
||||
@@ -394,7 +400,7 @@ Poison Reverse will advertise the route on the interface from which it
|
||||
was learned, but with a metric of 16 (infinity).
|
||||
For a full analysis of the three techniques, see :rfc:`1058`, section 2.2.
|
||||
|
||||
The example ``ripng-simple-network.cc`` is based on the network toplogy
|
||||
The examples are based on the network toplogy
|
||||
described in the RFC, but it does not show the effect described there.
|
||||
|
||||
The reason are the Triggered Updates, together with the fact that when a
|
||||
@@ -410,18 +416,19 @@ remanins valid.
|
||||
Default routes
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
RIPng protocol should be installed *only* on routers. As a consequence,
|
||||
RIP protocol should be installed *only* on routers. As a consequence,
|
||||
nodes will not know what is the default router.
|
||||
|
||||
To overcome this limitation, users should either install the default route
|
||||
manually (e.g., by resorting to Ipv6StaticRouting), or by using RADVd.
|
||||
manually (e.g., by resorting to Ipv4StaticRouting or Ipv6StaticRouting), or
|
||||
by using RADVd (in case of IPv6).
|
||||
RADVd is available in |ns3| in the Applications module, and it is strongly
|
||||
suggested.
|
||||
|
||||
Protocol parameters and options
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The RIPng |ns3| implementation allows to change all the timers associated
|
||||
The RIP |ns3| implementations allow to change all the timers associated
|
||||
with route updates and routes lifetime.
|
||||
|
||||
Moreover, users can change the interface metrics on a per-node basis.
|
||||
@@ -431,11 +438,14 @@ selected on a per-node basis, with the choices being "no split horizon",
|
||||
"split horizon" and "poison reverse". See :rfc:`2080` for further details,
|
||||
and :rfc:`1058` for a complete discussion on the split horizoning strategies.
|
||||
|
||||
Moreover, it is possible to use a non-standard value for Link Down Value (i.e.,
|
||||
the value after which a link is considered down). The defaul is value is 16.
|
||||
|
||||
Limitations
|
||||
~~~~~~~~~~~
|
||||
|
||||
There is no support for the Next Hop option (:rfc:`2080`, Section 2.1.1).
|
||||
The Next Hop option is useful when RIPng is not being run on all of the
|
||||
The Next Hop option is useful when RIP is not being run on all of the
|
||||
routers on a network.
|
||||
Support for this option may be considered in the future.
|
||||
|
||||
|
||||
182
src/internet/helper/rip-helper.cc
Normal file
182
src/internet/helper/rip-helper.cc
Normal file
@@ -0,0 +1,182 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/node-list.h"
|
||||
#include "ns3/ipv4-list-routing.h"
|
||||
#include "ns3/rip.h"
|
||||
#include "rip-helper.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
RipHelper::RipHelper ()
|
||||
{
|
||||
m_factory.SetTypeId ("ns3::Rip");
|
||||
}
|
||||
|
||||
RipHelper::RipHelper (const RipHelper &o)
|
||||
: m_factory (o.m_factory)
|
||||
{
|
||||
m_interfaceExclusions = o.m_interfaceExclusions;
|
||||
m_interfaceMetrics = o.m_interfaceMetrics;
|
||||
}
|
||||
|
||||
RipHelper::~RipHelper ()
|
||||
{
|
||||
m_interfaceExclusions.clear ();
|
||||
m_interfaceMetrics.clear ();
|
||||
}
|
||||
|
||||
RipHelper*
|
||||
RipHelper::Copy (void) const
|
||||
{
|
||||
return new RipHelper (*this);
|
||||
}
|
||||
|
||||
Ptr<Ipv4RoutingProtocol>
|
||||
RipHelper::Create (Ptr<Node> node) const
|
||||
{
|
||||
Ptr<Rip> rip = m_factory.Create<Rip> ();
|
||||
|
||||
std::map<Ptr<Node>, std::set<uint32_t> >::const_iterator it = m_interfaceExclusions.find (node);
|
||||
|
||||
if(it != m_interfaceExclusions.end ())
|
||||
{
|
||||
rip->SetInterfaceExclusions (it->second);
|
||||
}
|
||||
|
||||
std::map< Ptr<Node>, std::map<uint32_t, uint8_t> >::const_iterator iter = m_interfaceMetrics.find (node);
|
||||
|
||||
if(iter != m_interfaceMetrics.end ())
|
||||
{
|
||||
std::map<uint32_t, uint8_t>::const_iterator subiter;
|
||||
for (subiter = iter->second.begin (); subiter != iter->second.end (); subiter++)
|
||||
{
|
||||
rip->SetInterfaceMetric (subiter->first, subiter->second);
|
||||
}
|
||||
}
|
||||
|
||||
node->AggregateObject (rip);
|
||||
return rip;
|
||||
}
|
||||
|
||||
void
|
||||
RipHelper::Set (std::string name, const AttributeValue &value)
|
||||
{
|
||||
m_factory.Set (name, value);
|
||||
}
|
||||
|
||||
|
||||
int64_t
|
||||
RipHelper::AssignStreams (NodeContainer c, int64_t stream)
|
||||
{
|
||||
int64_t currentStream = stream;
|
||||
Ptr<Node> node;
|
||||
for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i)
|
||||
{
|
||||
node = (*i);
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
|
||||
NS_ASSERT_MSG (ipv4, "Ipv4 not installed on node");
|
||||
Ptr<Ipv4RoutingProtocol> proto = ipv4->GetRoutingProtocol ();
|
||||
NS_ASSERT_MSG (proto, "Ipv4 routing not installed on node");
|
||||
Ptr<Rip> rip = DynamicCast<Rip> (proto);
|
||||
if (rip)
|
||||
{
|
||||
currentStream += rip->AssignStreams (currentStream);
|
||||
continue;
|
||||
}
|
||||
// RIP may also be in a list
|
||||
Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (proto);
|
||||
if (list)
|
||||
{
|
||||
int16_t priority;
|
||||
Ptr<Ipv4RoutingProtocol> listProto;
|
||||
Ptr<Rip> listRip;
|
||||
for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++)
|
||||
{
|
||||
listProto = list->GetRoutingProtocol (i, priority);
|
||||
listRip = DynamicCast<Rip> (listProto);
|
||||
if (listRip)
|
||||
{
|
||||
currentStream += listRip->AssignStreams (currentStream);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (currentStream - stream);
|
||||
}
|
||||
|
||||
void RipHelper::SetDefaultRouter (Ptr<Node> node, Ipv4Address nextHop, uint32_t interface)
|
||||
{
|
||||
Ptr<Ipv4> ipv4 = node->GetObject<Ipv4> ();
|
||||
NS_ASSERT_MSG (ipv4, "Ipv4 not installed on node");
|
||||
Ptr<Ipv4RoutingProtocol> proto = ipv4->GetRoutingProtocol ();
|
||||
NS_ASSERT_MSG (proto, "Ipv4 routing not installed on node");
|
||||
Ptr<Rip> rip = DynamicCast<Rip> (proto);
|
||||
if (rip)
|
||||
{
|
||||
rip->AddDefaultRouteTo (nextHop, interface);
|
||||
}
|
||||
// RIP may also be in a list
|
||||
Ptr<Ipv4ListRouting> list = DynamicCast<Ipv4ListRouting> (proto);
|
||||
if (list)
|
||||
{
|
||||
int16_t priority;
|
||||
Ptr<Ipv4RoutingProtocol> listProto;
|
||||
Ptr<Rip> listRip;
|
||||
for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++)
|
||||
{
|
||||
listProto = list->GetRoutingProtocol (i, priority);
|
||||
listRip = DynamicCast<Rip> (listProto);
|
||||
if (listRip)
|
||||
{
|
||||
listRip->AddDefaultRouteTo (nextHop, interface);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RipHelper::ExcludeInterface (Ptr<Node> node, uint32_t interface)
|
||||
{
|
||||
std::map< Ptr<Node>, std::set<uint32_t> >::iterator it = m_interfaceExclusions.find (node);
|
||||
|
||||
if (it == m_interfaceExclusions.end ())
|
||||
{
|
||||
std::set<uint32_t> interfaces;
|
||||
interfaces.insert (interface);
|
||||
|
||||
m_interfaceExclusions.insert (std::make_pair (node, interfaces));
|
||||
}
|
||||
else
|
||||
{
|
||||
it->second.insert (interface);
|
||||
}
|
||||
}
|
||||
|
||||
void RipHelper::SetInterfaceMetric (Ptr<Node> node, uint32_t interface, uint8_t metric)
|
||||
{
|
||||
m_interfaceMetrics[node][interface] = metric;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
148
src/internet/helper/rip-helper.h
Normal file
148
src/internet/helper/rip-helper.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#ifndef RIP_HELPER_H
|
||||
#define RIP_HELPER_H
|
||||
|
||||
#include "ns3/object-factory.h"
|
||||
#include "ns3/ipv4-routing-helper.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/node.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief Helper class that adds RIP routing to nodes.
|
||||
*
|
||||
* This class is expected to be used in conjunction with
|
||||
* ns3::InternetStackHelper::SetRoutingHelper
|
||||
*
|
||||
*/
|
||||
class RipHelper : public Ipv4RoutingHelper
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Construct an RipHelper to make life easier while adding RIP
|
||||
* routing to nodes.
|
||||
*/
|
||||
RipHelper ();
|
||||
|
||||
/**
|
||||
* \brief Construct an RipHelper from another previously
|
||||
* initialized instance (Copy Constructor).
|
||||
*/
|
||||
RipHelper (const RipHelper &);
|
||||
|
||||
virtual ~RipHelper ();
|
||||
|
||||
/**
|
||||
* \returns pointer to clone of this RipHelper
|
||||
*
|
||||
* This method is mainly for internal use by the other helpers;
|
||||
* clients are expected to free the dynamic memory allocated by this method
|
||||
*/
|
||||
RipHelper* Copy (void) const;
|
||||
|
||||
/**
|
||||
* \param node the node on which the routing protocol will run
|
||||
* \returns a newly-created routing protocol
|
||||
*
|
||||
* This method will be called by ns3::InternetStackHelper::Install
|
||||
*/
|
||||
virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const;
|
||||
|
||||
/**
|
||||
* \param name the name of the attribute to set
|
||||
* \param value the value of the attribute to set.
|
||||
*
|
||||
* This method controls the attributes of ns3::Ripng
|
||||
*/
|
||||
void Set (std::string name, const AttributeValue &value);
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned. The Install() method should have previously been
|
||||
* called by the user.
|
||||
*
|
||||
* \param c NetDeviceContainer of the set of net devices for which the
|
||||
* SixLowPanNetDevice should be modified to use a fixed stream
|
||||
* \param stream first stream index to use
|
||||
* \return the number of stream indices assigned by this helper
|
||||
*/
|
||||
int64_t AssignStreams (NodeContainer c, int64_t stream);
|
||||
|
||||
/**
|
||||
* \brief Install a default route in the node.
|
||||
*
|
||||
* The traffic will be routed to the nextHop, located on the specified
|
||||
* interface, unless a more specific route is found.
|
||||
*
|
||||
* \param node the node
|
||||
* \param nextHop the next hop
|
||||
* \param interface the network interface
|
||||
*/
|
||||
void SetDefaultRouter (Ptr<Node> node, Ipv4Address nextHop, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Exclude an interface from RIP protocol.
|
||||
*
|
||||
* You have to call this function \a before installing RIP in the nodes.
|
||||
*
|
||||
* Note: the exclusion means that RIP will not be propagated on that interface.
|
||||
* The network prefix on that interface will be still considered in RIP.
|
||||
*
|
||||
* \param node the node
|
||||
* \param interface the network interface to be excluded
|
||||
*/
|
||||
void ExcludeInterface (Ptr<Node> node, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Set a metric for an interface.
|
||||
*
|
||||
* You have to call this function \a before installing RIP in the nodes.
|
||||
*
|
||||
* Note: RIP will apply the metric on route message reception.
|
||||
* As a consequence, interface metric should be set on the receiver.
|
||||
*
|
||||
* \param node the node
|
||||
* \param interface the network interface
|
||||
* \param metric the interface metric
|
||||
*/
|
||||
void SetInterfaceMetric (Ptr<Node> node, uint32_t interface, uint8_t metric);
|
||||
|
||||
private:
|
||||
/**
|
||||
* \brief Assignment operator declared private and not implemented to disallow
|
||||
* assignment and prevent the compiler from happily inserting its own.
|
||||
*/
|
||||
RipHelper &operator = (const RipHelper &o);
|
||||
|
||||
ObjectFactory m_factory; //!< Object Factory
|
||||
|
||||
std::map< Ptr<Node>, std::set<uint32_t> > m_interfaceExclusions; //!< Interface Exclusion set
|
||||
std::map< Ptr<Node>, std::map<uint32_t, uint8_t> > m_interfaceMetrics; //!< Interface Metric set
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
|
||||
|
||||
#endif /* RIP_HELPER_H */
|
||||
|
||||
278
src/internet/model/rip-header.cc
Normal file
278
src/internet/model/rip-header.cc
Normal file
@@ -0,0 +1,278 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#include "rip-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/*
|
||||
* RipRte
|
||||
*/
|
||||
NS_OBJECT_ENSURE_REGISTERED (RipRte);
|
||||
|
||||
|
||||
RipRte::RipRte ()
|
||||
: m_tag (0), m_prefix ("127.0.0.1"), m_subnetMask ("0.0.0.0"), m_nextHop ("0.0.0.0"), m_metric (16)
|
||||
{
|
||||
}
|
||||
|
||||
TypeId RipRte::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::RipRte")
|
||||
.SetParent<Header> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddConstructor<RipRte> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId RipRte::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void RipRte::Print (std::ostream & os) const
|
||||
{
|
||||
os << "prefix " << m_prefix << "/" << m_subnetMask.GetPrefixLength () << " Metric " << int(m_metric);
|
||||
os << " Tag " << int(m_tag) << " Next Hop " << m_nextHop;
|
||||
}
|
||||
|
||||
uint32_t RipRte::GetSerializedSize () const
|
||||
{
|
||||
return 20;
|
||||
}
|
||||
|
||||
void RipRte::Serialize (Buffer::Iterator i) const
|
||||
{
|
||||
i.WriteHtonU16 (2);
|
||||
i.WriteHtonU16 (m_tag);
|
||||
|
||||
i.WriteHtonU32 (m_prefix.Get ());
|
||||
i.WriteHtonU32 (m_subnetMask.Get ());
|
||||
i.WriteHtonU32 (m_nextHop.Get ());
|
||||
i.WriteHtonU32 (m_metric);
|
||||
}
|
||||
|
||||
uint32_t RipRte::Deserialize (Buffer::Iterator i)
|
||||
{
|
||||
uint16_t tmp;
|
||||
|
||||
tmp = i.ReadNtohU16 ();
|
||||
if (tmp != 2)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_tag = i.ReadNtohU16 ();
|
||||
m_prefix.Set (i.ReadNtohU32 ());
|
||||
m_subnetMask.Set (i.ReadNtohU32 ());
|
||||
m_nextHop.Set (i.ReadNtohU32 ());
|
||||
|
||||
m_metric = i.ReadNtohU32 ();
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
void RipRte::SetPrefix (Ipv4Address prefix)
|
||||
{
|
||||
m_prefix = prefix;
|
||||
}
|
||||
|
||||
Ipv4Address RipRte::GetPrefix () const
|
||||
{
|
||||
return m_prefix;
|
||||
}
|
||||
|
||||
void RipRte::SetSubnetMask (Ipv4Mask subnetMask)
|
||||
{
|
||||
m_subnetMask = subnetMask;
|
||||
}
|
||||
|
||||
Ipv4Mask RipRte::GetSubnetMask () const
|
||||
{
|
||||
return m_subnetMask;
|
||||
}
|
||||
|
||||
void RipRte::SetRouteTag (uint16_t routeTag)
|
||||
{
|
||||
m_tag = routeTag;
|
||||
}
|
||||
|
||||
uint16_t RipRte::GetRouteTag () const
|
||||
{
|
||||
return m_tag;
|
||||
}
|
||||
|
||||
void RipRte::SetRouteMetric (uint32_t routeMetric)
|
||||
{
|
||||
m_metric = routeMetric;
|
||||
}
|
||||
|
||||
uint32_t RipRte::GetRouteMetric () const
|
||||
{
|
||||
return m_metric;
|
||||
}
|
||||
|
||||
void RipRte::SetNextHop (Ipv4Address nextHop)
|
||||
{
|
||||
m_nextHop = nextHop;
|
||||
}
|
||||
|
||||
Ipv4Address RipRte::GetNextHop () const
|
||||
{
|
||||
return m_nextHop;
|
||||
}
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream & os, const RipRte & h)
|
||||
{
|
||||
h.Print (os);
|
||||
return os;
|
||||
}
|
||||
|
||||
/*
|
||||
* RipHeader
|
||||
*/
|
||||
NS_OBJECT_ENSURE_REGISTERED (RipHeader)
|
||||
;
|
||||
|
||||
RipHeader::RipHeader ()
|
||||
: m_command (0)
|
||||
{
|
||||
}
|
||||
|
||||
TypeId RipHeader::GetTypeId (void)
|
||||
{
|
||||
static TypeId tid = TypeId ("ns3::RipHeader")
|
||||
.SetParent<Header> ()
|
||||
.SetGroupName ("Internet")
|
||||
.AddConstructor<RipHeader> ();
|
||||
return tid;
|
||||
}
|
||||
|
||||
TypeId RipHeader::GetInstanceTypeId (void) const
|
||||
{
|
||||
return GetTypeId ();
|
||||
}
|
||||
|
||||
void RipHeader::Print (std::ostream & os) const
|
||||
{
|
||||
os << "command " << int(m_command);
|
||||
for (std::list<RipRte>::const_iterator iter = m_rteList.begin ();
|
||||
iter != m_rteList.end (); iter ++)
|
||||
{
|
||||
os << " | ";
|
||||
iter->Print (os);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RipHeader::GetSerializedSize () const
|
||||
{
|
||||
RipRte rte;
|
||||
return 4 + m_rteList.size () * rte.GetSerializedSize ();
|
||||
}
|
||||
|
||||
void RipHeader::Serialize (Buffer::Iterator start) const
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
|
||||
i.WriteU8 (uint8_t (m_command));
|
||||
i.WriteU8 (1);
|
||||
i.WriteU16 (0);
|
||||
|
||||
for (std::list<RipRte>::const_iterator iter = m_rteList.begin ();
|
||||
iter != m_rteList.end (); iter ++)
|
||||
{
|
||||
iter->Serialize (i);
|
||||
i.Next(iter->GetSerializedSize ());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RipHeader::Deserialize (Buffer::Iterator start)
|
||||
{
|
||||
Buffer::Iterator i = start;
|
||||
|
||||
uint8_t temp;
|
||||
temp = i.ReadU8 ();
|
||||
if ((temp == REQUEST) || (temp == RESPONSE))
|
||||
{
|
||||
m_command = temp;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
temp = i.ReadU8 ();
|
||||
NS_ASSERT_MSG (temp == 1, "RIP received a message with mismatch version, aborting.");
|
||||
|
||||
uint16_t temp16 = i.ReadU16 ();
|
||||
NS_ASSERT_MSG (temp16 == 0, "RIP received a message with invalid filled flags, aborting.");
|
||||
|
||||
uint8_t rteNumber = (i.GetSize () - 4)/20;
|
||||
for (uint8_t n=0; n<rteNumber; n++)
|
||||
{
|
||||
RipRte rte;
|
||||
i.Next (rte.Deserialize (i));
|
||||
m_rteList.push_back (rte);
|
||||
}
|
||||
|
||||
return GetSerializedSize ();
|
||||
}
|
||||
|
||||
void RipHeader::SetCommand (RipHeader::Command_e command)
|
||||
{
|
||||
m_command = command;
|
||||
}
|
||||
|
||||
RipHeader::Command_e RipHeader::GetCommand () const
|
||||
{
|
||||
return RipHeader::Command_e (m_command);
|
||||
}
|
||||
|
||||
void RipHeader::AddRte (RipRte rte)
|
||||
{
|
||||
m_rteList.push_back (rte);
|
||||
}
|
||||
|
||||
void RipHeader::ClearRtes ()
|
||||
{
|
||||
m_rteList.clear ();
|
||||
}
|
||||
|
||||
uint16_t RipHeader::GetRteNumber (void) const
|
||||
{
|
||||
return m_rteList.size ();
|
||||
}
|
||||
|
||||
std::list<RipRte> RipHeader::GetRteList (void) const
|
||||
{
|
||||
return m_rteList;
|
||||
}
|
||||
|
||||
|
||||
std::ostream & operator << (std::ostream & os, const RipHeader & h)
|
||||
{
|
||||
h.Print (os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
256
src/internet/model/rip-header.h
Normal file
256
src/internet/model/rip-header.h
Normal file
@@ -0,0 +1,256 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#ifndef RIP_HEADER_H
|
||||
#define RIP_HEADER_H
|
||||
|
||||
#include <list>
|
||||
#include "ns3/header.h"
|
||||
#include "ns3/ipv4-address.h"
|
||||
#include "ns3/packet.h"
|
||||
#include "ns3/ipv4-header.h"
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \ingroup rip
|
||||
* \brief Rip v2 Routing Table Entry (RTE) - see \RFC{2453}.
|
||||
*/
|
||||
class RipRte : public Header
|
||||
{
|
||||
public:
|
||||
RipRte (void);
|
||||
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return The object TypeId.
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Return the instance type identifier.
|
||||
* \return Instance type ID.
|
||||
*/
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
virtual void Print (std::ostream& os) const;
|
||||
|
||||
/**
|
||||
* \brief Get the serialized size of the packet.
|
||||
* \return Size.
|
||||
*/
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
|
||||
/**
|
||||
* \brief Serialize the packet.
|
||||
* \param start Buffer iterator.
|
||||
*/
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
|
||||
/**
|
||||
* \brief Deserialize the packet.
|
||||
* \param start Buffer iterator.
|
||||
* \return Size of the packet.
|
||||
*/
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
/**
|
||||
* \brief Set the prefix.
|
||||
* \param prefix The prefix.
|
||||
*/
|
||||
void SetPrefix (Ipv4Address prefix);
|
||||
|
||||
/**
|
||||
* \brief Get the prefix.
|
||||
* \returns The prefix.
|
||||
*/
|
||||
Ipv4Address GetPrefix (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the subnet mask.
|
||||
* \param subnetMask The subnet mask.
|
||||
*/
|
||||
void SetSubnetMask (Ipv4Mask subnetMask);
|
||||
|
||||
/**
|
||||
* \brief Get the subnet mask.
|
||||
* \returns The subnet mask.
|
||||
*/
|
||||
Ipv4Mask GetSubnetMask (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route tag.
|
||||
* \param routeTag The route tag.
|
||||
*/
|
||||
void SetRouteTag (uint16_t routeTag);
|
||||
|
||||
/**
|
||||
* \brief Get the route tag.
|
||||
* \returns The route tag.
|
||||
*/
|
||||
uint16_t GetRouteTag (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route metric.
|
||||
* \param routeMetric The route metric.
|
||||
*/
|
||||
void SetRouteMetric (uint32_t routeMetric);
|
||||
|
||||
/**
|
||||
* \brief Get the route metric.
|
||||
* \returns The route metric.
|
||||
*/
|
||||
uint32_t GetRouteMetric (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route metric.
|
||||
* \param routeMetric The route metric.
|
||||
*/
|
||||
void SetNextHop (Ipv4Address nextHop);
|
||||
|
||||
/**
|
||||
* \brief Get the route metric.
|
||||
* \returns The route metric.
|
||||
*/
|
||||
Ipv4Address GetNextHop (void) const;
|
||||
|
||||
|
||||
private:
|
||||
uint16_t m_tag; //!< Route tag.
|
||||
Ipv4Address m_prefix; //!< Advertised prefix.
|
||||
Ipv4Mask m_subnetMask; //!< Subnet mask.
|
||||
Ipv4Address m_nextHop; //!< Next hop.
|
||||
uint32_t m_metric; //!< Route metric.
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the reference to the output stream
|
||||
* \param h the Routing Table Entry
|
||||
* \returns the reference to the output stream
|
||||
*/
|
||||
std::ostream & operator << (std::ostream & os, const RipRte & h);
|
||||
|
||||
/**
|
||||
* \ingroup rip
|
||||
* \brief RipHeader - see \RFC{2453}
|
||||
*/
|
||||
class RipHeader : public Header
|
||||
{
|
||||
public:
|
||||
RipHeader (void);
|
||||
|
||||
/**
|
||||
* \brief Get the type ID.
|
||||
* \return the object TypeId
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
/**
|
||||
* \brief Return the instance type identifier.
|
||||
* \return instance type ID
|
||||
*/
|
||||
virtual TypeId GetInstanceTypeId (void) const;
|
||||
|
||||
virtual void Print (std::ostream& os) const;
|
||||
|
||||
/**
|
||||
* \brief Get the serialized size of the packet.
|
||||
* \return size
|
||||
*/
|
||||
virtual uint32_t GetSerializedSize (void) const;
|
||||
|
||||
/**
|
||||
* \brief Serialize the packet.
|
||||
* \param start Buffer iterator
|
||||
*/
|
||||
virtual void Serialize (Buffer::Iterator start) const;
|
||||
|
||||
/**
|
||||
* \brief Deserialize the packet.
|
||||
* \param start Buffer iterator
|
||||
* \return size of the packet
|
||||
*/
|
||||
virtual uint32_t Deserialize (Buffer::Iterator start);
|
||||
|
||||
/**
|
||||
* Commands to be used in Rip headers
|
||||
*/
|
||||
enum Command_e
|
||||
{
|
||||
REQUEST = 0x1,
|
||||
RESPONSE = 0x2,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Set the command
|
||||
* \param command the command
|
||||
*/
|
||||
void SetCommand (Command_e command);
|
||||
|
||||
/**
|
||||
* \brief Get the command
|
||||
* \returns the command
|
||||
*/
|
||||
Command_e GetCommand (void) const;
|
||||
|
||||
/**
|
||||
* \brief Add a RTE to the message
|
||||
* \param rte the RTE
|
||||
*/
|
||||
void AddRte (RipRte rte);
|
||||
|
||||
/**
|
||||
* \brief Clear all the RTEs from the header
|
||||
*/
|
||||
void ClearRtes ();
|
||||
|
||||
/**
|
||||
* \brief Get the number of RTE included in the message
|
||||
* \returns the number of RTE in the message
|
||||
*/
|
||||
uint16_t GetRteNumber (void) const;
|
||||
|
||||
/**
|
||||
* \brief Get the list of the RTEs included in the message
|
||||
* \returns the list of the RTEs in the message
|
||||
*/
|
||||
std::list<RipRte> GetRteList (void) const;
|
||||
|
||||
private:
|
||||
uint8_t m_command; //!< command type
|
||||
std::list<RipRte> m_rteList; //!< list of the RTEs in the message
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the reference to the output stream
|
||||
* \param h the Rip header
|
||||
* \returns the reference to the output stream
|
||||
*/
|
||||
std::ostream & operator << (std::ostream & os, const RipHeader & h);
|
||||
|
||||
}
|
||||
|
||||
#endif /* Rip_HEADER_H */
|
||||
|
||||
1369
src/internet/model/rip.cc
Normal file
1369
src/internet/model/rip.cc
Normal file
File diff suppressed because it is too large
Load Diff
409
src/internet/model/rip.h
Normal file
409
src/internet/model/rip.h
Normal file
@@ -0,0 +1,409 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze, Italy
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#ifndef RIP_H
|
||||
#define RIP_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "ns3/ipv4-routing-protocol.h"
|
||||
#include "ns3/ipv4-interface.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/ipv4-routing-table-entry.h"
|
||||
#include "ns3/random-variable-stream.h"
|
||||
#include "ns3/rip-header.h"
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \defgroup rip RIP
|
||||
*
|
||||
* The RIP protocol (\RFC{2453}) is a unicast-only IPv4 IGP (Interior Gateway Protocol).
|
||||
* Its convergence time is rather long. As a consequence, it is suggested to
|
||||
* carefully check the network topology and the route status before sending
|
||||
* data flows.
|
||||
*
|
||||
* RIP implements the Bellman-Ford algorithm (although the RFC does not state it).
|
||||
* Bellman-Ford algorithm convergence time is O(|V|*|E|) where |V| and |E| are the
|
||||
* number of vertices (routers) and edges (links) respectively. Since unsolicited
|
||||
* updates are exchanged every 30 seconds, the convergence might require a long time.
|
||||
*
|
||||
* For the RIP protocol, the exact convergence time is shorter, thanks to the
|
||||
* use of triggered updates, which are sent when a route changes.
|
||||
* Even with triggered updates, the convergence is in the order of magnitude of
|
||||
* O(|V|*|E|) * 5 seconds, which is still quite long for complex topologies.
|
||||
*
|
||||
* \todo: Add routing table compression (CIDR). The most evident result: without
|
||||
* it a router will announce to be the default router *and* more RTEs, which is silly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \ingroup rip
|
||||
* \brief Rip Routing Table Entry
|
||||
*/
|
||||
class RipRoutingTableEntry : public Ipv4RoutingTableEntry
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Route status
|
||||
*/
|
||||
enum Status_e {
|
||||
RIP_VALID,
|
||||
RIP_INVALID,
|
||||
};
|
||||
|
||||
RipRoutingTableEntry (void);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param network network address
|
||||
* \param networkPrefix network prefix
|
||||
* \param nextHop next hop address to route the packet
|
||||
* \param interface interface index
|
||||
*/
|
||||
RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Constructor
|
||||
* \param network network address
|
||||
* \param networkPrefix network prefix
|
||||
* \param interface interface index
|
||||
*/
|
||||
RipRoutingTableEntry (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface);
|
||||
|
||||
virtual ~RipRoutingTableEntry ();
|
||||
|
||||
/**
|
||||
* \brief Set the route tag
|
||||
* \param routeTag the route tag
|
||||
*/
|
||||
void SetRouteTag (uint16_t routeTag);
|
||||
|
||||
/**
|
||||
* \brief Get the route tag
|
||||
* \returns the route tag
|
||||
*/
|
||||
uint16_t GetRouteTag (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route metric
|
||||
* \param routeMetric the route metric
|
||||
*/
|
||||
void SetRouteMetric (uint8_t routeMetric);
|
||||
|
||||
/**
|
||||
* \brief Get the route metric
|
||||
* \returns the route metric
|
||||
*/
|
||||
uint8_t GetRouteMetric (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route status
|
||||
* \param status the route status
|
||||
*/
|
||||
void SetRouteStatus (Status_e status);
|
||||
|
||||
/**
|
||||
* \brief Get the route status
|
||||
* \returns the route status
|
||||
*/
|
||||
Status_e GetRouteStatus (void) const;
|
||||
|
||||
/**
|
||||
* \brief Set the route as changed
|
||||
*
|
||||
* The changed routes are scheduled for a Triggered Update.
|
||||
* After a Triggered Update, all the changed flags are cleared
|
||||
* from the routing table.
|
||||
*
|
||||
* \param changed true if route is changed
|
||||
*/
|
||||
void SetRouteChanged (bool changed);
|
||||
|
||||
/**
|
||||
* \brief Get the route changed status
|
||||
*
|
||||
* \returns true if route is changed
|
||||
*/
|
||||
bool IsRouteChanged (void) const;
|
||||
|
||||
private:
|
||||
uint16_t m_tag; //!< route tag
|
||||
uint8_t m_metric; //!< route metric
|
||||
Status_e m_status; //!< route status
|
||||
bool m_changed; //!< route has been updated
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Stream insertion operator.
|
||||
*
|
||||
* \param os the reference to the output stream
|
||||
* \param route the Ipv4 routing table entry
|
||||
* \returns the reference to the output stream
|
||||
*/
|
||||
std::ostream& operator<< (std::ostream& os, RipRoutingTableEntry const& route);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* \ingroup rip
|
||||
*
|
||||
* \brief RIP Routing Protocol, defined in \RFC{2453}.
|
||||
*/
|
||||
class Rip : public Ipv4RoutingProtocol
|
||||
{
|
||||
public:
|
||||
// /< C-tor
|
||||
Rip ();
|
||||
virtual ~Rip ();
|
||||
|
||||
/**
|
||||
* \brief Get the type ID
|
||||
* \return type ID
|
||||
*/
|
||||
static TypeId GetTypeId (void);
|
||||
|
||||
// From Ipv4RoutingProtocol
|
||||
Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif,
|
||||
Socket::SocketErrno &sockerr);
|
||||
bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
|
||||
UnicastForwardCallback ucb, MulticastForwardCallback mcb,
|
||||
LocalDeliverCallback lcb, ErrorCallback ecb);
|
||||
virtual void NotifyInterfaceUp (uint32_t interface);
|
||||
virtual void NotifyInterfaceDown (uint32_t interface);
|
||||
virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
|
||||
virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
|
||||
virtual void SetIpv4 (Ptr<Ipv4> ipv4);
|
||||
virtual void PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const;
|
||||
|
||||
/**
|
||||
* Split Horizon strategy type. See \RFC{2453}.
|
||||
*/
|
||||
enum SplitHorizonType_e {
|
||||
NO_SPLIT_HORIZON,//!< No Split Horizon
|
||||
SPLIT_HORIZON, //!< Split Horizon
|
||||
POISON_REVERSE, //!< Poison Reverse Split Horizon
|
||||
};
|
||||
|
||||
/**
|
||||
* Assign a fixed random variable stream number to the random variables
|
||||
* used by this model. Return the number of streams (possibly zero) that
|
||||
* have been assigned.
|
||||
*
|
||||
* \param stream first stream index to use
|
||||
* \return the number of stream indices assigned by this model
|
||||
*/
|
||||
int64_t AssignStreams (int64_t stream);
|
||||
|
||||
/**
|
||||
* \brief Get the set of interface excluded from the protocol
|
||||
* \return the set of excluded interfaces
|
||||
*/
|
||||
std::set<uint32_t> GetInterfaceExclusions () const;
|
||||
|
||||
/**
|
||||
* \brief Set the set of interface excluded from the protocol
|
||||
* \param exceptions the set of excluded interfaces
|
||||
*/
|
||||
void SetInterfaceExclusions (std::set<uint32_t> exceptions);
|
||||
|
||||
/**
|
||||
* \brief Get the metric for an interface
|
||||
* \param interface the interface
|
||||
* \returns the interface metric
|
||||
*/
|
||||
uint8_t GetInterfaceMetric (uint32_t interface) const;
|
||||
|
||||
/**
|
||||
* \brief Set the metric for an interface
|
||||
* \param interface the interface
|
||||
* \param metric the interface metric
|
||||
*/
|
||||
void SetInterfaceMetric (uint32_t interface, uint8_t metric);
|
||||
|
||||
/**
|
||||
* \brief Add a default route to the router through the nextHop located on interface.
|
||||
*
|
||||
* The default route is usually installed manually, or it is the result of
|
||||
* some "other" routing protocol (e.g., BGP).
|
||||
*
|
||||
* \param nextHop the next hop
|
||||
* \param interface the interface
|
||||
*/
|
||||
void AddDefaultRouteTo (Ipv4Address nextHop, uint32_t interface);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* \brief Dispose this object.
|
||||
*/
|
||||
virtual void DoDispose ();
|
||||
|
||||
/**
|
||||
* Start protocol operation
|
||||
*/
|
||||
void DoInitialize ();
|
||||
|
||||
private:
|
||||
/// Container for the network routes - pair RipRoutingTableEntry *, EventId (update event)
|
||||
typedef std::list<std::pair <RipRoutingTableEntry *, EventId> > Routes;
|
||||
|
||||
/// Const Iterator for container for the network routes
|
||||
typedef std::list<std::pair <RipRoutingTableEntry *, EventId> >::const_iterator RoutesCI;
|
||||
|
||||
/// Iterator for container for the network routes
|
||||
typedef std::list<std::pair <RipRoutingTableEntry *, EventId> >::iterator RoutesI;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Receive RIP packets.
|
||||
*
|
||||
* \param socket the socket the packet was received to.
|
||||
*/
|
||||
void Receive (Ptr<Socket> socket);
|
||||
|
||||
/**
|
||||
* \brief Handle RIP requests.
|
||||
*
|
||||
* \param hdr message header (including RTEs)
|
||||
* \param senderAddress sender address
|
||||
* \param senderPort sender port
|
||||
* \param incomingInterface incoming interface
|
||||
* \param hopLimit packet's hop limit
|
||||
*/
|
||||
void HandleRequests (RipHeader hdr, Ipv4Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit);
|
||||
|
||||
/**
|
||||
* \brief Handle RIP responses.
|
||||
*
|
||||
* \param hdr message header (including RTEs)
|
||||
* \param senderAddress sender address
|
||||
* \param incomingInterface incoming interface
|
||||
* \param hopLimit packet's hop limit
|
||||
*/
|
||||
void HandleResponses (RipHeader hdr, Ipv4Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit);
|
||||
|
||||
/**
|
||||
* \brief Lookup in the forwarding table for destination.
|
||||
* \param dest destination address
|
||||
* \param interface output interface if any (put 0 otherwise)
|
||||
* \return Ipv4Route to route the packet to reach dest address
|
||||
*/
|
||||
Ptr<Ipv4Route> Lookup (Ipv4Address dest, Ptr<NetDevice> = 0);
|
||||
|
||||
/**
|
||||
* Receive and process unicast packet
|
||||
* \param socket socket where packet is arrived
|
||||
*/
|
||||
void RecvUnicastRip (Ptr<Socket> socket);
|
||||
/**
|
||||
* Receive and process multicast packet
|
||||
* \param socket socket where packet is arrived
|
||||
*/
|
||||
void RecvMulticastRip (Ptr<Socket> socket);
|
||||
|
||||
/**
|
||||
* \brief Add route to network.
|
||||
* \param network network address
|
||||
* \param networkPrefix network prefix
|
||||
* \param nextHop next hop address to route the packet.
|
||||
* \param interface interface index
|
||||
*/
|
||||
void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, Ipv4Address nextHop, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Add route to network.
|
||||
* \param network network address
|
||||
* \param networkPrefix network prefix
|
||||
* \param interface interface index
|
||||
*/
|
||||
void AddNetworkRouteTo (Ipv4Address network, Ipv4Mask networkPrefix, uint32_t interface);
|
||||
|
||||
/**
|
||||
* \brief Send Routing Updates on all interfaces.
|
||||
*/
|
||||
void DoSendRouteUpdate (bool periodic);
|
||||
|
||||
/**
|
||||
* \brief Send Routing Request on all interfaces.
|
||||
*/
|
||||
void SendRouteRequest ();
|
||||
|
||||
/**
|
||||
* \brief Send Triggered Routing Updates on all interfaces.
|
||||
*/
|
||||
void SendTriggeredRouteUpdate ();
|
||||
|
||||
/**
|
||||
* \brief Send Unsolicited Routing Updates on all interfaces.
|
||||
*/
|
||||
void SendUnsolicitedRouteUpdate (void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate a route.
|
||||
* \param route the route to be removed
|
||||
*/
|
||||
void InvalidateRoute (RipRoutingTableEntry *route);
|
||||
|
||||
/**
|
||||
* \brief Delete a route.
|
||||
* \param route the route to be removed
|
||||
*/
|
||||
void DeleteRoute (RipRoutingTableEntry *route);
|
||||
|
||||
Routes m_routes; //!< the forwarding table for network.
|
||||
Ptr<Ipv4> m_ipv4; //!< IPv4 reference
|
||||
Time m_startupDelay; //!< Random delay before protocol startup.
|
||||
Time m_minTriggeredUpdateDelay; //!< Min cooldown delay after a Triggered Update.
|
||||
Time m_maxTriggeredUpdateDelay; //!< Max cooldown delay after a Triggered Update.
|
||||
Time m_unsolicitedUpdate; //!< time between two Unsolicited Routing Updates
|
||||
Time m_timeoutDelay; //!< Delay before invalidating a route
|
||||
Time m_garbageCollectionDelay; //!< Delay before deleting an INVALID route
|
||||
|
||||
// note: we can not trust the result of socket->GetBoundNetDevice ()->GetIfIndex ();
|
||||
// it is dependent on the interface initialization (i.e., if the loopback is already up).
|
||||
/// Socket list type
|
||||
typedef std::map< Ptr<Socket>, uint32_t> SocketList;
|
||||
/// Socket list type iterator
|
||||
typedef std::map<Ptr<Socket>, uint32_t>::iterator SocketListI;
|
||||
/// Socket list type const iterator
|
||||
typedef std::map<Ptr<Socket>, uint32_t>::const_iterator SocketListCI;
|
||||
|
||||
SocketList m_sendSocketList; //!< list of sockets for sending (socket, interface index)
|
||||
Ptr<Socket> m_recvSocket; //!< receive socket
|
||||
|
||||
EventId m_nextUnsolicitedUpdate; //!< Next Unsolicited Update event
|
||||
EventId m_nextTriggeredUpdate; //!< Next Triggered Update event
|
||||
|
||||
Ptr<UniformRandomVariable> m_rng; //!< Rng stream.
|
||||
|
||||
std::set<uint32_t> m_interfaceExclusions; //!< Set of excluded interfaces
|
||||
std::map<uint32_t, uint8_t> m_interfaceMetrics; //!< Map of interface metrics
|
||||
|
||||
SplitHorizonType_e m_splitHorizonStrategy; //!< Split Horizon strategy
|
||||
|
||||
bool m_initialized; //!< flag to allow socket's late-creation.
|
||||
uint32_t m_linkDown; //!< Link down value.
|
||||
};
|
||||
|
||||
} // namespace ns3
|
||||
#endif /* RIP_H */
|
||||
|
||||
647
src/internet/test/ipv4-rip-test.cc
Normal file
647
src/internet/test/ipv4-rip-test.cc
Normal file
@@ -0,0 +1,647 @@
|
||||
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
|
||||
/*
|
||||
* Copyright (c) 2016 Universita' di Firenze
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation;
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
|
||||
*/
|
||||
|
||||
#include "ns3/test.h"
|
||||
#include "ns3/socket-factory.h"
|
||||
#include "ns3/udp-socket-factory.h"
|
||||
#include "ns3/simulator.h"
|
||||
#include "ns3/simple-channel.h"
|
||||
#include "ns3/simple-net-device.h"
|
||||
#include "ns3/drop-tail-queue.h"
|
||||
#include "ns3/socket.h"
|
||||
#include "ns3/boolean.h"
|
||||
#include "ns3/enum.h"
|
||||
|
||||
#include "ns3/log.h"
|
||||
#include "ns3/node.h"
|
||||
#include "ns3/inet-socket-address.h"
|
||||
|
||||
#include "ns3/internet-stack-helper.h"
|
||||
#include "ns3/ipv4-address-helper.h"
|
||||
#include "ns3/ipv4-l3-protocol.h"
|
||||
#include "ns3/icmpv4-l4-protocol.h"
|
||||
#include "ns3/udp-l4-protocol.h"
|
||||
#include "ns3/rip.h"
|
||||
#include "ns3/rip-helper.h"
|
||||
#include "ns3/node-container.h"
|
||||
#include "ns3/ipv4-static-routing.h"
|
||||
|
||||
#include <string>
|
||||
#include <limits>
|
||||
|
||||
using namespace ns3;
|
||||
|
||||
// Ipv4RipTest
|
||||
|
||||
class Ipv4RipTest : public TestCase
|
||||
{
|
||||
Ptr<Packet> m_receivedPacket;
|
||||
void DoSendData (Ptr<Socket> socket, std::string to);
|
||||
void SendData (Ptr<Socket> socket, std::string to);
|
||||
|
||||
public:
|
||||
virtual void DoRun (void);
|
||||
Ipv4RipTest ();
|
||||
|
||||
void ReceivePkt (Ptr<Socket> socket);
|
||||
};
|
||||
|
||||
Ipv4RipTest::Ipv4RipTest ()
|
||||
: TestCase ("RIP")
|
||||
{
|
||||
}
|
||||
|
||||
void Ipv4RipTest::ReceivePkt (Ptr<Socket> socket)
|
||||
{
|
||||
uint32_t availableData;
|
||||
availableData = socket->GetRxAvailable ();
|
||||
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
|
||||
NS_ASSERT (availableData == m_receivedPacket->GetSize ());
|
||||
//cast availableData to void, to suppress 'availableData' set but not used
|
||||
//compiler warning
|
||||
(void) availableData;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipTest::DoSendData (Ptr<Socket> socket, std::string to)
|
||||
{
|
||||
Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 1234);
|
||||
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
|
||||
123, "100");
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipTest::SendData (Ptr<Socket> socket, std::string to)
|
||||
{
|
||||
m_receivedPacket = Create<Packet> ();
|
||||
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
|
||||
&Ipv4RipTest::DoSendData, this, socket, to);
|
||||
Simulator::Stop (Seconds (66));
|
||||
Simulator::Run ();
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipTest::DoRun (void)
|
||||
{
|
||||
// Create topology
|
||||
|
||||
Ptr<Node> txNode = CreateObject<Node> ();
|
||||
Ptr<Node> rxNode = CreateObject<Node> ();
|
||||
Ptr<Node> routerA = CreateObject<Node> ();
|
||||
Ptr<Node> routerB = CreateObject<Node> ();
|
||||
Ptr<Node> routerC = CreateObject<Node> ();
|
||||
|
||||
NodeContainer nodes (txNode, rxNode);
|
||||
NodeContainer routers (routerA, routerB, routerC);
|
||||
NodeContainer all (nodes, routers);
|
||||
|
||||
RipHelper ripRouting;
|
||||
InternetStackHelper internetRouters;
|
||||
internetRouters.SetRoutingHelper (ripRouting);
|
||||
internetRouters.Install (routers);
|
||||
|
||||
InternetStackHelper internetNodes;
|
||||
internetNodes.Install (nodes);
|
||||
|
||||
NetDeviceContainer net1;
|
||||
NetDeviceContainer net2;
|
||||
NetDeviceContainer net3;
|
||||
NetDeviceContainer net4;
|
||||
|
||||
// Sender Node
|
||||
Ptr<SimpleNetDevice> txDev;
|
||||
{
|
||||
txDev = CreateObject<SimpleNetDevice> ();
|
||||
txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
|
||||
txNode->AddDevice (txDev);
|
||||
}
|
||||
net1.Add (txDev);
|
||||
|
||||
// Router A
|
||||
Ptr<SimpleNetDevice> fwDev1routerA, fwDev2routerA;
|
||||
{ // first interface
|
||||
fwDev1routerA = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
routerA->AddDevice (fwDev1routerA);
|
||||
}
|
||||
net1.Add (fwDev1routerA);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerA = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
|
||||
routerA->AddDevice (fwDev2routerA);
|
||||
}
|
||||
net2.Add (fwDev2routerA);
|
||||
|
||||
// Router B
|
||||
Ptr<SimpleNetDevice> fwDev1routerB, fwDev2routerB;
|
||||
{ // first interface
|
||||
fwDev1routerB = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
|
||||
routerB->AddDevice (fwDev1routerB);
|
||||
}
|
||||
net2.Add (fwDev1routerB);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerB = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05"));
|
||||
routerB->AddDevice (fwDev2routerB);
|
||||
}
|
||||
net3.Add (fwDev2routerB);
|
||||
|
||||
// Router C
|
||||
Ptr<SimpleNetDevice> fwDev1routerC, fwDev2routerC;
|
||||
{ // first interface
|
||||
fwDev1routerC = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06"));
|
||||
routerC->AddDevice (fwDev1routerC);
|
||||
}
|
||||
net3.Add (fwDev1routerC);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerC = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07"));
|
||||
routerC->AddDevice (fwDev2routerC);
|
||||
}
|
||||
net4.Add (fwDev2routerC);
|
||||
|
||||
// Rx node
|
||||
Ptr<SimpleNetDevice> rxDev;
|
||||
{ // first interface
|
||||
rxDev = CreateObject<SimpleNetDevice> ();
|
||||
rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08"));
|
||||
rxNode->AddDevice (rxDev);
|
||||
}
|
||||
net4.Add (rxDev);
|
||||
|
||||
// link the channels
|
||||
Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
|
||||
txDev->SetChannel (channel1);
|
||||
fwDev1routerA->SetChannel (channel1);
|
||||
|
||||
Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerA->SetChannel (channel2);
|
||||
fwDev1routerB->SetChannel (channel2);
|
||||
|
||||
Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerB->SetChannel (channel3);
|
||||
fwDev1routerC->SetChannel (channel3);
|
||||
|
||||
Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerC->SetChannel (channel4);
|
||||
rxDev->SetChannel (channel4);
|
||||
|
||||
// Setup IPv4 addresses and forwarding
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic2 = ipv4.Assign (net2);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("192.168.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic3 = ipv4.Assign (net3);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic4 = ipv4.Assign (net4);
|
||||
|
||||
Ptr<Ipv4StaticRouting> staticRouting;
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (txNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.1.2", 1 );
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (rxNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.2.1", 1 );
|
||||
|
||||
// Create the UDP sockets
|
||||
Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
|
||||
NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.2.2"), 1234)), 0, "trivial");
|
||||
rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipTest::ReceivePkt, this));
|
||||
|
||||
Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
|
||||
txSocket->SetAllowBroadcast (true);
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
// Unicast test
|
||||
SendData (txSocket, "10.0.2.2");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "IPv4 RIP should work.");
|
||||
|
||||
m_receivedPacket->RemoveAllByteTags ();
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
// Ipv4RipCountToInfinityTest
|
||||
|
||||
class Ipv4RipCountToInfinityTest : public TestCase
|
||||
{
|
||||
Ptr<Packet> m_receivedPacket;
|
||||
void DoSendData (Ptr<Socket> socket, std::string to);
|
||||
void SendData (Ptr<Socket> socket, std::string to);
|
||||
|
||||
public:
|
||||
virtual void DoRun (void);
|
||||
Ipv4RipCountToInfinityTest ();
|
||||
|
||||
void ReceivePkt (Ptr<Socket> socket);
|
||||
};
|
||||
|
||||
Ipv4RipCountToInfinityTest::Ipv4RipCountToInfinityTest ()
|
||||
: TestCase ("RIP counting to infinity")
|
||||
{
|
||||
}
|
||||
|
||||
void Ipv4RipCountToInfinityTest::ReceivePkt (Ptr<Socket> socket)
|
||||
{
|
||||
uint32_t availableData;
|
||||
availableData = socket->GetRxAvailable ();
|
||||
m_receivedPacket = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
|
||||
NS_ASSERT (availableData == m_receivedPacket->GetSize ());
|
||||
//cast availableData to void, to suppress 'availableData' set but not used
|
||||
//compiler warning
|
||||
(void) availableData;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipCountToInfinityTest::DoSendData (Ptr<Socket> socket, std::string to)
|
||||
{
|
||||
Address realTo = InetSocketAddress (Ipv4Address (to.c_str ()), 1234);
|
||||
NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create<Packet> (123), 0, realTo),
|
||||
123, "100");
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipCountToInfinityTest::SendData (Ptr<Socket> socket, std::string to)
|
||||
{
|
||||
m_receivedPacket = Create<Packet> ();
|
||||
Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60),
|
||||
&Ipv4RipCountToInfinityTest::DoSendData, this, socket, to);
|
||||
Simulator::Stop (Seconds (66));
|
||||
Simulator::Run ();
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipCountToInfinityTest::DoRun (void)
|
||||
{
|
||||
// Create topology
|
||||
|
||||
Ptr<Node> txNode = CreateObject<Node> ();
|
||||
Ptr<Node> rxNode = CreateObject<Node> ();
|
||||
Ptr<Node> routerA = CreateObject<Node> ();
|
||||
Ptr<Node> routerB = CreateObject<Node> ();
|
||||
Ptr<Node> routerC = CreateObject<Node> ();
|
||||
|
||||
NodeContainer nodes (txNode, rxNode);
|
||||
NodeContainer routers (routerA, routerB, routerC);
|
||||
NodeContainer all (nodes, routers);
|
||||
|
||||
RipHelper ripNgRouting;
|
||||
// Change the router's interface metric to 10, must not send packets (count to infinity)
|
||||
// note: Interface 0 is the loopback.
|
||||
ripNgRouting.SetInterfaceMetric (routerA, 2, 10);
|
||||
ripNgRouting.SetInterfaceMetric (routerB, 1, 10);
|
||||
ripNgRouting.SetInterfaceMetric (routerB, 2, 10);
|
||||
ripNgRouting.SetInterfaceMetric (routerC, 1, 10);
|
||||
|
||||
InternetStackHelper internetv6routers;
|
||||
internetv6routers.SetRoutingHelper (ripNgRouting);
|
||||
internetv6routers.Install (routers);
|
||||
|
||||
InternetStackHelper internetv6nodes;
|
||||
internetv6nodes.Install (nodes);
|
||||
|
||||
NetDeviceContainer net1;
|
||||
NetDeviceContainer net2;
|
||||
NetDeviceContainer net3;
|
||||
NetDeviceContainer net4;
|
||||
|
||||
// Sender Node
|
||||
Ptr<SimpleNetDevice> txDev;
|
||||
{
|
||||
txDev = CreateObject<SimpleNetDevice> ();
|
||||
txDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
|
||||
txNode->AddDevice (txDev);
|
||||
}
|
||||
net1.Add (txDev);
|
||||
|
||||
// Router A
|
||||
Ptr<SimpleNetDevice> fwDev1routerA, fwDev2routerA;
|
||||
{ // first interface
|
||||
fwDev1routerA = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
routerA->AddDevice (fwDev1routerA);
|
||||
}
|
||||
net1.Add (fwDev1routerA);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerA = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
|
||||
routerA->AddDevice (fwDev2routerA);
|
||||
}
|
||||
net2.Add (fwDev2routerA);
|
||||
|
||||
// Router B
|
||||
Ptr<SimpleNetDevice> fwDev1routerB, fwDev2routerB;
|
||||
{ // first interface
|
||||
fwDev1routerB = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
|
||||
routerB->AddDevice (fwDev1routerB);
|
||||
}
|
||||
net2.Add (fwDev1routerB);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerB = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05"));
|
||||
routerB->AddDevice (fwDev2routerB);
|
||||
}
|
||||
net3.Add (fwDev2routerB);
|
||||
|
||||
// Router C
|
||||
Ptr<SimpleNetDevice> fwDev1routerC, fwDev2routerC;
|
||||
{ // first interface
|
||||
fwDev1routerC = CreateObject<SimpleNetDevice> ();
|
||||
fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06"));
|
||||
routerC->AddDevice (fwDev1routerC);
|
||||
}
|
||||
net3.Add (fwDev1routerC);
|
||||
|
||||
{ // second interface
|
||||
fwDev2routerC = CreateObject<SimpleNetDevice> ();
|
||||
fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07"));
|
||||
routerC->AddDevice (fwDev2routerC);
|
||||
}
|
||||
net4.Add (fwDev2routerC);
|
||||
|
||||
// Rx node
|
||||
Ptr<SimpleNetDevice> rxDev;
|
||||
{ // first interface
|
||||
rxDev = CreateObject<SimpleNetDevice> ();
|
||||
rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08"));
|
||||
rxNode->AddDevice (rxDev);
|
||||
}
|
||||
net4.Add (rxDev);
|
||||
|
||||
// link the channels
|
||||
Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
|
||||
txDev->SetChannel (channel1);
|
||||
fwDev1routerA->SetChannel (channel1);
|
||||
|
||||
Ptr<SimpleChannel> channel2 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerA->SetChannel (channel2);
|
||||
fwDev1routerB->SetChannel (channel2);
|
||||
|
||||
Ptr<SimpleChannel> channel3 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerB->SetChannel (channel3);
|
||||
fwDev1routerC->SetChannel (channel3);
|
||||
|
||||
Ptr<SimpleChannel> channel4 = CreateObject<SimpleChannel> ();
|
||||
fwDev2routerC->SetChannel (channel4);
|
||||
rxDev->SetChannel (channel4);
|
||||
|
||||
// Setup IPv4 addresses and forwarding
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic2 = ipv4.Assign (net2);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("192.168.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic3 = ipv4.Assign (net3);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.2.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic4 = ipv4.Assign (net4);
|
||||
|
||||
Ptr<Ipv4StaticRouting> staticRouting;
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (txNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.1.2", 1 );
|
||||
staticRouting = Ipv4RoutingHelper::GetRouting <Ipv4StaticRouting> (rxNode->GetObject<Ipv4> ()->GetRoutingProtocol ());
|
||||
staticRouting->SetDefaultRoute ("10.0.2.1", 1 );
|
||||
|
||||
|
||||
// Create the UDP sockets
|
||||
Ptr<SocketFactory> rxSocketFactory = rxNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
|
||||
NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("10.0.2.2"), 1234)), 0, "trivial");
|
||||
rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipCountToInfinityTest::ReceivePkt, this));
|
||||
|
||||
Ptr<SocketFactory> txSocketFactory = txNode->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> txSocket = txSocketFactory->CreateSocket ();
|
||||
txSocket->SetAllowBroadcast (true);
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
SendData (txSocket, "10.0.2.2");
|
||||
NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 0, "RIP counting to infinity.");
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
// Ipv4RipSplitHorizonStrategyTest
|
||||
|
||||
class Ipv4RipSplitHorizonStrategyTest : public TestCase
|
||||
{
|
||||
Rip::SplitHorizonType_e m_setStrategy;
|
||||
Rip::SplitHorizonType_e m_detectedStrategy;
|
||||
|
||||
public:
|
||||
virtual void DoRun (void);
|
||||
Ipv4RipSplitHorizonStrategyTest (Rip::SplitHorizonType_e strategy);
|
||||
|
||||
void ReceivePktProbe (Ptr<Socket> socket);
|
||||
};
|
||||
|
||||
Ipv4RipSplitHorizonStrategyTest::Ipv4RipSplitHorizonStrategyTest (Rip::SplitHorizonType_e strategy)
|
||||
: TestCase ("RIP Split Horizon strategy")
|
||||
{
|
||||
m_setStrategy = strategy;
|
||||
}
|
||||
|
||||
void Ipv4RipSplitHorizonStrategyTest::ReceivePktProbe (Ptr<Socket> socket)
|
||||
{
|
||||
uint32_t availableData;
|
||||
availableData = socket->GetRxAvailable ();
|
||||
Ptr<Packet> receivedPacketProbe = socket->Recv (std::numeric_limits<uint32_t>::max (), 0);
|
||||
NS_ASSERT (availableData == receivedPacketProbe->GetSize ());
|
||||
SocketAddressTag tag;
|
||||
receivedPacketProbe->RemovePacketTag (tag);
|
||||
Ipv4Address senderAddress = InetSocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv4 ();
|
||||
|
||||
if (senderAddress == "192.168.0.2")
|
||||
{
|
||||
RipHeader hdr;
|
||||
receivedPacketProbe->RemoveHeader (hdr);
|
||||
|
||||
std::list<RipRte> rtes = hdr.GetRteList ();
|
||||
|
||||
// validate the RTEs before processing
|
||||
for (std::list<RipRte>::iterator iter = rtes.begin ();
|
||||
iter != rtes.end (); iter++)
|
||||
{
|
||||
if (iter->GetPrefix () == "10.0.1.0")
|
||||
{
|
||||
bool correct = false;
|
||||
if (iter->GetRouteMetric () == 16)
|
||||
{
|
||||
correct = true;
|
||||
m_detectedStrategy = Rip::POISON_REVERSE;
|
||||
}
|
||||
else if (iter->GetRouteMetric () == 2)
|
||||
{
|
||||
correct = true;
|
||||
m_detectedStrategy = Rip::NO_SPLIT_HORIZON;
|
||||
}
|
||||
NS_TEST_EXPECT_MSG_EQ (correct, true, "RIP: unexpected metric value: " << iter->GetRouteMetric ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//cast availableData to void, to suppress 'availableData' set but not used
|
||||
//compiler warning
|
||||
(void) availableData;
|
||||
}
|
||||
|
||||
void
|
||||
Ipv4RipSplitHorizonStrategyTest::DoRun (void)
|
||||
{
|
||||
// Create topology
|
||||
|
||||
Ptr<Node> fakeNode = CreateObject<Node> ();
|
||||
Ptr<Node> listener = CreateObject<Node> ();
|
||||
|
||||
Ptr<Node> routerA = CreateObject<Node> ();
|
||||
Ptr<Node> routerB = CreateObject<Node> ();
|
||||
|
||||
NodeContainer listeners (listener, fakeNode);
|
||||
NodeContainer routers (routerA, routerB);
|
||||
NodeContainer all (routers, listeners);
|
||||
|
||||
RipHelper ripNgRouting;
|
||||
ripNgRouting.Set ("SplitHorizon", EnumValue (m_setStrategy));
|
||||
|
||||
InternetStackHelper internetRouters;
|
||||
internetRouters.SetRoutingHelper (ripNgRouting);
|
||||
internetRouters.Install (routers);
|
||||
|
||||
InternetStackHelper internetNodes;
|
||||
internetNodes.Install (listeners);
|
||||
|
||||
NetDeviceContainer net0;
|
||||
NetDeviceContainer net1;
|
||||
|
||||
// Fake Node
|
||||
Ptr<SimpleNetDevice> silentDev;
|
||||
{
|
||||
silentDev = CreateObject<SimpleNetDevice> ();
|
||||
silentDev->SetAddress (Mac48Address ("00:00:00:00:00:01"));
|
||||
fakeNode->AddDevice (silentDev);
|
||||
}
|
||||
net0.Add (silentDev);
|
||||
|
||||
// Router A
|
||||
Ptr<SimpleNetDevice> silentDevRouterA, fwDevRouterA;
|
||||
{ // silent interface
|
||||
silentDevRouterA = CreateObject<SimpleNetDevice> ();
|
||||
silentDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:02"));
|
||||
routerA->AddDevice (silentDevRouterA);
|
||||
}
|
||||
net0.Add (silentDevRouterA);
|
||||
|
||||
{ // first interface
|
||||
fwDevRouterA = CreateObject<SimpleNetDevice> ();
|
||||
fwDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:03"));
|
||||
routerA->AddDevice (fwDevRouterA);
|
||||
}
|
||||
net1.Add (fwDevRouterA);
|
||||
|
||||
// Router B
|
||||
Ptr<SimpleNetDevice> fwDevRouterB;
|
||||
{ // first interface
|
||||
fwDevRouterB = CreateObject<SimpleNetDevice> ();
|
||||
fwDevRouterB->SetAddress (Mac48Address ("00:00:00:00:00:04"));
|
||||
routerB->AddDevice (fwDevRouterB);
|
||||
}
|
||||
net1.Add (fwDevRouterB);
|
||||
|
||||
// listener A
|
||||
Ptr<SimpleNetDevice> listenerDev;
|
||||
{
|
||||
listenerDev = CreateObject<SimpleNetDevice> ();
|
||||
listenerDev->SetAddress (Mac48Address ("00:00:00:00:00:05"));
|
||||
listener->AddDevice (listenerDev);
|
||||
}
|
||||
net1.Add (listenerDev);
|
||||
|
||||
// link the channels
|
||||
Ptr<SimpleChannel> channel0 = CreateObject<SimpleChannel> ();
|
||||
silentDev->SetChannel (channel0);
|
||||
silentDevRouterA->SetChannel (channel0);
|
||||
|
||||
Ptr<SimpleChannel> channel1 = CreateObject<SimpleChannel> ();
|
||||
fwDevRouterA->SetChannel (channel1);
|
||||
fwDevRouterB->SetChannel (channel1);
|
||||
listenerDev->SetChannel (channel1);
|
||||
|
||||
// Setup IPv6 addresses and forwarding
|
||||
Ipv4AddressHelper ipv4;
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("10.0.1.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic0 = ipv4.Assign (net0);
|
||||
|
||||
ipv4.SetBase (Ipv4Address ("192.168.0.0"), Ipv4Mask ("255.255.255.0"));
|
||||
Ipv4InterfaceContainer iic1 = ipv4.Assign (net1);
|
||||
|
||||
// Create the UDP sockets
|
||||
Ptr<SocketFactory> rxSocketFactory = listener->GetObject<UdpSocketFactory> ();
|
||||
Ptr<Socket> rxSocket = rxSocketFactory->CreateSocket ();
|
||||
NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (InetSocketAddress (Ipv4Address ("224.0.0.9"), 520)), 0, "trivial");
|
||||
rxSocket->BindToNetDevice (listenerDev);
|
||||
rxSocket->SetRecvCallback (MakeCallback (&Ipv4RipSplitHorizonStrategyTest::ReceivePktProbe, this));
|
||||
|
||||
// ------ Now the tests ------------
|
||||
|
||||
// If the strategy is Split Horizon, then no packet will be received.
|
||||
m_detectedStrategy = Rip::SPLIT_HORIZON;
|
||||
|
||||
Simulator::Stop (Seconds (66));
|
||||
Simulator::Run ();
|
||||
NS_TEST_EXPECT_MSG_EQ (m_detectedStrategy, m_setStrategy, "RIP counting to infinity.");
|
||||
|
||||
Simulator::Destroy ();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
class Ipv4RipTestSuite : public TestSuite
|
||||
{
|
||||
public:
|
||||
Ipv4RipTestSuite () : TestSuite ("ipv4-rip", UNIT)
|
||||
{
|
||||
AddTestCase (new Ipv4RipTest, TestCase::QUICK);
|
||||
AddTestCase (new Ipv4RipCountToInfinityTest, TestCase::QUICK);
|
||||
AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::POISON_REVERSE), TestCase::QUICK);
|
||||
AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::SPLIT_HORIZON), TestCase::QUICK);
|
||||
AddTestCase (new Ipv4RipSplitHorizonStrategyTest (Rip::NO_SPLIT_HORIZON), TestCase::QUICK);
|
||||
}
|
||||
} g_ipv4ripTestSuite;
|
||||
@@ -206,6 +206,9 @@ def build(bld):
|
||||
'model/ripng.cc',
|
||||
'model/ripng-header.cc',
|
||||
'helper/ripng-helper.cc',
|
||||
'model/rip.cc',
|
||||
'model/rip-header.cc',
|
||||
'helper/rip-helper.cc',
|
||||
]
|
||||
|
||||
internet_test = bld.create_ns3_module_test_library('internet')
|
||||
@@ -256,6 +259,8 @@ def build(bld):
|
||||
'test/codel-queue-test-suite.cc',
|
||||
'test/tcp-endpoint-bug2211.cc',
|
||||
'test/tcp-datasentcb-test.cc',
|
||||
'test/ipv4-rip-test.cc',
|
||||
|
||||
]
|
||||
privateheaders = bld(features='ns3privateheader')
|
||||
privateheaders.module = 'internet'
|
||||
@@ -351,6 +356,9 @@ def build(bld):
|
||||
'model/ripng.h',
|
||||
'model/ripng-header.h',
|
||||
'helper/ripng-helper.h',
|
||||
'model/rip.h',
|
||||
'model/rip-header.h',
|
||||
'helper/rip-helper.h',
|
||||
]
|
||||
|
||||
if bld.env['NSC_ENABLED']:
|
||||
|
||||
Reference in New Issue
Block a user