internet: RIPv2 implementation

This commit is contained in:
Tommaso Pecorella
2016-02-25 16:30:34 -08:00
parent b135f2260b
commit dd90b30eaa
11 changed files with 3589 additions and 18 deletions

View 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.");
}

View File

@@ -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'

View File

@@ -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.

View 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;
}
}

View 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 */

View 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;
}
}

View 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

File diff suppressed because it is too large Load Diff

409
src/internet/model/rip.h Normal file
View 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 */

View 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;

View File

@@ -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']: