From f3a3fb85b17c89351f8471317bc4e8ebb62fa892 Mon Sep 17 00:00:00 2001 From: Tommaso Pecorella Date: Mon, 17 Mar 2014 20:01:49 +0100 Subject: [PATCH] RIPng implementation --- RELEASE_NOTES | 2 + examples/routing/ripng-simple-network.cc | 268 ++++ examples/routing/wscript | 4 + src/applications/model/ping6.cc | 22 +- src/internet/bindings/modulegen__gcc_ILP32.py | 359 +++++ src/internet/bindings/modulegen__gcc_LP64.py | 359 +++++ src/internet/doc/routing-overview.rst | 142 +- src/internet/helper/ripng-helper.cc | 182 +++ src/internet/helper/ripng-helper.h | 148 ++ src/internet/model/ipv6-routing-table-entry.h | 2 +- src/internet/model/ripng-header.cc | 255 +++ src/internet/model/ripng-header.h | 226 +++ src/internet/model/ripng.cc | 1382 +++++++++++++++++ src/internet/model/ripng.h | 411 +++++ src/internet/test/ipv6-ripng-test.cc | 652 ++++++++ src/internet/wscript | 9 +- 16 files changed, 4403 insertions(+), 20 deletions(-) create mode 100644 examples/routing/ripng-simple-network.cc create mode 100644 src/internet/helper/ripng-helper.cc create mode 100644 src/internet/helper/ripng-helper.h create mode 100644 src/internet/model/ripng-header.cc create mode 100644 src/internet/model/ripng-header.h create mode 100644 src/internet/model/ripng.cc create mode 100644 src/internet/model/ripng.h create mode 100644 src/internet/test/ipv6-ripng-test.cc diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 9837883d1..6207b728f 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -36,6 +36,8 @@ New user-visible features is now fired when appropriate. - FlowMonitor does not track anymore multicast/broadcast packets, reflecting its original design. +- A new IPv6 routing protocol has been added: RIPng. This protocol is + an Interior Gateway Protocol and it is available in the Internet module. Bugs fixed ---------- diff --git a/examples/routing/ripng-simple-network.cc b/examples/routing/ripng-simple-network.cc new file mode 100644 index 000000000..7c95479ea --- /dev/null +++ b/examples/routing/ripng-simple-network.cc @@ -0,0 +1,268 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +// 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 +#include "ns3/core-module.h" +#include "ns3/internet-module.h" +#include "ns3/csma-module.h" +#include "ns3/applications-module.h" +#include "ns3/ipv6-static-routing-helper.h" +#include "ns3/ipv6-routing-table-entry.h" + +using namespace ns3; + +NS_LOG_COMPONENT_DEFINE ("RipNgSimpleRouting"); + +void TearDownLink (Ptr nodeA, Ptr nodeB, uint32_t interfaceA, uint32_t interfaceB) +{ + nodeA->GetObject ()->SetDown (interfaceA); + nodeB->GetObject ()->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) + { + LogComponentEnable ("RipNgSimpleRouting", LOG_LEVEL_INFO); + LogComponentEnable ("RipNg", LOG_LEVEL_ALL); + LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_INFO); + LogComponentEnable ("Ipv6Interface", LOG_LEVEL_ALL); + LogComponentEnable ("Icmpv6L4Protocol", LOG_LEVEL_ALL); + LogComponentEnable ("NdiscCache", LOG_LEVEL_ALL); + LogComponentEnable ("Ping6Application", LOG_LEVEL_ALL); + } + + if (showPings) + { + LogComponentEnable ("Ping6Application", LOG_LEVEL_INFO); + } + + if (SplitHorizon == "NoSplitHorizon") + { + Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::NO_SPLIT_HORIZON)); + } + else if (SplitHorizon == "SplitHorizon") + { + Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::SPLIT_HORIZON)); + } + else + { + Config::SetDefault ("ns3::RipNg::SplitHorizon", EnumValue (RipNg::POISON_REVERSE)); + } + + NS_LOG_INFO ("Create nodes."); + Ptr src = CreateObject (); + Names::Add ("SrcNode", src); + Ptr dst = CreateObject (); + Names::Add ("DstNode", dst); + Ptr a = CreateObject (); + Names::Add ("RouterA", a); + Ptr b = CreateObject (); + Names::Add ("RouterB", b); + Ptr c = CreateObject (); + Names::Add ("RouterC", c); + Ptr d = CreateObject (); + 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 IPv6 and routing"); + RipNgHelper ripNgRouting; + + // Rule of thumb: + // Interfaces are added sequentially, starting from 0 + // However, interface 0 is always the loopback... + ripNgRouting.ExcludeInterface (a, 1); + ripNgRouting.ExcludeInterface (d, 3); + + ripNgRouting.SetInterfaceMetric (c, 3, 10); + ripNgRouting.SetInterfaceMetric (d, 1, 10); + + Ipv6ListRoutingHelper listRH; + listRH.Add (ripNgRouting, 0); + + InternetStackHelper internetv6; + internetv6.SetIpv4StackInstall (false); + internetv6.SetRoutingHelper (listRH); + internetv6.Install (routers); + + InternetStackHelper internetv6Nodes; + internetv6Nodes.SetIpv4StackInstall (false); + internetv6Nodes.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 IPv6 Addresses."); + Ipv6AddressHelper ipv6; + + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic1 = ipv6.Assign (ndc1); + iic1.SetForwarding (1, true); + iic1.SetDefaultRouteInAllNodes (1); + + ipv6.SetBase (Ipv6Address ("2001:0:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic2 = ipv6.Assign (ndc2); + iic2.SetForwarding (0, true); + iic2.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:0:2::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic3 = ipv6.Assign (ndc3); + iic3.SetForwarding (0, true); + iic3.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:0:3::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic4 = ipv6.Assign (ndc4); + iic4.SetForwarding (0, true); + iic4.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:0:4::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic5 = ipv6.Assign (ndc5); + iic5.SetForwarding (0, true); + iic5.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:0:5::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic6 = ipv6.Assign (ndc6); + iic6.SetForwarding (0, true); + iic6.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic7 = ipv6.Assign (ndc7); + iic7.SetForwarding (0, true); + iic7.SetDefaultRouteInAllNodes (0); + + if (printRoutingTables) + { + RipNgHelper routingHelper; + + Ptr routingStream = Create (&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; + uint32_t maxPacketCount = 100; + Time interPacketInterval = Seconds (1.0); + Ping6Helper ping6; + + ping6.SetLocal (iic1.GetAddress (0, 1)); + ping6.SetRemote (iic7.GetAddress (1, 1)); + ping6.SetAttribute ("MaxPackets", UintegerValue (maxPacketCount)); + ping6.SetAttribute ("Interval", TimeValue (interPacketInterval)); + ping6.SetAttribute ("PacketSize", UintegerValue (packetSize)); + ApplicationContainer apps = ping6.Install (src); + apps.Start (Seconds (1.0)); + apps.Stop (Seconds (110.0)); + + AsciiTraceHelper ascii; + csma.EnableAsciiAll (ascii.CreateFileStream ("ripng-simple-routing.tr")); + csma.EnablePcapAll ("ripng-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 (120)); + Simulator::Run (); + Simulator::Destroy (); + NS_LOG_INFO ("Done."); +} + diff --git a/examples/routing/wscript b/examples/routing/wscript index 7d9d1ae03..8fba0e9c7 100644 --- a/examples/routing/wscript +++ b/examples/routing/wscript @@ -37,4 +37,8 @@ def build(bld): ['wifi', 'dsr', 'dsdv', 'aodv', 'olsr', 'internet', 'applications']) obj.source = 'manet-routing-compare.cc' + obj = bld.create_ns3_program('ripng-simple-network', + ['csma', 'internet', 'applications']) + obj.source = 'ripng-simple-network.cc' + bld.register_ns3_script('simple-routing-ping6.py', ['csma', 'internet', 'applications']) diff --git a/src/applications/model/ping6.cc b/src/applications/model/ping6.cc index 4e66fad67..bee27069b 100644 --- a/src/applications/model/ping6.cc +++ b/src/applications/model/ping6.cc @@ -109,7 +109,6 @@ void Ping6::StartApplication () NS_ASSERT (m_socket); m_socket->Bind (Inet6SocketAddress (m_localAddress, 0)); - m_socket->Connect (Inet6SocketAddress (m_peerAddress, 0)); m_socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_ICMPV6)); m_socket->SetRecvCallback (MakeCallback (&Ping6::HandleRead, this)); } @@ -222,7 +221,7 @@ void Ping6::Send () m_socket->SetAttribute ("Protocol", UintegerValue (Ipv6Header::IPV6_EXT_ROUTING)); } - m_socket->Send (p, 0); + m_socket->SendTo (p, 0, Inet6SocketAddress (m_peerAddress, 0)); ++m_sent; NS_LOG_INFO ("Sent " << p->GetSize () << " bytes to " << m_peerAddress); @@ -247,6 +246,8 @@ void Ping6::HandleRead (Ptr socket) { Ipv6Header hdr; Icmpv6Echo reply (0); + Icmpv6DestinationUnreachable destUnreach; + Icmpv6TimeExceeded timeExceeded; Inet6SocketAddress address = Inet6SocketAddress::ConvertFrom (from); packet->RemoveHeader (hdr); @@ -259,10 +260,23 @@ void Ping6::HandleRead (Ptr socket) case Icmpv6Header::ICMPV6_ECHO_REPLY: packet->RemoveHeader (reply); - NS_LOG_INFO ("Received Echo Reply size = " << std::dec << packet->GetSize () << " bytes from " << address.GetIpv6 () << " id = " << (uint16_t)reply.GetId () << " seq = " << (uint16_t)reply.GetSeq ()); + NS_LOG_INFO ("Received Echo Reply size = " << std::dec << packet->GetSize () << + " bytes from " << address.GetIpv6 () << + " id = " << (uint16_t)reply.GetId () << + " seq = " << (uint16_t)reply.GetSeq () << + " Hop Count = " << (uint16_t) (64 - hdr.GetHopLimit ())); + break; + case Icmpv6Header::ICMPV6_ERROR_DESTINATION_UNREACHABLE: + packet->RemoveHeader (destUnreach); + + NS_LOG_INFO ("Received Destination Unreachable from " << address.GetIpv6 ()); + break; + case Icmpv6Header::ICMPV6_ERROR_TIME_EXCEEDED: + packet->RemoveHeader (timeExceeded); + + NS_LOG_INFO ("Received Time Exceeded from " << address.GetIpv6 ()); break; default: - /* other type, discard */ break; } } diff --git a/src/internet/bindings/modulegen__gcc_ILP32.py b/src/internet/bindings/modulegen__gcc_ILP32.py index 386d1686d..df4e62dd4 100644 --- a/src/internet/bindings/modulegen__gcc_ILP32.py +++ b/src/internet/bindings/modulegen__gcc_ILP32.py @@ -210,6 +210,12 @@ def register_types(module): module.add_class('PcapHelperForIpv4', allow_subclassing=True) ## internet-trace-helper.h (module 'internet'): ns3::PcapHelperForIpv6 [class] module.add_class('PcapHelperForIpv6', allow_subclassing=True) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper [class] + module.add_class('RipNgHelper', parent=root_module['ns3::Ipv6RoutingHelper']) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry [class] + module.add_class('RipNgRoutingTableEntry', parent=root_module['ns3::Ipv6RoutingTableEntry']) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e [enumeration] + module.add_enum('Status_e', ['RIPNG_VALID', 'RIPNG_INVALID'], outer_class=root_module['ns3::RipNgRoutingTableEntry']) ## rtt-estimator.h (module 'internet'): ns3::RttHistory [class] module.add_class('RttHistory') ## global-route-manager-impl.h (module 'internet'): ns3::SPFVertex [class] @@ -226,6 +232,8 @@ def register_types(module): module.add_class('Tag', import_from_module='ns.network', parent=root_module['ns3::ObjectBase']) ## tag-buffer.h (module 'network'): ns3::TagBuffer [class] module.add_class('TagBuffer', import_from_module='ns.network') + ## nstime.h (module 'core'): ns3::TimeWithUnit [class] + module.add_class('TimeWithUnit', import_from_module='ns.core') ## timer.h (module 'core'): ns3::Timer [class] module.add_class('Timer', import_from_module='ns.core') ## timer.h (module 'core'): ns3::Timer::DestroyPolicy [enumeration] @@ -362,6 +370,12 @@ def register_types(module): module.add_class('PcapFileWrapper', import_from_module='ns.network', parent=root_module['ns3::Object']) ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream [class] module.add_class('RandomVariableStream', import_from_module='ns.core', parent=root_module['ns3::Object']) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader [class] + module.add_class('RipNgHeader', parent=root_module['ns3::Header']) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::Command_e [enumeration] + module.add_enum('Command_e', ['REQUEST', 'RESPONSE'], outer_class=root_module['ns3::RipNgHeader']) + ## ripng-header.h (module 'internet'): ns3::RipNgRte [class] + module.add_class('RipNgRte', parent=root_module['ns3::Header']) ## rtt-estimator.h (module 'internet'): ns3::RttEstimator [class] module.add_class('RttEstimator', parent=root_module['ns3::Object']) ## rtt-estimator.h (module 'internet'): ns3::RttMeanDeviation [class] @@ -648,6 +662,10 @@ def register_types(module): module.add_class('ParetoRandomVariable', import_from_module='ns.core', parent=root_module['ns3::RandomVariableStream']) ## probe.h (module 'stats'): ns3::Probe [class] module.add_class('Probe', import_from_module='ns.stats', parent=root_module['ns3::DataCollectionObject']) + ## ripng.h (module 'internet'): ns3::RipNg [class] + module.add_class('RipNg', parent=root_module['ns3::Ipv6RoutingProtocol']) + ## ripng.h (module 'internet'): ns3::RipNg::SplitHorizonType_e [enumeration] + module.add_enum('SplitHorizonType_e', ['NO_SPLIT_HORIZON', 'SPLIT_HORIZON', 'POISON_REVERSE'], outer_class=root_module['ns3::RipNg']) ## tcp-l4-protocol.h (module 'internet'): ns3::TcpL4Protocol [class] module.add_class('TcpL4Protocol', parent=root_module['ns3::IpL4Protocol']) ## tcp-newreno.h (module 'internet'): ns3::TcpNewReno [class] @@ -694,10 +712,12 @@ def register_types(module): module.add_class('LoopbackNetDevice', parent=root_module['ns3::NetDevice']) module.add_container('std::vector< unsigned int >', 'unsigned int', container_type=u'vector') module.add_container('std::vector< bool >', 'bool', container_type=u'vector') + module.add_container('std::list< ns3::RipNgRte >', 'ns3::RipNgRte', container_type=u'list') module.add_container('std::map< ns3::SequenceNumber< unsigned int, int >, ns3::Ptr< ns3::Packet > >', ('ns3::SequenceNumber< unsigned int, int >', 'ns3::Ptr< ns3::Packet >'), container_type=u'map') module.add_container('std::list< ns3::Ptr< ns3::Packet > >', 'ns3::Ptr< ns3::Packet >', container_type=u'list') module.add_container('std::map< unsigned int, unsigned int >', ('unsigned int', 'unsigned int'), container_type=u'map') module.add_container('std::vector< ns3::Ipv6Address >', 'ns3::Ipv6Address', container_type=u'vector') + module.add_container('std::set< unsigned int >', 'unsigned int', container_type=u'set') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >', u'ns3::SequenceNumber16') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >*', u'ns3::SequenceNumber16*') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >&', u'ns3::SequenceNumber16&') @@ -837,6 +857,8 @@ def register_methods(root_module): register_Ns3PcapHelperForDevice_methods(root_module, root_module['ns3::PcapHelperForDevice']) register_Ns3PcapHelperForIpv4_methods(root_module, root_module['ns3::PcapHelperForIpv4']) register_Ns3PcapHelperForIpv6_methods(root_module, root_module['ns3::PcapHelperForIpv6']) + register_Ns3RipNgHelper_methods(root_module, root_module['ns3::RipNgHelper']) + register_Ns3RipNgRoutingTableEntry_methods(root_module, root_module['ns3::RipNgRoutingTableEntry']) register_Ns3RttHistory_methods(root_module, root_module['ns3::RttHistory']) register_Ns3SPFVertex_methods(root_module, root_module['ns3::SPFVertex']) register_Ns3SequenceNumber32_methods(root_module, root_module['ns3::SequenceNumber32']) @@ -844,6 +866,7 @@ def register_methods(root_module): register_Ns3Simulator_methods(root_module, root_module['ns3::Simulator']) register_Ns3Tag_methods(root_module, root_module['ns3::Tag']) register_Ns3TagBuffer_methods(root_module, root_module['ns3::TagBuffer']) + register_Ns3TimeWithUnit_methods(root_module, root_module['ns3::TimeWithUnit']) register_Ns3Timer_methods(root_module, root_module['ns3::Timer']) register_Ns3TimerImpl_methods(root_module, root_module['ns3::TimerImpl']) register_Ns3TracedValue__Double_methods(root_module, root_module['ns3::TracedValue< double >']) @@ -896,6 +919,8 @@ def register_methods(root_module): register_Ns3ObjectAggregateIterator_methods(root_module, root_module['ns3::Object::AggregateIterator']) register_Ns3PcapFileWrapper_methods(root_module, root_module['ns3::PcapFileWrapper']) register_Ns3RandomVariableStream_methods(root_module, root_module['ns3::RandomVariableStream']) + register_Ns3RipNgHeader_methods(root_module, root_module['ns3::RipNgHeader']) + register_Ns3RipNgRte_methods(root_module, root_module['ns3::RipNgRte']) register_Ns3RttEstimator_methods(root_module, root_module['ns3::RttEstimator']) register_Ns3RttMeanDeviation_methods(root_module, root_module['ns3::RttMeanDeviation']) register_Ns3SequentialRandomVariable_methods(root_module, root_module['ns3::SequentialRandomVariable']) @@ -1026,6 +1051,7 @@ def register_methods(root_module): register_Ns3Packet_methods(root_module, root_module['ns3::Packet']) register_Ns3ParetoRandomVariable_methods(root_module, root_module['ns3::ParetoRandomVariable']) register_Ns3Probe_methods(root_module, root_module['ns3::Probe']) + register_Ns3RipNg_methods(root_module, root_module['ns3::RipNg']) register_Ns3TcpL4Protocol_methods(root_module, root_module['ns3::TcpL4Protocol']) register_Ns3TcpNewReno_methods(root_module, root_module['ns3::TcpNewReno']) register_Ns3TcpReno_methods(root_module, root_module['ns3::TcpReno']) @@ -4337,6 +4363,91 @@ def register_Ns3PcapHelperForIpv6_methods(root_module, cls): is_pure_virtual=True, is_virtual=True) return +def register_Ns3RipNgHelper_methods(root_module, cls): + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper::RipNgHelper() [constructor] + cls.add_constructor([]) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper::RipNgHelper(ns3::RipNgHelper const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgHelper const &', 'arg0')]) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper * ns3::RipNgHelper::Copy() const [member function] + cls.add_method('Copy', + 'ns3::RipNgHelper *', + [], + is_const=True, is_virtual=True) + ## ripng-helper.h (module 'internet'): ns3::Ptr ns3::RipNgHelper::Create(ns3::Ptr node) const [member function] + cls.add_method('Create', + 'ns3::Ptr< ns3::Ipv6RoutingProtocol >', + [param('ns3::Ptr< ns3::Node >', 'node')], + is_const=True, is_virtual=True) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::Set(std::string name, ns3::AttributeValue const & value) [member function] + cls.add_method('Set', + 'void', + [param('std::string', 'name'), param('ns3::AttributeValue const &', 'value')]) + ## ripng-helper.h (module 'internet'): int64_t ns3::RipNgHelper::AssignStreams(ns3::NodeContainer c, int64_t stream) [member function] + cls.add_method('AssignStreams', + 'int64_t', + [param('ns3::NodeContainer', 'c'), param('int64_t', 'stream')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::SetDefaultRouter(ns3::Ptr node, ns3::Ipv6Address nextHop, uint32_t interface) [member function] + cls.add_method('SetDefaultRouter', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::ExcludeInterface(ns3::Ptr node, uint32_t interface) [member function] + cls.add_method('ExcludeInterface', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('uint32_t', 'interface')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::SetInterfaceMetric(ns3::Ptr node, uint32_t interface, uint8_t metric) [member function] + cls.add_method('SetInterfaceMetric', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('uint32_t', 'interface'), param('uint8_t', 'metric')]) + return + +def register_Ns3RipNgRoutingTableEntry_methods(root_module, cls): + cls.add_output_stream_operator() + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::RipNgRoutingTableEntry const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgRoutingTableEntry const &', 'arg0')]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry() [constructor] + cls.add_constructor([]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::Ipv6Address network, ns3::Ipv6Prefix networkPrefix, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse) [constructor] + cls.add_constructor([param('ns3::Ipv6Address', 'network'), param('ns3::Ipv6Prefix', 'networkPrefix'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse')]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::Ipv6Address network, ns3::Ipv6Prefix networkPrefix, uint32_t interface) [constructor] + cls.add_constructor([param('ns3::Ipv6Address', 'network'), param('ns3::Ipv6Prefix', 'networkPrefix'), param('uint32_t', 'interface')]) + ## ripng.h (module 'internet'): uint8_t ns3::RipNgRoutingTableEntry::GetRouteMetric() const [member function] + cls.add_method('GetRouteMetric', + 'uint8_t', + [], + is_const=True) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e ns3::RipNgRoutingTableEntry::GetRouteStatus() const [member function] + cls.add_method('GetRouteStatus', + 'ns3::RipNgRoutingTableEntry::Status_e', + [], + is_const=True) + ## ripng.h (module 'internet'): uint16_t ns3::RipNgRoutingTableEntry::GetRouteTag() const [member function] + cls.add_method('GetRouteTag', + 'uint16_t', + [], + is_const=True) + ## ripng.h (module 'internet'): bool ns3::RipNgRoutingTableEntry::IsRouteChanged() const [member function] + cls.add_method('IsRouteChanged', + 'bool', + [], + is_const=True) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteChanged(bool changed) [member function] + cls.add_method('SetRouteChanged', + 'void', + [param('bool', 'changed')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteMetric(uint8_t routeMetric) [member function] + cls.add_method('SetRouteMetric', + 'void', + [param('uint8_t', 'routeMetric')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteStatus(ns3::RipNgRoutingTableEntry::Status_e status) [member function] + cls.add_method('SetRouteStatus', + 'void', + [param('ns3::RipNgRoutingTableEntry::Status_e', 'status')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteTag(uint16_t routeTag) [member function] + cls.add_method('SetRouteTag', + 'void', + [param('uint16_t', 'routeTag')]) + return + def register_Ns3RttHistory_methods(root_module, cls): ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor] cls.add_constructor([param('ns3::SequenceNumber32', 's'), param('uint32_t', 'c'), param('ns3::Time', 't')]) @@ -4678,6 +4789,14 @@ def register_Ns3TagBuffer_methods(root_module, cls): [param('uint8_t', 'v')]) return +def register_Ns3TimeWithUnit_methods(root_module, cls): + cls.add_output_stream_operator() + ## nstime.h (module 'core'): ns3::TimeWithUnit::TimeWithUnit(ns3::TimeWithUnit const & arg0) [copy constructor] + cls.add_constructor([param('ns3::TimeWithUnit const &', 'arg0')]) + ## nstime.h (module 'core'): ns3::TimeWithUnit::TimeWithUnit(ns3::Time const time, ns3::Time::Unit const unit) [constructor] + cls.add_constructor([param('ns3::Time const', 'time'), param('ns3::Time::Unit const', 'unit')]) + return + def register_Ns3Timer_methods(root_module, cls): ## timer.h (module 'core'): ns3::Timer::Timer(ns3::Timer const & arg0) [copy constructor] cls.add_constructor([param('ns3::Timer const &', 'arg0')]) @@ -7499,6 +7618,143 @@ def register_Ns3RandomVariableStream_methods(root_module, cls): is_const=True, visibility='protected') return +def register_Ns3RipNgHeader_methods(root_module, cls): + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::RipNgHeader(ns3::RipNgHeader const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgHeader const &', 'arg0')]) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::RipNgHeader() [constructor] + cls.add_constructor([]) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::AddRte(ns3::RipNgRte rte) [member function] + cls.add_method('AddRte', + 'void', + [param('ns3::RipNgRte', 'rte')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::ClearRtes() [member function] + cls.add_method('ClearRtes', + 'void', + []) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgHeader::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::Command_e ns3::RipNgHeader::GetCommand() const [member function] + cls.add_method('GetCommand', + 'ns3::RipNgHeader::Command_e', + [], + is_const=True) + ## ripng-header.h (module 'internet'): ns3::TypeId ns3::RipNgHeader::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): std::list > ns3::RipNgHeader::GetRteList() const [member function] + cls.add_method('GetRteList', + 'std::list< ns3::RipNgRte >', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint16_t ns3::RipNgHeader::GetRteNumber() const [member function] + cls.add_method('GetRteNumber', + 'uint16_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgHeader::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): static ns3::TypeId ns3::RipNgHeader::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::SetCommand(ns3::RipNgHeader::Command_e command) [member function] + cls.add_method('SetCommand', + 'void', + [param('ns3::RipNgHeader::Command_e', 'command')]) + return + +def register_Ns3RipNgRte_methods(root_module, cls): + ## ripng-header.h (module 'internet'): ns3::RipNgRte::RipNgRte(ns3::RipNgRte const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgRte const &', 'arg0')]) + ## ripng-header.h (module 'internet'): ns3::RipNgRte::RipNgRte() [constructor] + cls.add_constructor([]) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgRte::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::TypeId ns3::RipNgRte::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::Ipv6Address ns3::RipNgRte::GetPrefix() const [member function] + cls.add_method('GetPrefix', + 'ns3::Ipv6Address', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint8_t ns3::RipNgRte::GetPrefixLen() const [member function] + cls.add_method('GetPrefixLen', + 'uint8_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint8_t ns3::RipNgRte::GetRouteMetric() const [member function] + cls.add_method('GetRouteMetric', + 'uint8_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint16_t ns3::RipNgRte::GetRouteTag() const [member function] + cls.add_method('GetRouteTag', + 'uint16_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgRte::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): static ns3::TypeId ns3::RipNgRte::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetPrefix(ns3::Ipv6Address prefix) [member function] + cls.add_method('SetPrefix', + 'void', + [param('ns3::Ipv6Address', 'prefix')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetPrefixLen(uint8_t prefixLen) [member function] + cls.add_method('SetPrefixLen', + 'void', + [param('uint8_t', 'prefixLen')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetRouteMetric(uint8_t routeMetric) [member function] + cls.add_method('SetRouteMetric', + 'void', + [param('uint8_t', 'routeMetric')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetRouteTag(uint16_t routeTag) [member function] + cls.add_method('SetRouteTag', + 'void', + [param('uint16_t', 'routeTag')]) + return + def register_Ns3RttEstimator_methods(root_module, cls): ## rtt-estimator.h (module 'internet'): ns3::RttEstimator::RttEstimator() [constructor] cls.add_constructor([]) @@ -9555,6 +9811,11 @@ def register_Ns3Time_methods(root_module, cls): cls.add_constructor([param('std::string const &', 's')]) ## nstime.h (module 'core'): ns3::Time::Time(ns3::int64x64_t const & value) [constructor] cls.add_constructor([param('ns3::int64x64_t const &', 'value')]) + ## nstime.h (module 'core'): ns3::TimeWithUnit ns3::Time::As(ns3::Time::Unit const unit) const [member function] + cls.add_method('As', + 'ns3::TimeWithUnit', + [param('ns3::Time::Unit const', 'unit')], + is_const=True) ## nstime.h (module 'core'): int ns3::Time::Compare(ns3::Time const & o) const [member function] cls.add_method('Compare', 'int', @@ -14674,6 +14935,104 @@ def register_Ns3Probe_methods(root_module, cls): is_const=True, is_virtual=True) return +def register_Ns3RipNg_methods(root_module, cls): + ## ripng.h (module 'internet'): ns3::RipNg::RipNg(ns3::RipNg const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNg const &', 'arg0')]) + ## ripng.h (module 'internet'): ns3::RipNg::RipNg() [constructor] + cls.add_constructor([]) + ## ripng.h (module 'internet'): void ns3::RipNg::AddDefaultRouteTo(ns3::Ipv6Address nextHop, uint32_t interface) [member function] + cls.add_method('AddDefaultRouteTo', + 'void', + [param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface')]) + ## ripng.h (module 'internet'): int64_t ns3::RipNg::AssignStreams(int64_t stream) [member function] + cls.add_method('AssignStreams', + 'int64_t', + [param('int64_t', 'stream')]) + ## ripng.h (module 'internet'): std::set, std::allocator > ns3::RipNg::GetInterfaceExclusions() const [member function] + cls.add_method('GetInterfaceExclusions', + 'std::set< unsigned int >', + [], + is_const=True) + ## ripng.h (module 'internet'): uint8_t ns3::RipNg::GetInterfaceMetric(uint32_t interface) const [member function] + cls.add_method('GetInterfaceMetric', + 'uint8_t', + [param('uint32_t', 'interface')], + is_const=True) + ## ripng.h (module 'internet'): static ns3::TypeId ns3::RipNg::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyAddAddress(uint32_t interface, ns3::Ipv6InterfaceAddress address) [member function] + cls.add_method('NotifyAddAddress', + 'void', + [param('uint32_t', 'interface'), param('ns3::Ipv6InterfaceAddress', 'address')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyAddRoute(ns3::Ipv6Address dst, ns3::Ipv6Prefix mask, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse=ns3::Ipv6Address::GetZero( )) [member function] + cls.add_method('NotifyAddRoute', + 'void', + [param('ns3::Ipv6Address', 'dst'), param('ns3::Ipv6Prefix', 'mask'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse', default_value='ns3::Ipv6Address::GetZero( )')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyInterfaceDown(uint32_t interface) [member function] + cls.add_method('NotifyInterfaceDown', + 'void', + [param('uint32_t', 'interface')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyInterfaceUp(uint32_t interface) [member function] + cls.add_method('NotifyInterfaceUp', + 'void', + [param('uint32_t', 'interface')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyRemoveAddress(uint32_t interface, ns3::Ipv6InterfaceAddress address) [member function] + cls.add_method('NotifyRemoveAddress', + 'void', + [param('uint32_t', 'interface'), param('ns3::Ipv6InterfaceAddress', 'address')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyRemoveRoute(ns3::Ipv6Address dst, ns3::Ipv6Prefix mask, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse=ns3::Ipv6Address::GetZero( )) [member function] + cls.add_method('NotifyRemoveRoute', + 'void', + [param('ns3::Ipv6Address', 'dst'), param('ns3::Ipv6Prefix', 'mask'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse', default_value='ns3::Ipv6Address::GetZero( )')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::PrintRoutingTable(ns3::Ptr stream) const [member function] + cls.add_method('PrintRoutingTable', + 'void', + [param('ns3::Ptr< ns3::OutputStreamWrapper >', 'stream')], + is_const=True, is_virtual=True) + ## ripng.h (module 'internet'): bool ns3::RipNg::RouteInput(ns3::Ptr p, ns3::Ipv6Header const & header, ns3::Ptr idev, ns3::Callback,ns3::Ptr,ns3::Ptr,const ns3::Ipv6Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback,ns3::Ptr,ns3::Ptr,const ns3::Ipv6Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback,const ns3::Ipv6Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback,const ns3::Ipv6Header&,ns3::Socket::SocketErrno,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function] + cls.add_method('RouteInput', + 'bool', + [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv6Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::NetDevice const >, ns3::Ptr< ns3::Ipv6Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::NetDevice const >, ns3::Ptr< ns3::Ipv6MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::Socket::SocketErrno, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], + is_virtual=True) + ## ripng.h (module 'internet'): ns3::Ptr ns3::RipNg::RouteOutput(ns3::Ptr p, ns3::Ipv6Header const & header, ns3::Ptr oif, ns3::Socket::SocketErrno & sockerr) [member function] + cls.add_method('RouteOutput', + 'ns3::Ptr< ns3::Ipv6Route >', + [param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ipv6Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice >', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::SetInterfaceExclusions(std::set, std::allocator > exceptions) [member function] + cls.add_method('SetInterfaceExclusions', + 'void', + [param('std::set< unsigned int >', 'exceptions')]) + ## ripng.h (module 'internet'): void ns3::RipNg::SetInterfaceMetric(uint32_t interface, uint8_t metric) [member function] + cls.add_method('SetInterfaceMetric', + 'void', + [param('uint32_t', 'interface'), param('uint8_t', 'metric')]) + ## ripng.h (module 'internet'): void ns3::RipNg::SetIpv6(ns3::Ptr ipv6) [member function] + cls.add_method('SetIpv6', + 'void', + [param('ns3::Ptr< ns3::Ipv6 >', 'ipv6')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::DoDispose() [member function] + cls.add_method('DoDispose', + 'void', + [], + visibility='protected', is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::DoInitialize() [member function] + cls.add_method('DoInitialize', + 'void', + [], + visibility='protected', is_virtual=True) + return + def register_Ns3TcpL4Protocol_methods(root_module, cls): ## tcp-l4-protocol.h (module 'internet'): ns3::TcpL4Protocol::PROT_NUMBER [variable] cls.add_static_attribute('PROT_NUMBER', 'uint8_t const', is_const=True) diff --git a/src/internet/bindings/modulegen__gcc_LP64.py b/src/internet/bindings/modulegen__gcc_LP64.py index 386d1686d..df4e62dd4 100644 --- a/src/internet/bindings/modulegen__gcc_LP64.py +++ b/src/internet/bindings/modulegen__gcc_LP64.py @@ -210,6 +210,12 @@ def register_types(module): module.add_class('PcapHelperForIpv4', allow_subclassing=True) ## internet-trace-helper.h (module 'internet'): ns3::PcapHelperForIpv6 [class] module.add_class('PcapHelperForIpv6', allow_subclassing=True) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper [class] + module.add_class('RipNgHelper', parent=root_module['ns3::Ipv6RoutingHelper']) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry [class] + module.add_class('RipNgRoutingTableEntry', parent=root_module['ns3::Ipv6RoutingTableEntry']) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e [enumeration] + module.add_enum('Status_e', ['RIPNG_VALID', 'RIPNG_INVALID'], outer_class=root_module['ns3::RipNgRoutingTableEntry']) ## rtt-estimator.h (module 'internet'): ns3::RttHistory [class] module.add_class('RttHistory') ## global-route-manager-impl.h (module 'internet'): ns3::SPFVertex [class] @@ -226,6 +232,8 @@ def register_types(module): module.add_class('Tag', import_from_module='ns.network', parent=root_module['ns3::ObjectBase']) ## tag-buffer.h (module 'network'): ns3::TagBuffer [class] module.add_class('TagBuffer', import_from_module='ns.network') + ## nstime.h (module 'core'): ns3::TimeWithUnit [class] + module.add_class('TimeWithUnit', import_from_module='ns.core') ## timer.h (module 'core'): ns3::Timer [class] module.add_class('Timer', import_from_module='ns.core') ## timer.h (module 'core'): ns3::Timer::DestroyPolicy [enumeration] @@ -362,6 +370,12 @@ def register_types(module): module.add_class('PcapFileWrapper', import_from_module='ns.network', parent=root_module['ns3::Object']) ## random-variable-stream.h (module 'core'): ns3::RandomVariableStream [class] module.add_class('RandomVariableStream', import_from_module='ns.core', parent=root_module['ns3::Object']) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader [class] + module.add_class('RipNgHeader', parent=root_module['ns3::Header']) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::Command_e [enumeration] + module.add_enum('Command_e', ['REQUEST', 'RESPONSE'], outer_class=root_module['ns3::RipNgHeader']) + ## ripng-header.h (module 'internet'): ns3::RipNgRte [class] + module.add_class('RipNgRte', parent=root_module['ns3::Header']) ## rtt-estimator.h (module 'internet'): ns3::RttEstimator [class] module.add_class('RttEstimator', parent=root_module['ns3::Object']) ## rtt-estimator.h (module 'internet'): ns3::RttMeanDeviation [class] @@ -648,6 +662,10 @@ def register_types(module): module.add_class('ParetoRandomVariable', import_from_module='ns.core', parent=root_module['ns3::RandomVariableStream']) ## probe.h (module 'stats'): ns3::Probe [class] module.add_class('Probe', import_from_module='ns.stats', parent=root_module['ns3::DataCollectionObject']) + ## ripng.h (module 'internet'): ns3::RipNg [class] + module.add_class('RipNg', parent=root_module['ns3::Ipv6RoutingProtocol']) + ## ripng.h (module 'internet'): ns3::RipNg::SplitHorizonType_e [enumeration] + module.add_enum('SplitHorizonType_e', ['NO_SPLIT_HORIZON', 'SPLIT_HORIZON', 'POISON_REVERSE'], outer_class=root_module['ns3::RipNg']) ## tcp-l4-protocol.h (module 'internet'): ns3::TcpL4Protocol [class] module.add_class('TcpL4Protocol', parent=root_module['ns3::IpL4Protocol']) ## tcp-newreno.h (module 'internet'): ns3::TcpNewReno [class] @@ -694,10 +712,12 @@ def register_types(module): module.add_class('LoopbackNetDevice', parent=root_module['ns3::NetDevice']) module.add_container('std::vector< unsigned int >', 'unsigned int', container_type=u'vector') module.add_container('std::vector< bool >', 'bool', container_type=u'vector') + module.add_container('std::list< ns3::RipNgRte >', 'ns3::RipNgRte', container_type=u'list') module.add_container('std::map< ns3::SequenceNumber< unsigned int, int >, ns3::Ptr< ns3::Packet > >', ('ns3::SequenceNumber< unsigned int, int >', 'ns3::Ptr< ns3::Packet >'), container_type=u'map') module.add_container('std::list< ns3::Ptr< ns3::Packet > >', 'ns3::Ptr< ns3::Packet >', container_type=u'list') module.add_container('std::map< unsigned int, unsigned int >', ('unsigned int', 'unsigned int'), container_type=u'map') module.add_container('std::vector< ns3::Ipv6Address >', 'ns3::Ipv6Address', container_type=u'vector') + module.add_container('std::set< unsigned int >', 'unsigned int', container_type=u'set') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >', u'ns3::SequenceNumber16') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >*', u'ns3::SequenceNumber16*') typehandlers.add_type_alias(u'ns3::SequenceNumber< short unsigned int, short int >&', u'ns3::SequenceNumber16&') @@ -837,6 +857,8 @@ def register_methods(root_module): register_Ns3PcapHelperForDevice_methods(root_module, root_module['ns3::PcapHelperForDevice']) register_Ns3PcapHelperForIpv4_methods(root_module, root_module['ns3::PcapHelperForIpv4']) register_Ns3PcapHelperForIpv6_methods(root_module, root_module['ns3::PcapHelperForIpv6']) + register_Ns3RipNgHelper_methods(root_module, root_module['ns3::RipNgHelper']) + register_Ns3RipNgRoutingTableEntry_methods(root_module, root_module['ns3::RipNgRoutingTableEntry']) register_Ns3RttHistory_methods(root_module, root_module['ns3::RttHistory']) register_Ns3SPFVertex_methods(root_module, root_module['ns3::SPFVertex']) register_Ns3SequenceNumber32_methods(root_module, root_module['ns3::SequenceNumber32']) @@ -844,6 +866,7 @@ def register_methods(root_module): register_Ns3Simulator_methods(root_module, root_module['ns3::Simulator']) register_Ns3Tag_methods(root_module, root_module['ns3::Tag']) register_Ns3TagBuffer_methods(root_module, root_module['ns3::TagBuffer']) + register_Ns3TimeWithUnit_methods(root_module, root_module['ns3::TimeWithUnit']) register_Ns3Timer_methods(root_module, root_module['ns3::Timer']) register_Ns3TimerImpl_methods(root_module, root_module['ns3::TimerImpl']) register_Ns3TracedValue__Double_methods(root_module, root_module['ns3::TracedValue< double >']) @@ -896,6 +919,8 @@ def register_methods(root_module): register_Ns3ObjectAggregateIterator_methods(root_module, root_module['ns3::Object::AggregateIterator']) register_Ns3PcapFileWrapper_methods(root_module, root_module['ns3::PcapFileWrapper']) register_Ns3RandomVariableStream_methods(root_module, root_module['ns3::RandomVariableStream']) + register_Ns3RipNgHeader_methods(root_module, root_module['ns3::RipNgHeader']) + register_Ns3RipNgRte_methods(root_module, root_module['ns3::RipNgRte']) register_Ns3RttEstimator_methods(root_module, root_module['ns3::RttEstimator']) register_Ns3RttMeanDeviation_methods(root_module, root_module['ns3::RttMeanDeviation']) register_Ns3SequentialRandomVariable_methods(root_module, root_module['ns3::SequentialRandomVariable']) @@ -1026,6 +1051,7 @@ def register_methods(root_module): register_Ns3Packet_methods(root_module, root_module['ns3::Packet']) register_Ns3ParetoRandomVariable_methods(root_module, root_module['ns3::ParetoRandomVariable']) register_Ns3Probe_methods(root_module, root_module['ns3::Probe']) + register_Ns3RipNg_methods(root_module, root_module['ns3::RipNg']) register_Ns3TcpL4Protocol_methods(root_module, root_module['ns3::TcpL4Protocol']) register_Ns3TcpNewReno_methods(root_module, root_module['ns3::TcpNewReno']) register_Ns3TcpReno_methods(root_module, root_module['ns3::TcpReno']) @@ -4337,6 +4363,91 @@ def register_Ns3PcapHelperForIpv6_methods(root_module, cls): is_pure_virtual=True, is_virtual=True) return +def register_Ns3RipNgHelper_methods(root_module, cls): + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper::RipNgHelper() [constructor] + cls.add_constructor([]) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper::RipNgHelper(ns3::RipNgHelper const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgHelper const &', 'arg0')]) + ## ripng-helper.h (module 'internet'): ns3::RipNgHelper * ns3::RipNgHelper::Copy() const [member function] + cls.add_method('Copy', + 'ns3::RipNgHelper *', + [], + is_const=True, is_virtual=True) + ## ripng-helper.h (module 'internet'): ns3::Ptr ns3::RipNgHelper::Create(ns3::Ptr node) const [member function] + cls.add_method('Create', + 'ns3::Ptr< ns3::Ipv6RoutingProtocol >', + [param('ns3::Ptr< ns3::Node >', 'node')], + is_const=True, is_virtual=True) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::Set(std::string name, ns3::AttributeValue const & value) [member function] + cls.add_method('Set', + 'void', + [param('std::string', 'name'), param('ns3::AttributeValue const &', 'value')]) + ## ripng-helper.h (module 'internet'): int64_t ns3::RipNgHelper::AssignStreams(ns3::NodeContainer c, int64_t stream) [member function] + cls.add_method('AssignStreams', + 'int64_t', + [param('ns3::NodeContainer', 'c'), param('int64_t', 'stream')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::SetDefaultRouter(ns3::Ptr node, ns3::Ipv6Address nextHop, uint32_t interface) [member function] + cls.add_method('SetDefaultRouter', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::ExcludeInterface(ns3::Ptr node, uint32_t interface) [member function] + cls.add_method('ExcludeInterface', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('uint32_t', 'interface')]) + ## ripng-helper.h (module 'internet'): void ns3::RipNgHelper::SetInterfaceMetric(ns3::Ptr node, uint32_t interface, uint8_t metric) [member function] + cls.add_method('SetInterfaceMetric', + 'void', + [param('ns3::Ptr< ns3::Node >', 'node'), param('uint32_t', 'interface'), param('uint8_t', 'metric')]) + return + +def register_Ns3RipNgRoutingTableEntry_methods(root_module, cls): + cls.add_output_stream_operator() + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::RipNgRoutingTableEntry const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgRoutingTableEntry const &', 'arg0')]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry() [constructor] + cls.add_constructor([]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::Ipv6Address network, ns3::Ipv6Prefix networkPrefix, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse) [constructor] + cls.add_constructor([param('ns3::Ipv6Address', 'network'), param('ns3::Ipv6Prefix', 'networkPrefix'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse')]) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::RipNgRoutingTableEntry(ns3::Ipv6Address network, ns3::Ipv6Prefix networkPrefix, uint32_t interface) [constructor] + cls.add_constructor([param('ns3::Ipv6Address', 'network'), param('ns3::Ipv6Prefix', 'networkPrefix'), param('uint32_t', 'interface')]) + ## ripng.h (module 'internet'): uint8_t ns3::RipNgRoutingTableEntry::GetRouteMetric() const [member function] + cls.add_method('GetRouteMetric', + 'uint8_t', + [], + is_const=True) + ## ripng.h (module 'internet'): ns3::RipNgRoutingTableEntry::Status_e ns3::RipNgRoutingTableEntry::GetRouteStatus() const [member function] + cls.add_method('GetRouteStatus', + 'ns3::RipNgRoutingTableEntry::Status_e', + [], + is_const=True) + ## ripng.h (module 'internet'): uint16_t ns3::RipNgRoutingTableEntry::GetRouteTag() const [member function] + cls.add_method('GetRouteTag', + 'uint16_t', + [], + is_const=True) + ## ripng.h (module 'internet'): bool ns3::RipNgRoutingTableEntry::IsRouteChanged() const [member function] + cls.add_method('IsRouteChanged', + 'bool', + [], + is_const=True) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteChanged(bool changed) [member function] + cls.add_method('SetRouteChanged', + 'void', + [param('bool', 'changed')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteMetric(uint8_t routeMetric) [member function] + cls.add_method('SetRouteMetric', + 'void', + [param('uint8_t', 'routeMetric')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteStatus(ns3::RipNgRoutingTableEntry::Status_e status) [member function] + cls.add_method('SetRouteStatus', + 'void', + [param('ns3::RipNgRoutingTableEntry::Status_e', 'status')]) + ## ripng.h (module 'internet'): void ns3::RipNgRoutingTableEntry::SetRouteTag(uint16_t routeTag) [member function] + cls.add_method('SetRouteTag', + 'void', + [param('uint16_t', 'routeTag')]) + return + def register_Ns3RttHistory_methods(root_module, cls): ## rtt-estimator.h (module 'internet'): ns3::RttHistory::RttHistory(ns3::SequenceNumber32 s, uint32_t c, ns3::Time t) [constructor] cls.add_constructor([param('ns3::SequenceNumber32', 's'), param('uint32_t', 'c'), param('ns3::Time', 't')]) @@ -4678,6 +4789,14 @@ def register_Ns3TagBuffer_methods(root_module, cls): [param('uint8_t', 'v')]) return +def register_Ns3TimeWithUnit_methods(root_module, cls): + cls.add_output_stream_operator() + ## nstime.h (module 'core'): ns3::TimeWithUnit::TimeWithUnit(ns3::TimeWithUnit const & arg0) [copy constructor] + cls.add_constructor([param('ns3::TimeWithUnit const &', 'arg0')]) + ## nstime.h (module 'core'): ns3::TimeWithUnit::TimeWithUnit(ns3::Time const time, ns3::Time::Unit const unit) [constructor] + cls.add_constructor([param('ns3::Time const', 'time'), param('ns3::Time::Unit const', 'unit')]) + return + def register_Ns3Timer_methods(root_module, cls): ## timer.h (module 'core'): ns3::Timer::Timer(ns3::Timer const & arg0) [copy constructor] cls.add_constructor([param('ns3::Timer const &', 'arg0')]) @@ -7499,6 +7618,143 @@ def register_Ns3RandomVariableStream_methods(root_module, cls): is_const=True, visibility='protected') return +def register_Ns3RipNgHeader_methods(root_module, cls): + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::RipNgHeader(ns3::RipNgHeader const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgHeader const &', 'arg0')]) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::RipNgHeader() [constructor] + cls.add_constructor([]) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::AddRte(ns3::RipNgRte rte) [member function] + cls.add_method('AddRte', + 'void', + [param('ns3::RipNgRte', 'rte')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::ClearRtes() [member function] + cls.add_method('ClearRtes', + 'void', + []) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgHeader::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::RipNgHeader::Command_e ns3::RipNgHeader::GetCommand() const [member function] + cls.add_method('GetCommand', + 'ns3::RipNgHeader::Command_e', + [], + is_const=True) + ## ripng-header.h (module 'internet'): ns3::TypeId ns3::RipNgHeader::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): std::list > ns3::RipNgHeader::GetRteList() const [member function] + cls.add_method('GetRteList', + 'std::list< ns3::RipNgRte >', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint16_t ns3::RipNgHeader::GetRteNumber() const [member function] + cls.add_method('GetRteNumber', + 'uint16_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgHeader::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): static ns3::TypeId ns3::RipNgHeader::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgHeader::SetCommand(ns3::RipNgHeader::Command_e command) [member function] + cls.add_method('SetCommand', + 'void', + [param('ns3::RipNgHeader::Command_e', 'command')]) + return + +def register_Ns3RipNgRte_methods(root_module, cls): + ## ripng-header.h (module 'internet'): ns3::RipNgRte::RipNgRte(ns3::RipNgRte const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNgRte const &', 'arg0')]) + ## ripng-header.h (module 'internet'): ns3::RipNgRte::RipNgRte() [constructor] + cls.add_constructor([]) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgRte::Deserialize(ns3::Buffer::Iterator start) [member function] + cls.add_method('Deserialize', + 'uint32_t', + [param('ns3::Buffer::Iterator', 'start')], + is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::TypeId ns3::RipNgRte::GetInstanceTypeId() const [member function] + cls.add_method('GetInstanceTypeId', + 'ns3::TypeId', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): ns3::Ipv6Address ns3::RipNgRte::GetPrefix() const [member function] + cls.add_method('GetPrefix', + 'ns3::Ipv6Address', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint8_t ns3::RipNgRte::GetPrefixLen() const [member function] + cls.add_method('GetPrefixLen', + 'uint8_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint8_t ns3::RipNgRte::GetRouteMetric() const [member function] + cls.add_method('GetRouteMetric', + 'uint8_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint16_t ns3::RipNgRte::GetRouteTag() const [member function] + cls.add_method('GetRouteTag', + 'uint16_t', + [], + is_const=True) + ## ripng-header.h (module 'internet'): uint32_t ns3::RipNgRte::GetSerializedSize() const [member function] + cls.add_method('GetSerializedSize', + 'uint32_t', + [], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): static ns3::TypeId ns3::RipNgRte::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::Print(std::ostream & os) const [member function] + cls.add_method('Print', + 'void', + [param('std::ostream &', 'os')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::Serialize(ns3::Buffer::Iterator start) const [member function] + cls.add_method('Serialize', + 'void', + [param('ns3::Buffer::Iterator', 'start')], + is_const=True, is_virtual=True) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetPrefix(ns3::Ipv6Address prefix) [member function] + cls.add_method('SetPrefix', + 'void', + [param('ns3::Ipv6Address', 'prefix')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetPrefixLen(uint8_t prefixLen) [member function] + cls.add_method('SetPrefixLen', + 'void', + [param('uint8_t', 'prefixLen')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetRouteMetric(uint8_t routeMetric) [member function] + cls.add_method('SetRouteMetric', + 'void', + [param('uint8_t', 'routeMetric')]) + ## ripng-header.h (module 'internet'): void ns3::RipNgRte::SetRouteTag(uint16_t routeTag) [member function] + cls.add_method('SetRouteTag', + 'void', + [param('uint16_t', 'routeTag')]) + return + def register_Ns3RttEstimator_methods(root_module, cls): ## rtt-estimator.h (module 'internet'): ns3::RttEstimator::RttEstimator() [constructor] cls.add_constructor([]) @@ -9555,6 +9811,11 @@ def register_Ns3Time_methods(root_module, cls): cls.add_constructor([param('std::string const &', 's')]) ## nstime.h (module 'core'): ns3::Time::Time(ns3::int64x64_t const & value) [constructor] cls.add_constructor([param('ns3::int64x64_t const &', 'value')]) + ## nstime.h (module 'core'): ns3::TimeWithUnit ns3::Time::As(ns3::Time::Unit const unit) const [member function] + cls.add_method('As', + 'ns3::TimeWithUnit', + [param('ns3::Time::Unit const', 'unit')], + is_const=True) ## nstime.h (module 'core'): int ns3::Time::Compare(ns3::Time const & o) const [member function] cls.add_method('Compare', 'int', @@ -14674,6 +14935,104 @@ def register_Ns3Probe_methods(root_module, cls): is_const=True, is_virtual=True) return +def register_Ns3RipNg_methods(root_module, cls): + ## ripng.h (module 'internet'): ns3::RipNg::RipNg(ns3::RipNg const & arg0) [copy constructor] + cls.add_constructor([param('ns3::RipNg const &', 'arg0')]) + ## ripng.h (module 'internet'): ns3::RipNg::RipNg() [constructor] + cls.add_constructor([]) + ## ripng.h (module 'internet'): void ns3::RipNg::AddDefaultRouteTo(ns3::Ipv6Address nextHop, uint32_t interface) [member function] + cls.add_method('AddDefaultRouteTo', + 'void', + [param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface')]) + ## ripng.h (module 'internet'): int64_t ns3::RipNg::AssignStreams(int64_t stream) [member function] + cls.add_method('AssignStreams', + 'int64_t', + [param('int64_t', 'stream')]) + ## ripng.h (module 'internet'): std::set, std::allocator > ns3::RipNg::GetInterfaceExclusions() const [member function] + cls.add_method('GetInterfaceExclusions', + 'std::set< unsigned int >', + [], + is_const=True) + ## ripng.h (module 'internet'): uint8_t ns3::RipNg::GetInterfaceMetric(uint32_t interface) const [member function] + cls.add_method('GetInterfaceMetric', + 'uint8_t', + [param('uint32_t', 'interface')], + is_const=True) + ## ripng.h (module 'internet'): static ns3::TypeId ns3::RipNg::GetTypeId() [member function] + cls.add_method('GetTypeId', + 'ns3::TypeId', + [], + is_static=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyAddAddress(uint32_t interface, ns3::Ipv6InterfaceAddress address) [member function] + cls.add_method('NotifyAddAddress', + 'void', + [param('uint32_t', 'interface'), param('ns3::Ipv6InterfaceAddress', 'address')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyAddRoute(ns3::Ipv6Address dst, ns3::Ipv6Prefix mask, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse=ns3::Ipv6Address::GetZero( )) [member function] + cls.add_method('NotifyAddRoute', + 'void', + [param('ns3::Ipv6Address', 'dst'), param('ns3::Ipv6Prefix', 'mask'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse', default_value='ns3::Ipv6Address::GetZero( )')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyInterfaceDown(uint32_t interface) [member function] + cls.add_method('NotifyInterfaceDown', + 'void', + [param('uint32_t', 'interface')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyInterfaceUp(uint32_t interface) [member function] + cls.add_method('NotifyInterfaceUp', + 'void', + [param('uint32_t', 'interface')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyRemoveAddress(uint32_t interface, ns3::Ipv6InterfaceAddress address) [member function] + cls.add_method('NotifyRemoveAddress', + 'void', + [param('uint32_t', 'interface'), param('ns3::Ipv6InterfaceAddress', 'address')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::NotifyRemoveRoute(ns3::Ipv6Address dst, ns3::Ipv6Prefix mask, ns3::Ipv6Address nextHop, uint32_t interface, ns3::Ipv6Address prefixToUse=ns3::Ipv6Address::GetZero( )) [member function] + cls.add_method('NotifyRemoveRoute', + 'void', + [param('ns3::Ipv6Address', 'dst'), param('ns3::Ipv6Prefix', 'mask'), param('ns3::Ipv6Address', 'nextHop'), param('uint32_t', 'interface'), param('ns3::Ipv6Address', 'prefixToUse', default_value='ns3::Ipv6Address::GetZero( )')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::PrintRoutingTable(ns3::Ptr stream) const [member function] + cls.add_method('PrintRoutingTable', + 'void', + [param('ns3::Ptr< ns3::OutputStreamWrapper >', 'stream')], + is_const=True, is_virtual=True) + ## ripng.h (module 'internet'): bool ns3::RipNg::RouteInput(ns3::Ptr p, ns3::Ipv6Header const & header, ns3::Ptr idev, ns3::Callback,ns3::Ptr,ns3::Ptr,const ns3::Ipv6Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ucb, ns3::Callback,ns3::Ptr,ns3::Ptr,const ns3::Ipv6Header&,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> mcb, ns3::Callback,const ns3::Ipv6Header&,unsigned int,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> lcb, ns3::Callback,const ns3::Ipv6Header&,ns3::Socket::SocketErrno,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty,ns3::empty> ecb) [member function] + cls.add_method('RouteInput', + 'bool', + [param('ns3::Ptr< ns3::Packet const >', 'p'), param('ns3::Ipv6Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice const >', 'idev'), param('ns3::Callback< void, ns3::Ptr< ns3::NetDevice const >, ns3::Ptr< ns3::Ipv6Route >, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ucb'), param('ns3::Callback< void, ns3::Ptr< ns3::NetDevice const >, ns3::Ptr< ns3::Ipv6MulticastRoute >, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'mcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, unsigned int, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'lcb'), param('ns3::Callback< void, ns3::Ptr< ns3::Packet const >, ns3::Ipv6Header const &, ns3::Socket::SocketErrno, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty, ns3::empty >', 'ecb')], + is_virtual=True) + ## ripng.h (module 'internet'): ns3::Ptr ns3::RipNg::RouteOutput(ns3::Ptr p, ns3::Ipv6Header const & header, ns3::Ptr oif, ns3::Socket::SocketErrno & sockerr) [member function] + cls.add_method('RouteOutput', + 'ns3::Ptr< ns3::Ipv6Route >', + [param('ns3::Ptr< ns3::Packet >', 'p'), param('ns3::Ipv6Header const &', 'header'), param('ns3::Ptr< ns3::NetDevice >', 'oif'), param('ns3::Socket::SocketErrno &', 'sockerr')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::SetInterfaceExclusions(std::set, std::allocator > exceptions) [member function] + cls.add_method('SetInterfaceExclusions', + 'void', + [param('std::set< unsigned int >', 'exceptions')]) + ## ripng.h (module 'internet'): void ns3::RipNg::SetInterfaceMetric(uint32_t interface, uint8_t metric) [member function] + cls.add_method('SetInterfaceMetric', + 'void', + [param('uint32_t', 'interface'), param('uint8_t', 'metric')]) + ## ripng.h (module 'internet'): void ns3::RipNg::SetIpv6(ns3::Ptr ipv6) [member function] + cls.add_method('SetIpv6', + 'void', + [param('ns3::Ptr< ns3::Ipv6 >', 'ipv6')], + is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::DoDispose() [member function] + cls.add_method('DoDispose', + 'void', + [], + visibility='protected', is_virtual=True) + ## ripng.h (module 'internet'): void ns3::RipNg::DoInitialize() [member function] + cls.add_method('DoInitialize', + 'void', + [], + visibility='protected', is_virtual=True) + return + def register_Ns3TcpL4Protocol_methods(root_module, cls): ## tcp-l4-protocol.h (module 'internet'): ns3::TcpL4Protocol::PROT_NUMBER [variable] cls.add_static_attribute('PROT_NUMBER', 'uint8_t const', is_const=True) diff --git a/src/internet/doc/routing-overview.rst b/src/internet/doc/routing-overview.rst index 4f07ba768..6f0f6b6ea 100644 --- a/src/internet/doc/routing-overview.rst +++ b/src/internet/doc/routing-overview.rst @@ -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 two for +There are presently seven unicast routing protocols defined for IPv4 and three for IPv6: * class Ipv4StaticRouting (covering both unicast and multicast) @@ -232,19 +232,20 @@ IPv6: stores source routes in a packet header field) * class Ipv6ListRouting (used to store a prioritized list of routing protocols) * class Ipv6StaticRouting +* class RipNg - the IPv6 RIPng protocol (:rfc:`2080`) In the future, this architecture should also allow someone to implement a Linux-like implementation with routing cache, or a Click modular router, but those are out of scope for now. -Ipv4ListRouting -+++++++++++++++ +Ipv[4,6]ListRouting ++++++++++++++++++++ -This section describes the current default |ns3| Ipv4RoutingProtocol. Typically, +This section describes the current default |ns3| Ipv[4,6]RoutingProtocol. Typically, multiple routing protocols are supported in user space and coordinate to write a single forwarding table in the kernel. Presently in |ns3|, the implementation instead allows for multiple routing protocols to build/keep their own routing -state, and the IPv4 implementation will query each one of these routing +state, and the IP implementation will query each one of these routing protocols (in some order determined by the simulation author) until a route is found. @@ -254,23 +255,26 @@ a single table, approaches where more information than destination IP address (e.g., source routing) is used to determine the next hop, and on-demand routing approaches where packets must be cached. -Ipv4ListRouting::AddRoutingProtocol -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Ipv[4,6]4ListRouting::AddRoutingProtocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Class Ipv4ListRouting provides a pure virtual function declaration for the -method that allows one to add a routing protocol:: +Classes Ipv4ListRouting and Ipv6ListRouting provides a pure virtual function declaration +for the method that allows one to add a routing protocol:: void AddRoutingProtocol (Ptr routingProtocol, int16_t priority); -This method is implemented by class Ipv4ListRoutingImpl in the internet-stack -module. + void AddRoutingProtocol (Ptr routingProtocol, + int16_t priority); + +These methods are implemented respectively by class Ipv4ListRoutingImpl and by class +Ipv6ListRoutingImpl in the internet module. The priority variable above governs the priority in which the routing protocols are inserted. Notice that it is a signed int. By default in |ns3|, the helper -classes will instantiate a Ipv4ListRoutingImpl object, and add to it an -Ipv4StaticRoutingImpl object at priority zero. Internally, a list of -Ipv4RoutingProtocols is stored, and and the routing protocols are each consulted +classes will instantiate a Ipv[4,6]ListRoutingImpl object, and add to it an +Ipv[4,6]StaticRoutingImpl object at priority zero. Internally, a list of +Ipv[4,6]RoutingProtocols is stored, and and the routing protocols are each consulted in decreasing order of priority to see whether a match is found. Therefore, if you want your Ipv4RoutingProtocol to have priority lower than the static routing, insert it with priority less than 0; e.g.:: @@ -330,6 +334,116 @@ 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 ++++++ + +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. + +The protocol is very simple, and it is 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 +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. + + +Routing convergence +~~~~~~~~~~~~~~~~~~~ + +RIPng 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. +It should be stressed that the convergence time is the number of steps in +the algorithm, and each step is triggered by a message. +Since Triggered Updates (i.e., when a route is changed) have a 1-5 seconds +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. +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. + +If the network topology is changed (e.g., a link is broken), the recovery +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. + +Split Horizoning +~~~~~~~~~~~~~~~~ + +Split Horizon is a strategy to prevent routing instability. Three options are possible: + +* No Split Horizon +* Split Horizon +* Poison Reverse + +In the first case, routes are advertised on all the router's interfaces. +In the second case, routers will not advertise a route on the interface +from which it was learned. +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 +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 +router invalidates a route, it will immediately propagate the route +unreachability, thus preventing most of the issues described in the RFC. + +However, with complex toplogies, it is still possible to have route +instability phenomena similar to the one described in the RFC after a +link failure. As a consequence, all the considerations about Split Horizon +remanins valid. + + +Default routes +~~~~~~~~~~~~~~ + +RIPng 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. +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 +with route updates and routes lifetime. + +Moreover, users can change the interface metrics on a per-node basis. + +The type of Split Horizoning (to avoid routes back-propagation) can be +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. + +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 +routers on a network. +Support for this option may be considered in the future. + +There is no support for CIDR prefix aggregation. As a result, both routing +tables and route advertisements may be larger than necessary. +Prefix aggregation may be added in the future. + + .. _Multicast-routing: Multicast routing diff --git a/src/internet/helper/ripng-helper.cc b/src/internet/helper/ripng-helper.cc new file mode 100644 index 000000000..b276ffa31 --- /dev/null +++ b/src/internet/helper/ripng-helper.cc @@ -0,0 +1,182 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#include "ns3/node.h" +#include "ns3/node-list.h" +#include "ns3/ipv6-list-routing.h" +#include "ns3/ripng.h" +#include "ripng-helper.h" + +namespace ns3 { + +RipNgHelper::RipNgHelper () +{ + m_factory.SetTypeId ("ns3::RipNg"); +} + +RipNgHelper::RipNgHelper (const RipNgHelper &o) + : m_factory (o.m_factory) +{ + m_interfaceExclusions = o.m_interfaceExclusions; + m_interfaceMetrics = o.m_interfaceMetrics; +} + +RipNgHelper::~RipNgHelper () +{ + m_interfaceExclusions.clear (); + m_interfaceMetrics.clear (); +} + +RipNgHelper* +RipNgHelper::Copy (void) const +{ + return new RipNgHelper (*this); +} + +Ptr +RipNgHelper::Create (Ptr node) const +{ + Ptr ripng = m_factory.Create (); + + std::map, std::set >::const_iterator it = m_interfaceExclusions.find (node); + + if(it != m_interfaceExclusions.end ()) + { + ripng->SetInterfaceExclusions (it->second); + } + + std::map< Ptr, std::map >::const_iterator iter = m_interfaceMetrics.find (node); + + if(iter != m_interfaceMetrics.end ()) + { + std::map::const_iterator subiter; + for (subiter = iter->second.begin (); subiter != iter->second.end (); subiter++) + { + ripng->SetInterfaceMetric (subiter->first, subiter->second); + } + } + + node->AggregateObject (ripng); + return ripng; +} + +void +RipNgHelper::Set (std::string name, const AttributeValue &value) +{ + m_factory.Set (name, value); +} + + +int64_t +RipNgHelper::AssignStreams (NodeContainer c, int64_t stream) +{ + int64_t currentStream = stream; + Ptr node; + for (NodeContainer::Iterator i = c.Begin (); i != c.End (); ++i) + { + node = (*i); + Ptr ipv6 = node->GetObject (); + NS_ASSERT_MSG (ipv6, "Ipv6 not installed on node"); + Ptr proto = ipv6->GetRoutingProtocol (); + NS_ASSERT_MSG (proto, "Ipv6 routing not installed on node"); + Ptr ripng = DynamicCast (proto); + if (ripng) + { + currentStream += ripng->AssignStreams (currentStream); + continue; + } + // RIPng may also be in a list + Ptr list = DynamicCast (proto); + if (list) + { + int16_t priority; + Ptr listProto; + Ptr listRipng; + for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++) + { + listProto = list->GetRoutingProtocol (i, priority); + listRipng = DynamicCast (listProto); + if (listRipng) + { + currentStream += listRipng->AssignStreams (currentStream); + break; + } + } + } + } + return (currentStream - stream); +} + +void RipNgHelper::SetDefaultRouter (Ptr node, Ipv6Address nextHop, uint32_t interface) +{ + Ptr ipv6 = node->GetObject (); + NS_ASSERT_MSG (ipv6, "Ipv6 not installed on node"); + Ptr proto = ipv6->GetRoutingProtocol (); + NS_ASSERT_MSG (proto, "Ipv6 routing not installed on node"); + Ptr ripng = DynamicCast (proto); + if (ripng) + { + ripng->AddDefaultRouteTo (nextHop, interface); + } + // RIPng may also be in a list + Ptr list = DynamicCast (proto); + if (list) + { + int16_t priority; + Ptr listProto; + Ptr listRipng; + for (uint32_t i = 0; i < list->GetNRoutingProtocols (); i++) + { + listProto = list->GetRoutingProtocol (i, priority); + listRipng = DynamicCast (listProto); + if (listRipng) + { + listRipng->AddDefaultRouteTo (nextHop, interface); + break; + } + } + } +} + +void +RipNgHelper::ExcludeInterface (Ptr node, uint32_t interface) +{ + std::map< Ptr, std::set >::iterator it = m_interfaceExclusions.find (node); + + if (it == m_interfaceExclusions.end ()) + { + std::set interfaces; + interfaces.insert (interface); + + m_interfaceExclusions.insert (std::make_pair (node, interfaces)); + } + else + { + it->second.insert (interface); + } +} + +void RipNgHelper::SetInterfaceMetric (Ptr node, uint32_t interface, uint8_t metric) +{ + m_interfaceMetrics[node][interface] = metric; +} + +} + diff --git a/src/internet/helper/ripng-helper.h b/src/internet/helper/ripng-helper.h new file mode 100644 index 000000000..1075884af --- /dev/null +++ b/src/internet/helper/ripng-helper.h @@ -0,0 +1,148 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#ifndef RIPNG_HELPER_H +#define RIPNG_HELPER_H + +#include "ns3/object-factory.h" +#include "ns3/ipv6-routing-helper.h" +#include "ns3/node-container.h" +#include "ns3/node.h" + +namespace ns3 { + +/** + * \brief Helper class that adds RIPng routing to nodes. + * + * This class is expected to be used in conjunction with + * ns3::InternetStackHelper::SetRoutingHelper + * + */ +class RipNgHelper : public Ipv6RoutingHelper +{ +public: + /* + * Construct an RipngHelper to make life easier while adding RIPng + * routing to nodes. + */ + RipNgHelper (); + + /** + * \brief Construct an RipngHelper from another previously + * initialized instance (Copy Constructor). + */ + RipNgHelper (const RipNgHelper &); + + virtual ~RipNgHelper (); + + /** + * \returns pointer to clone of this Ipv4NixVectorHelper + * + * This method is mainly for internal use by the other helpers; + * clients are expected to free the dynamic memory allocated by this method + */ + RipNgHelper* 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 Create (Ptr 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, Ipv6Address nextHop, uint32_t interface); + + /** + * \brief Exclude an interface from RIPng protocol. + * + * You have to call this function \a before installing RIPng in the nodes. + * + * Note: the exclusion means that RIPng will not be propagated on that interface. + * The network prefix on that interface will be still considered in RIPng. + * + * \param node the node + * \param interface the network interface to be excluded + */ + void ExcludeInterface (Ptr node, uint32_t interface); + + /** + * \brief Set a metric for an interface. + * + * You have to call this function \a before installing RIPng in the nodes. + * + * Note: RIPng 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, 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. + */ + RipNgHelper &operator = (const RipNgHelper &o); + + ObjectFactory m_factory; //|< Object Factory + + std::map< Ptr, std::set > m_interfaceExclusions; //!< Interface Exclusion set + std::map< Ptr, std::map > m_interfaceMetrics; //!< Interface Metric set +}; + +} // namespace ns3 + + +#endif /* RIPNG_HELPER_H */ + diff --git a/src/internet/model/ipv6-routing-table-entry.h b/src/internet/model/ipv6-routing-table-entry.h index acb7c0ebe..5da6937eb 100644 --- a/src/internet/model/ipv6-routing-table-entry.h +++ b/src/internet/model/ipv6-routing-table-entry.h @@ -57,7 +57,7 @@ public: /** * \brief Destructor */ - ~Ipv6RoutingTableEntry (); + virtual ~Ipv6RoutingTableEntry (); /** * \brief Is the route entry correspond to a host ? diff --git a/src/internet/model/ripng-header.cc b/src/internet/model/ripng-header.cc new file mode 100644 index 000000000..72ce60b62 --- /dev/null +++ b/src/internet/model/ripng-header.cc @@ -0,0 +1,255 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#include "ripng-header.h" + +namespace ns3 { + +/* + * RipNgRte + */ +NS_OBJECT_ENSURE_REGISTERED (RipNgRte) + ; + +RipNgRte::RipNgRte () + : m_prefix ("::"), m_tag (0), m_prefixLen (0), m_metric (16) +{ +} + +TypeId RipNgRte::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RipNgRte").SetParent
().AddConstructor (); + return tid; +} + +TypeId RipNgRte::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +void RipNgRte::Print (std::ostream & os) const +{ + os << "prefix " << m_prefix << "/" << int(m_prefixLen) << " Metric " << int(m_metric) << " Tag " << int(m_tag); +} + +uint32_t RipNgRte::GetSerializedSize () const +{ + return 20; +} + +void RipNgRte::Serialize (Buffer::Iterator i) const +{ + uint8_t tmp[16]; + + m_prefix.Serialize (tmp); + i.Write (tmp, 16); + + i.WriteHtonU16 (m_tag); + i.WriteU8 (m_prefixLen); + i.WriteU8 (m_metric); +} + +uint32_t RipNgRte::Deserialize (Buffer::Iterator i) +{ + uint8_t tmp[16]; + + i.Read (tmp, 16); + m_prefix.Set (tmp); + m_tag = i.ReadNtohU16 (); + m_prefixLen = i.ReadU8 (); + m_metric = i.ReadU8 (); + + return GetSerializedSize (); +} + +void RipNgRte::SetPrefix (Ipv6Address prefix) +{ + m_prefix = prefix; +} + +Ipv6Address RipNgRte::GetPrefix () const +{ + return m_prefix; +} + +void RipNgRte::SetPrefixLen (uint8_t prefixLen) +{ + m_prefixLen = prefixLen; +} + +uint8_t RipNgRte::GetPrefixLen () const +{ + return m_prefixLen; +} + +void RipNgRte::SetRouteTag (uint16_t routeTag) +{ + m_tag = routeTag; +} + +uint16_t RipNgRte::GetRouteTag () const +{ + return m_tag; +} + +void RipNgRte::SetRouteMetric (uint8_t routeMetric) +{ + m_metric = routeMetric; +} + +uint8_t RipNgRte::GetRouteMetric () const +{ + return m_metric; +} + + +std::ostream & operator << (std::ostream & os, const RipNgRte & h) +{ + h.Print (os); + return os; +} + +/* + * RipNgHeader + */ +NS_OBJECT_ENSURE_REGISTERED (RipNgHeader) + ; + +RipNgHeader::RipNgHeader () + : m_command (0) +{ +} + +TypeId RipNgHeader::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RipNgHeader").SetParent
().AddConstructor (); + return tid; +} + +TypeId RipNgHeader::GetInstanceTypeId (void) const +{ + return GetTypeId (); +} + +void RipNgHeader::Print (std::ostream & os) const +{ + os << "command " << int(m_command); + for (std::list::const_iterator iter = m_rteList.begin (); + iter != m_rteList.end (); iter ++) + { + os << " | "; + iter->Print (os); + } +} + +uint32_t RipNgHeader::GetSerializedSize () const +{ + RipNgRte rte; + return 4 + m_rteList.size () * rte.GetSerializedSize (); +} + +void RipNgHeader::Serialize (Buffer::Iterator start) const +{ + Buffer::Iterator i = start; + + i.WriteU8 (uint8_t (m_command)); + i.WriteU8 (1); + i.WriteU16 (0); + + for (std::list::const_iterator iter = m_rteList.begin (); + iter != m_rteList.end (); iter ++) + { + iter->Serialize (i); + i.Next(iter->GetSerializedSize ()); + } +} + +uint32_t RipNgHeader::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, "RipNG received a message with mismatch version, aborting."); + + uint16_t temp16 = i.ReadU16 (); + NS_ASSERT_MSG (temp16 == 0, "RipNG received a message with invalid filled flags, aborting."); + + uint8_t rteNumber = (i.GetSize () - 4)/20; + for (uint8_t n=0; n RipNgHeader::GetRteList (void) const +{ + return m_rteList; +} + + +std::ostream & operator << (std::ostream & os, const RipNgHeader & h) +{ + h.Print (os); + return os; +} + + +} + diff --git a/src/internet/model/ripng-header.h b/src/internet/model/ripng-header.h new file mode 100644 index 000000000..9aa237635 --- /dev/null +++ b/src/internet/model/ripng-header.h @@ -0,0 +1,226 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#ifndef RIPNG_HEADER_H +#define RIPNG_HEADER_H + +#include +#include "ns3/header.h" +#include "ns3/ipv6-address.h" +#include "ns3/packet.h" +#include "ns3/ipv6-header.h" + + +namespace ns3 { + +/** + * \ingroup ripng + * \brief RipNg Routing Table Entry (RTE) - see \RFC{2080} + */ +class RipNgRte : public Header +{ +public: + RipNgRte (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 (Ipv6Address prefix); + + /** + * \brief Get the prefix + * \returns the prefix + */ + Ipv6Address GetPrefix (void) const; + + /** + * \brief Set the prefix length + * \param prefixLen the prefix length + */ + void SetPrefixLen (uint8_t prefixLen); + + /** + * \brief Get the prefix length + * \returns the prefix length + */ + uint8_t GetPrefixLen (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 (uint8_t routeMetric); + + /** + * \brief Get the route metric + * \returns the route metric + */ + uint8_t GetRouteMetric (void) const; + + +private: + Ipv6Address m_prefix; //!< prefix + uint16_t m_tag; //!< route tag + uint8_t m_prefixLen; //!< prefix length + uint8_t m_metric; //!< route metric +}; + + +/** + * \ingroup ripng + * \brief RipNgHeader - see \RFC{2080} + */ +class RipNgHeader : public Header +{ +public: + RipNgHeader (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 RipNg 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 (RipNgRte 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 GetRteList (void) const; + +private: + uint8_t m_command; //!< command type + std::list m_rteList; //!< list of the RTEs in the message +}; + +} + +#endif /* RIPNG_HEADER_H */ + diff --git a/src/internet/model/ripng.cc b/src/internet/model/ripng.cc new file mode 100644 index 000000000..955fac976 --- /dev/null +++ b/src/internet/model/ripng.cc @@ -0,0 +1,1382 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#include +#include "ripng.h" +#include "ns3/log.h" +#include "ns3/abort.h" +#include "ns3/assert.h" +#include "ns3/unused.h" +#include "ns3/random-variable-stream.h" +#include "ns3/ipv6-route.h" +#include "ns3/node.h" +#include "ns3/names.h" +#include "ns3/ripng-header.h" +#include "ns3/udp-header.h" +#include "ns3/enum.h" +#include "ns3/ipv6-packet-info-tag.h" + +#define RIPNG_ALL_NODE "ff02::9" +#define RIPNG_PORT 521 + +NS_LOG_COMPONENT_DEFINE ("RipNg") + ; + +namespace ns3 { + +NS_OBJECT_ENSURE_REGISTERED (RipNg) + ; + +RipNg::RipNg () + : m_ipv6 (0), m_splitHorizonStrategy (RipNg::POISON_REVERSE), m_initialized (false) +{ + m_rng = CreateObject (); +} + +RipNg::~RipNg () +{ +} + +TypeId +RipNg::GetTypeId (void) +{ + static TypeId tid = TypeId ("ns3::RipNg") + .SetParent () + .AddConstructor () + .AddAttribute ("UnsolicitedRoutingUpdate", "The time between two Unsolicited Routing Updates.", + TimeValue (Seconds(30)), + MakeTimeAccessor (&RipNg::m_unsolicitedUpdate), + MakeTimeChecker ()) + .AddAttribute ("StartupDelay", "Maximum random delay for protocol startup (send route requests).", + TimeValue (Seconds(1)), + MakeTimeAccessor (&RipNg::m_startupDelay), + MakeTimeChecker ()) + .AddAttribute ("TimeoutDelay", "The delay to invalidate a route.", + TimeValue (Seconds(180)), + MakeTimeAccessor (&RipNg::m_timeoutDelay), + MakeTimeChecker ()) + .AddAttribute ("GarbageCollectionDelay", "The delay to delete an expired route.", + TimeValue (Seconds(120)), + MakeTimeAccessor (&RipNg::m_garbageCollectionDelay), + MakeTimeChecker ()) + .AddAttribute ("MinTriggeredCooldown", "Min cooldown delay after a Triggered Update.", + TimeValue (Seconds(1)), + MakeTimeAccessor (&RipNg::m_minTriggeredUpdateDelay), + MakeTimeChecker ()) + .AddAttribute ("MaxTriggeredCooldown", "Max cooldown delay after a Triggered Update.", + TimeValue (Seconds(5)), + MakeTimeAccessor (&RipNg::m_maxTriggeredUpdateDelay), + MakeTimeChecker ()) + .AddAttribute ("SplitHorizon", "Split Horizon strategy.", + EnumValue (RipNg::POISON_REVERSE), + MakeEnumAccessor (&RipNg::m_splitHorizonStrategy), + MakeEnumChecker (RipNg::NO_SPLIT_HORIZON, "No Split Horizon", + RipNg::SPLIT_HORIZON, "Split Horizon", + RipNg::POISON_REVERSE, "Poison Reverse")) + ; + return tid; +} + +int64_t RipNg::AssignStreams (int64_t stream) +{ + NS_LOG_FUNCTION (this << stream); + + m_rng->SetStream (stream); + return 1; +} + +void RipNg::DoInitialize () +{ + NS_LOG_FUNCTION (this); + + bool addedGlobal = false; + + m_initialized = true; + + Time delay = m_unsolicitedUpdate + Seconds (m_rng->GetValue (0, 0.5*m_unsolicitedUpdate.GetSeconds ()) ); + m_nextUnsolicitedUpdate = Simulator::Schedule (delay, &RipNg::SendUnsolicitedRouteUpdate, this); + + + for (uint32_t i = 0 ; i < m_ipv6->GetNInterfaces (); i++) + { + bool activeInterface = false; + if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ()) + { + activeInterface = true; + } + + for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++) + { + Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j); + if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && activeInterface == true) + { + NS_LOG_LOGIC ("RIPng: adding socket to " << address.GetAddress ()); + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr theNode = GetObject (); + Ptr socket = Socket::CreateSocket (theNode, tid); + Inet6SocketAddress local = Inet6SocketAddress (address.GetAddress (), RIPNG_PORT); + int ret = socket->Bind (local); + NS_ASSERT_MSG (ret == 0, "Bind unsuccessful"); + socket->BindToNetDevice (m_ipv6->GetNetDevice (i)); + socket->ShutdownRecv (); + socket->SetIpv6RecvHopLimit (true); + m_sendSocketList[socket] = i; + } + else if (m_ipv6->GetAddress (i, j).GetScope() == Ipv6InterfaceAddress::GLOBAL) + { + addedGlobal = true; + } + } + } + + if (!m_recvSocket) + { + NS_LOG_LOGIC ("RIPng: adding receiving socket"); + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr theNode = GetObject (); + m_recvSocket = Socket::CreateSocket (theNode, tid); + Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address::GetAny (), RIPNG_PORT); + m_recvSocket->Bind (local); + m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this)); + m_recvSocket->SetIpv6RecvHopLimit (true); + m_recvSocket->SetRecvPktInfo (true); + } + + + if (addedGlobal) + { + Time delay = Seconds (m_rng->GetValue (m_minTriggeredUpdateDelay.GetSeconds (), m_maxTriggeredUpdateDelay.GetSeconds ())); + m_nextTriggeredUpdate = Simulator::Schedule (delay, &RipNg::DoSendRouteUpdate, this, false); + } + + delay = Seconds (m_rng->GetValue (0.01, m_startupDelay.GetSeconds ())); + m_nextTriggeredUpdate = Simulator::Schedule (delay, &RipNg::SendRouteRequest, this); + + Ipv6RoutingProtocol::DoInitialize (); +} + +Ptr RipNg::RouteOutput (Ptr p, const Ipv6Header &header, Ptr oif, Socket::SocketErrno &sockerr) +{ + NS_LOG_FUNCTION (this << header << oif); + + Ipv6Address destination = header.GetDestinationAddress (); + Ptr rtentry = 0; + + if (destination.IsMulticast ()) + { + // Note: Multicast routes for outbound packets are stored in the + // normal unicast table. An implication of this is that it is not + // possible to source multicast datagrams on multiple interfaces. + // This is a well-known property of sockets implementation on + // many Unix variants. + // So, we just log it and fall through to LookupStatic () + NS_LOG_LOGIC ("RouteOutput (): Multicast destination"); + } + + rtentry = Lookup (destination, oif); + if (rtentry) + { + sockerr = Socket::ERROR_NOTERROR; + } + else + { + sockerr = Socket::ERROR_NOROUTETOHOST; + } + return rtentry; +} + +bool RipNg::RouteInput (Ptr p, const Ipv6Header &header, Ptr idev, + UnicastForwardCallback ucb, MulticastForwardCallback mcb, + LocalDeliverCallback lcb, ErrorCallback ecb) +{ + NS_LOG_FUNCTION (this << p << header << header.GetSourceAddress () << header.GetDestinationAddress () << idev); + + NS_ASSERT (m_ipv6 != 0); + // Check if input device supports IP + NS_ASSERT (m_ipv6->GetInterfaceForDevice (idev) >= 0); + uint32_t iif = m_ipv6->GetInterfaceForDevice (idev); + Ipv6Address dst = header.GetDestinationAddress (); + + if (dst.IsMulticast ()) + { + NS_LOG_LOGIC ("Multicast route not supported by RIPng"); + return false; // Let other routing protocols try to handle this + } + + /// \todo Configurable option to enable \RFC{1222} Strong End System Model + // Right now, we will be permissive and allow a source to send us + // a packet to one of our other interface addresses; that is, the + // destination unicast address does not match one of the iif addresses, + // but we check our other interfaces. This could be an option + // (to remove the outer loop immediately below and just check iif). + for (uint32_t j = 0; j < m_ipv6->GetNInterfaces (); j++) + { + for (uint32_t i = 0; i < m_ipv6->GetNAddresses (j); i++) + { + Ipv6InterfaceAddress iaddr = m_ipv6->GetAddress (j, i); + Ipv6Address addr = iaddr.GetAddress (); + if (addr.IsEqual (header.GetDestinationAddress ())) + { + if (j == iif) + { + NS_LOG_LOGIC ("For me (destination " << addr << " match)"); + } + else + { + NS_LOG_LOGIC ("For me (destination " << addr << " match) on another interface " << header.GetDestinationAddress ()); + } + lcb (p, header, iif); + return true; + } + NS_LOG_LOGIC ("Address " << addr << " not a match"); + } + } + // Check if input device supports IP forwarding + if (m_ipv6->IsForwarding (iif) == false) + { + NS_LOG_LOGIC ("Forwarding disabled for this interface"); + ecb (p, header, Socket::ERROR_NOROUTETOHOST); + return false; + } + // Next, try to find a route + NS_LOG_LOGIC ("Unicast destination"); + Ptr rtentry = Lookup (header.GetDestinationAddress ()); + + if (rtentry != 0) + { + NS_LOG_LOGIC ("Found unicast destination- calling unicast callback"); + ucb (idev, rtentry, p, header); // unicast forwarding callback + return true; + } + else + { + NS_LOG_LOGIC ("Did not find unicast destination- returning false"); + return false; // Let other routing protocols try to handle this + } +} + +void RipNg::NotifyInterfaceUp (uint32_t i) +{ + NS_LOG_FUNCTION (this << i); + + for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++) + { + Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j); + Ipv6Prefix networkMask = address.GetPrefix (); + Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (networkMask); + + if (address != Ipv6Address () && networkMask != Ipv6Prefix ()) + { + if (networkMask == Ipv6Prefix (128)) + { + /* host route */ + AddNetworkRouteTo (networkAddress, Ipv6Prefix::GetOnes (), 0); + } + else + { + AddNetworkRouteTo (networkAddress, networkMask, i); + } + } + } + + if (!m_initialized) + { + return; + } + + + bool sendSocketFound = false; + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + if (iter->second == i) + { + sendSocketFound = true; + break; + } + } + + bool activeInterface = false; + if (m_interfaceExclusions.find (i) == m_interfaceExclusions.end ()) + { + activeInterface = true; + } + + for (uint32_t j = 0; j < m_ipv6->GetNAddresses (i); j++) + { + Ipv6InterfaceAddress address = m_ipv6->GetAddress (i, j); + + Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ()); + Ipv6Prefix networkMask = address.GetPrefix (); + AddNetworkRouteTo (networkAddress, networkMask, i); + + if (address.GetScope() == Ipv6InterfaceAddress::LINKLOCAL && sendSocketFound == false && activeInterface == true) + { + NS_LOG_LOGIC ("RIPng: adding sending socket to " << address.GetAddress ()); + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr theNode = GetObject (); + Ptr socket = Socket::CreateSocket (theNode, tid); + Inet6SocketAddress local = Inet6SocketAddress (address.GetAddress (), RIPNG_PORT); + socket->Bind (local); + socket->BindToNetDevice (m_ipv6->GetNetDevice (i)); + socket->ShutdownRecv (); + socket->SetIpv6RecvHopLimit (true); + m_sendSocketList[socket] = i; + } + else if (address.GetScope() == Ipv6InterfaceAddress::GLOBAL) + { + SendTriggeredRouteUpdate (); + } + } + + if (!m_recvSocket) + { + NS_LOG_LOGIC ("RIPng: adding receiving socket"); + TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory"); + Ptr theNode = GetObject (); + m_recvSocket = Socket::CreateSocket (theNode, tid); + Inet6SocketAddress local = Inet6SocketAddress (Ipv6Address::GetAny (), RIPNG_PORT); + m_recvSocket->Bind (local); + m_recvSocket->SetRecvCallback (MakeCallback (&RipNg::Receive, this)); + m_recvSocket->SetIpv6RecvHopLimit (true); + m_recvSocket->SetRecvPktInfo (true); + } +} + +void RipNg::NotifyInterfaceDown (uint32_t interface) +{ + NS_LOG_FUNCTION (this << interface); + + /* remove all routes that are going through this interface */ + for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++) + { + if (it->first->GetInterface () == interface) + { + InvalidateRoute (it->first); + } + } + + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + NS_LOG_INFO ("Checking socket for interface " << interface); + if (iter->second == interface) + { + NS_LOG_INFO ("Removed socket for interface " << interface); + iter->first->Close (); + m_sendSocketList.erase (iter); + break; + } + } + + if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ()) + { + SendTriggeredRouteUpdate (); + } +} + +void RipNg::NotifyAddAddress (uint32_t interface, Ipv6InterfaceAddress address) +{ + NS_LOG_FUNCTION (this << interface << address); + + if (!m_ipv6->IsUp (interface)) + { + return; + } + + if (m_interfaceExclusions.find (interface) != m_interfaceExclusions.end ()) + { + return; + } + + Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ()); + Ipv6Prefix networkMask = address.GetPrefix (); + + if (address.GetAddress () != Ipv6Address () && address.GetPrefix () != Ipv6Prefix ()) + { + AddNetworkRouteTo (networkAddress, networkMask, interface); + } + + SendTriggeredRouteUpdate (); +} + +void RipNg::NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address) +{ + NS_LOG_FUNCTION (this << interface << address); + + if (!m_ipv6->IsUp (interface)) + { + return; + } + + if (address.GetScope() != Ipv6InterfaceAddress::GLOBAL) + { + return; + } + + Ipv6Address networkAddress = address.GetAddress ().CombinePrefix (address.GetPrefix ()); + Ipv6Prefix networkMask = address.GetPrefix (); + + // Remove all routes that are going through this interface + // which reference this network + for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++) + { + if (it->first->GetInterface () == interface + && it->first->IsNetwork () + && it->first->GetDestNetwork () == networkAddress + && it->first->GetDestNetworkPrefix () == networkMask) + { + InvalidateRoute (it->first); + } + } + + if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ()) + { + SendTriggeredRouteUpdate (); + } + +} + +void RipNg::NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse) +{ + NS_LOG_INFO (this << dst << mask << nextHop << interface << prefixToUse); + // \todo this can be used to add delegate routes +} + +void RipNg::NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse) +{ + NS_LOG_FUNCTION (this << dst << mask << nextHop << interface); + // \todo this can be used to delete delegate routes +} + +void RipNg::SetIpv6 (Ptr ipv6) +{ + NS_LOG_FUNCTION (this << ipv6); + + NS_ASSERT (m_ipv6 == 0 && ipv6 != 0); + uint32_t i = 0; + m_ipv6 = ipv6; + + for (i = 0; i < m_ipv6->GetNInterfaces (); i++) + { + if (m_ipv6->IsUp (i)) + { + NotifyInterfaceUp (i); + } + else + { + NotifyInterfaceDown (i); + } + } +} + +void RipNg::PrintRoutingTable (Ptr stream) const +{ + NS_LOG_FUNCTION (this << stream); + + std::ostream* os = stream->GetStream (); + + *os << "Node: " << m_ipv6->GetObject ()->GetId () + << " Time: " << Simulator::Now ().GetSeconds () << "s " + << "Ipv6 RIPng table" << std::endl; + + if (!m_routes.empty ()) + { + *os << "Destination Next Hop Flag Met Ref Use If" << std::endl; + for (RoutesCI it = m_routes.begin (); it != m_routes.end (); it++) + { + RipNgRoutingTableEntry* route = it->first; + RipNgRoutingTableEntry::Status_e status = route->GetRouteStatus(); + + if (status == RipNgRoutingTableEntry::RIPNG_VALID) + { + std::ostringstream dest, gw, mask, flags; + + dest << route->GetDest () << "/" << int(route->GetDestNetworkPrefix ().GetPrefixLength ()); + *os << std::setiosflags (std::ios::left) << std::setw (31) << dest.str (); + gw << route->GetGateway (); + *os << std::setiosflags (std::ios::left) << std::setw (27) << gw.str (); + flags << "U"; + if (route->IsHost ()) + { + flags << "H"; + } + else if (route->IsGateway ()) + { + flags << "G"; + } + *os << std::setiosflags (std::ios::left) << std::setw (5) << flags.str (); + *os << std::setiosflags (std::ios::left) << std::setw (4) << int(route->GetRouteMetric ()); + // Ref ct not implemented + *os << "-" << " "; + // Use not implemented + *os << "-" << " "; + if (Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())) != "") + { + *os << Names::FindName (m_ipv6->GetNetDevice (route->GetInterface ())); + } + else + { + *os << route->GetInterface (); + } + *os << std::endl; + } + } + } +} + +void RipNg::DoDispose () +{ + NS_LOG_FUNCTION (this); + + for (RoutesI j = m_routes.begin (); j != m_routes.end (); j = m_routes.erase (j)) + { + delete j->first; + } + m_routes.clear (); + + m_nextTriggeredUpdate.Cancel (); + m_nextUnsolicitedUpdate.Cancel (); + m_nextTriggeredUpdate = EventId (); + m_nextUnsolicitedUpdate = EventId (); + + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + iter->first->Close (); + } + m_sendSocketList.clear (); + + m_recvSocket->Close (); + m_recvSocket = 0; + + m_ipv6 = 0; + + Ipv6RoutingProtocol::DoDispose (); +} + + +Ptr RipNg::Lookup (Ipv6Address dst, Ptr interface) +{ + NS_LOG_FUNCTION (this << dst << interface); + + Ptr rtentry = 0; + uint16_t longestMask = 0; + + /* when sending on link-local multicast, there have to be interface specified */ + if (dst.IsLinkLocalMulticast ()) + { + NS_ASSERT_MSG (interface, "Try to send on link-local multicast address, and no interface index is given!"); + rtentry = Create (); + rtentry->SetSource (m_ipv6->SourceAddressSelection (m_ipv6->GetInterfaceForDevice (interface), dst)); + rtentry->SetDestination (dst); + rtentry->SetGateway (Ipv6Address::GetZero ()); + rtentry->SetOutputDevice (interface); + return rtentry; + } + + for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++) + { + RipNgRoutingTableEntry* j = it->first; + + if (j->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID) + { + Ipv6Prefix mask = j->GetDestNetworkPrefix (); + uint16_t maskLen = mask.GetPrefixLength (); + Ipv6Address entry = j->GetDestNetwork (); + + NS_LOG_LOGIC ("Searching for route to " << dst << ", mask length " << maskLen); + + if (mask.IsMatch (dst, entry)) + { + NS_LOG_LOGIC ("Found global network route " << j << ", mask length " << maskLen); + + /* if interface is given, check the route will output on this interface */ + if (!interface || interface == m_ipv6->GetNetDevice (j->GetInterface ())) + { + if (maskLen < longestMask) + { + NS_LOG_LOGIC ("Previous match longer, skipping"); + continue; + } + + longestMask = maskLen; + + Ipv6RoutingTableEntry* route = j; + uint32_t interfaceIdx = route->GetInterface (); + rtentry = Create (); + + if (route->GetGateway ().IsAny ()) + { + rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ())); + } + else if (route->GetDest ().IsAny ()) /* default route */ + { + rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetPrefixToUse ().IsAny () ? dst : route->GetPrefixToUse ())); + } + else + { + rtentry->SetSource (m_ipv6->SourceAddressSelection (interfaceIdx, route->GetDest ())); + } + + rtentry->SetDestination (route->GetDest ()); + rtentry->SetGateway (route->GetGateway ()); + rtentry->SetOutputDevice (m_ipv6->GetNetDevice (interfaceIdx)); + } + } + } + } + + if (rtentry) + { + NS_LOG_LOGIC ("Matching route via " << rtentry->GetDestination () << " (through " << rtentry->GetGateway () << ") at the end"); + } + return rtentry; +} + +void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse) +{ + NS_LOG_FUNCTION (this << network << networkPrefix << nextHop << interface << prefixToUse); + + if (nextHop.IsLinkLocal()) + { + NS_LOG_WARN ("Ripng::AddNetworkRouteTo - Next hop should be link-local"); + } + + RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, nextHop, interface, prefixToUse); + route->SetRouteMetric (1); + route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + route->SetRouteChanged (true); + + m_routes.push_back (std::make_pair (route, EventId ())); +} + +void RipNg::AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface) +{ + NS_LOG_FUNCTION (this << network << networkPrefix << interface); + + RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (network, networkPrefix, interface); + route->SetRouteMetric (1); + route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + route->SetRouteChanged (true); + + m_routes.push_back (std::make_pair (route, EventId ())); +} + +void RipNg::InvalidateRoute (RipNgRoutingTableEntry *route) +{ + NS_LOG_FUNCTION (this << *route); + + for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++) + { + if (it->first == route) + { + route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_INVALID); + route->SetRouteMetric (16); + route->SetRouteChanged (true); + if (it->second.IsRunning ()) + { + it->second.Cancel (); + } + it->second = Simulator::Schedule (m_garbageCollectionDelay, &RipNg::DeleteRoute, this, route); + return; + } + } + NS_ABORT_MSG ("Ripng::InvalidateRoute - cannot find the route to update"); +} + +void RipNg::DeleteRoute (RipNgRoutingTableEntry *route) +{ + NS_LOG_FUNCTION (this << *route); + + for (RoutesI it = m_routes.begin (); it != m_routes.end (); it++) + { + if (it->first == route) + { + delete route; + m_routes.erase (it); + return; + } + } + NS_ABORT_MSG ("Ripng::DeleteRoute - cannot find the route to delete"); +} + + +void RipNg::Receive (Ptr socket) +{ + NS_LOG_FUNCTION (this << socket); + + Ptr packet = socket->Recv (); + NS_LOG_INFO ("Received " << *packet); + + Ipv6PacketInfoTag interfaceInfo; + if (!packet->RemovePacketTag (interfaceInfo)) + { + NS_ABORT_MSG ("No incoming interface on RIPng message, aborting."); + } + uint32_t incomingIf = interfaceInfo.GetRecvIf (); + Ptr node = this->GetObject (); + Ptr dev = node->GetDevice (incomingIf); + uint32_t ipInterfaceIndex = m_ipv6->GetInterfaceForDevice (dev); + + SocketIpv6HopLimitTag hoplimitTag; + if (!packet->RemovePacketTag (hoplimitTag)) + { + NS_ABORT_MSG ("No incoming Hop Count on RIPng message, aborting."); + } + uint8_t hopLimit = hoplimitTag.GetHopLimit (); + + SocketAddressTag tag; + if (!packet->RemovePacketTag (tag)) + { + NS_ABORT_MSG ("No incoming sender address on RIPng message, aborting."); + } + Ipv6Address senderAddress = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv6 (); + uint16_t senderPort = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetPort (); + + int32_t interfaceForAddress = m_ipv6->GetInterfaceForAddress (senderAddress); + if (interfaceForAddress != -1) + { + NS_LOG_LOGIC ("Ignoring a packet sent by myself."); + return; + } + + RipNgHeader hdr; + packet->RemoveHeader (hdr); + + if (hdr.GetCommand () == RipNgHeader::RESPONSE) + { + HandleResponses (hdr, senderAddress, ipInterfaceIndex, hopLimit); + } + else if (hdr.GetCommand () == RipNgHeader::REQUEST) + { + HandleRequests (hdr, senderAddress, senderPort, ipInterfaceIndex, hopLimit); + } + else + { + NS_LOG_LOGIC ("Ignoring message with unknown command: " << int (hdr.GetCommand ())); + } + return; +} + +void RipNg::HandleRequests (RipNgHeader requestHdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit) +{ + NS_LOG_FUNCTION (this << senderAddress << int (senderPort) << incomingInterface << int (hopLimit) << requestHdr); + + std::list rtes = requestHdr.GetRteList (); + + if (rtes.empty ()) + { + return; + } + + // check if it's a request for the full table from a neighbor + if (rtes.size () == 1 && senderAddress.IsLinkLocal ()) + { + if (rtes.begin ()->GetPrefix () == Ipv6Address::GetAny () && + rtes.begin ()->GetPrefixLen () == 0 && + rtes.begin ()->GetRouteMetric () == 16) + { + // Output whole thing. Use Split Horizon + if (m_interfaceExclusions.find (incomingInterface) == m_interfaceExclusions.end ()) + { + // we use one of the sending sockets, as they're bound to the right interface + // and the local address might be used on different interfaces. + Ptr sendingSoket; + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + if (iter->second == incomingInterface) + { + sendingSoket = iter->first; + } + } + NS_ASSERT_MSG (sendingSoket, "HandleRequest - Impossible to find a socket to send the reply"); + + uint16_t mtu = m_ipv6->GetMtu (incomingInterface); + uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize (); + + Ptr p = Create (); + SocketIpv6HopLimitTag tag; + p->RemovePacketTag (tag); + tag.SetHopLimit (255); + p->AddPacketTag (tag); + + RipNgHeader hdr; + hdr.SetCommand (RipNgHeader::RESPONSE); + + for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++) + { + bool splitHorizoning = (rtIter->first->GetInterface () == incomingInterface); + + Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ()); + + bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL); + bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) && + (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) && + (rtIter->first->GetInterface () != incomingInterface)); + + if ((isGlobal || isDefaultRoute) && + (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID) ) + { + RipNgRte rte; + rte.SetPrefix (rtIter->first->GetDestNetwork ()); + rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ()); + if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning) + { + rte.SetRouteMetric (16); + } + else + { + rte.SetRouteMetric (rtIter->first->GetRouteMetric ()); + } + rte.SetRouteTag (rtIter->first->GetRouteTag ()); + if ((m_splitHorizonStrategy != SPLIT_HORIZON) || + (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning)) + { + hdr.AddRte (rte); + } + } + if (hdr.GetRteNumber () == maxRte) + { + p->AddHeader (hdr); + NS_LOG_DEBUG ("SendTo: " << *p); + sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT)); + p->RemoveHeader (hdr); + hdr.ClearRtes (); + } + } + if (hdr.GetRteNumber () > 0) + { + p->AddHeader (hdr); + NS_LOG_DEBUG ("SendTo: " << *p); + sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, RIPNG_PORT)); + } + } + } + } + else + { + // note: we got the request as a single packet, so no check is necessary for MTU limit + + // we use one of the sending sockets, as they're bound to the right interface + // and the local address might be used on different interfaces. + Ptr sendingSoket; + if (senderAddress.IsLinkLocal ()) + { + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + if (iter->second == incomingInterface) + { + sendingSoket = iter->first; + } + } + } + else + { + sendingSoket = m_recvSocket; + } + + Ptr p = Create (); + SocketIpv6HopLimitTag tag; + p->RemovePacketTag (tag); + tag.SetHopLimit (255); + p->AddPacketTag (tag); + + RipNgHeader hdr; + hdr.SetCommand (RipNgHeader::RESPONSE); + + for (std::list::iterator iter = rtes.begin (); + iter != rtes.end (); iter++) + { + bool found = false; + for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++) + { + Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ()); + if ((rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL) && + (rtIter->first->GetRouteStatus () == RipNgRoutingTableEntry::RIPNG_VALID)) + { + Ipv6Address requestedAddress = iter->GetPrefix (); + requestedAddress.CombinePrefix (Ipv6Prefix (iter->GetPrefixLen ())); + Ipv6Address rtAddress = rtIter->first->GetDestNetwork (); + rtAddress.CombinePrefix (rtIter->first->GetDestNetworkPrefix ()); + + if (requestedAddress == rtAddress) + { + iter->SetRouteMetric (rtIter->first->GetRouteMetric ()); + iter->SetRouteTag (rtIter->first->GetRouteTag ()); + hdr.AddRte (*iter); + found = true; + break; + } + } + } + if (!found) + { + iter->SetRouteMetric (16); + iter->SetRouteTag (0); + hdr.AddRte (*iter); + } + } + p->AddHeader (hdr); + NS_LOG_DEBUG ("SendTo: " << *p); + sendingSoket->SendTo (p, 0, Inet6SocketAddress (senderAddress, senderPort)); + } + +} + +void RipNg::HandleResponses (RipNgHeader hdr, Ipv6Address senderAddress, uint32_t incomingInterface, uint8_t hopLimit) +{ + NS_LOG_FUNCTION (this << senderAddress << incomingInterface << int (hopLimit) << hdr); + + if (m_interfaceExclusions.find (incomingInterface) != m_interfaceExclusions.end ()) + { + NS_LOG_LOGIC ("Ignoring an update message from an excluded interface: " << incomingInterface); + return; + } + + if (!senderAddress.IsLinkLocal ()) + { + NS_LOG_LOGIC ("Ignoring an update message from a non-link-local source: " << senderAddress); + return; + } + + if (hopLimit != 255) + { + NS_LOG_LOGIC ("Ignoring an update message with suspicious hop count: " << int (hopLimit)); + return; + } + + std::list rtes = hdr.GetRteList (); + + // validate the RTEs before processing + for (std::list::iterator iter = rtes.begin (); + iter != rtes.end (); iter++) + { + if (iter->GetRouteMetric () == 0 || iter->GetRouteMetric () > 16) + { + NS_LOG_LOGIC ("Ignoring an update message with malformed metric: " << int (iter->GetRouteMetric ())); + return; + } + if (iter->GetPrefixLen () > 128) + { + NS_LOG_LOGIC ("Ignoring an update message with malformed prefix length: " << int (iter->GetPrefixLen ())); + return; + } + if (iter->GetPrefix ().IsLocalhost () || + iter->GetPrefix ().IsLinkLocal () || + iter->GetPrefix ().IsMulticast ()) + { + NS_LOG_LOGIC ("Ignoring an update message with wrong prefixes: " << iter->GetPrefix ()); + return; + } + } + + bool changed = false; + + for (std::list::iterator iter = rtes.begin (); + iter != rtes.end (); iter++) + { + Ipv6Prefix rtePrefix = Ipv6Prefix (iter->GetPrefixLen ()); + Ipv6Address rteAddr = iter->GetPrefix ().CombinePrefix (rtePrefix); + + NS_LOG_LOGIC ("Processing RTE " << *iter); + + uint8_t interfaceMetric = 1; + if (m_interfaceMetrics.find (incomingInterface) != m_interfaceMetrics.end ()) + { + interfaceMetric = m_interfaceMetrics[incomingInterface]; + } + uint8_t rteMetric = std::min (iter->GetRouteMetric () + interfaceMetric, 16); + RoutesI it; + bool found = false; + for (it = m_routes.begin (); it != m_routes.end (); it++) + { + if (it->first->GetDestNetwork () == rteAddr && + it->first->GetDestNetworkPrefix () == rtePrefix) + { + found = true; + if (rteMetric < it->first->GetRouteMetric ()) + { + if (senderAddress != it->first->GetGateway ()) + { + RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ()); + delete it->first; + it->first = route; + } + it->first->SetRouteMetric (rteMetric); + it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + it->first->SetRouteTag (iter->GetRouteTag ()); + it->first->SetRouteChanged (true); + it->second.Cancel (); + it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first); + changed = true; + } + else if (rteMetric == it->first->GetRouteMetric ()) + { + if (senderAddress == it->first->GetGateway ()) + { + it->second.Cancel (); + it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first); + } + else + { + if (Simulator::GetDelayLeft (it->second) < m_timeoutDelay/2) + { + RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ()); + route->SetRouteMetric (rteMetric); + route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + route->SetRouteTag (iter->GetRouteTag ()); + route->SetRouteChanged (true); + delete it->first; + it->first = route; + it->second.Cancel (); + it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route); + changed = true; + } + } + } + else if (rteMetric > it->first->GetRouteMetric () && senderAddress == it->first->GetGateway ()) + { + it->second.Cancel (); + if (rteMetric < 16) + { + it->first->SetRouteMetric (rteMetric); + it->first->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + it->first->SetRouteTag (iter->GetRouteTag ()); + it->first->SetRouteChanged (true); + it->second.Cancel (); + it->second = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, it->first); + } + else + { + InvalidateRoute (it->first); + } + changed = true; + } + } + } + if (!found && rteMetric != 16) + { + NS_LOG_LOGIC ("Received a RTE with new route, adding."); + + RipNgRoutingTableEntry* route = new RipNgRoutingTableEntry (rteAddr, rtePrefix, senderAddress, incomingInterface, Ipv6Address::GetAny ()); + route->SetRouteMetric (rteMetric); + route->SetRouteStatus (RipNgRoutingTableEntry::RIPNG_VALID); + route->SetRouteChanged (true); + m_routes.push_front (std::make_pair (route, EventId ())); + EventId invalidateEvent = Simulator::Schedule (m_timeoutDelay, &RipNg::InvalidateRoute, this, route); + (m_routes.begin ())->second = invalidateEvent; + changed = true; + } + } + + if (changed) + { + SendTriggeredRouteUpdate (); + } +} + +void RipNg::DoSendRouteUpdate (bool periodic) +{ + NS_LOG_FUNCTION (this << (periodic ? " periodic" : " triggered")); + + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + uint32_t interface = iter->second; + + if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ()) + { + uint16_t mtu = m_ipv6->GetMtu (interface); + uint16_t maxRte = (mtu - Ipv6Header ().GetSerializedSize () - UdpHeader ().GetSerializedSize () - RipNgHeader ().GetSerializedSize ()) / RipNgRte ().GetSerializedSize (); + + Ptr p = Create (); + SocketIpv6HopLimitTag tag; + tag.SetHopLimit (255); + p->AddPacketTag (tag); + + RipNgHeader hdr; + hdr.SetCommand (RipNgHeader::RESPONSE); + + for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++) + { + bool splitHorizoning = (rtIter->first->GetInterface () == interface); + Ipv6InterfaceAddress rtDestAddr = Ipv6InterfaceAddress(rtIter->first->GetDestNetwork ()); + + NS_LOG_DEBUG ("Processing RT " << rtDestAddr << " " << int(rtIter->first->IsRouteChanged ())); + + bool isGlobal = (rtDestAddr.GetScope () == Ipv6InterfaceAddress::GLOBAL); + bool isDefaultRoute = ((rtIter->first->GetDestNetwork () == Ipv6Address::GetAny ()) && + (rtIter->first->GetDestNetworkPrefix () == Ipv6Prefix::GetZero ()) && + (rtIter->first->GetInterface () != interface)); + + if ((isGlobal || isDefaultRoute) && + (periodic || rtIter->first->IsRouteChanged ())) + { + RipNgRte rte; + rte.SetPrefix (rtIter->first->GetDestNetwork ()); + rte.SetPrefixLen (rtIter->first->GetDestNetworkPrefix ().GetPrefixLength ()); + if (m_splitHorizonStrategy == POISON_REVERSE && splitHorizoning) + { + rte.SetRouteMetric (16); + } + else + { + rte.SetRouteMetric (rtIter->first->GetRouteMetric ()); + } + rte.SetRouteTag (rtIter->first->GetRouteTag ()); + if (m_splitHorizonStrategy == SPLIT_HORIZON && !splitHorizoning) + { + hdr.AddRte (rte); + } + else if (m_splitHorizonStrategy != SPLIT_HORIZON) + { + hdr.AddRte (rte); + } + } + if (hdr.GetRteNumber () == maxRte) + { + p->AddHeader (hdr); + NS_LOG_DEBUG ("SendTo: " << *p); + iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT)); + p->RemoveHeader (hdr); + hdr.ClearRtes (); + } + } + if (hdr.GetRteNumber () > 0) + { + p->AddHeader (hdr); + NS_LOG_DEBUG ("SendTo: " << *p); + iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT)); + } + } + } + for (RoutesI rtIter = m_routes.begin (); rtIter != m_routes.end (); rtIter++) + { + rtIter->first->SetRouteChanged (false); + } +} + +void RipNg::SendTriggeredRouteUpdate () +{ + NS_LOG_FUNCTION (this); + + if (m_nextTriggeredUpdate.IsRunning()) + { + NS_LOG_LOGIC ("Skipping Triggered Update due to cooldown"); + return; + } + + // DoSendRouteUpdate (false); + + // note: The RFC states: + // After a triggered + // update is sent, a timer should be set for a random interval between 1 + // and 5 seconds. If other changes that would trigger updates occur + // before the timer expires, a single update is triggered when the timer + // expires. The timer is then reset to another random value between 1 + // and 5 seconds. Triggered updates may be suppressed if a regular + // update is due by the time the triggered update would be sent. + // Here we rely on this: + // When an update occurs (either Triggered or Periodic) the "IsChanged ()" + // route field will be cleared. + // Hence, the following Triggered Update will be fired, but will not send + // any route update. + + Time delay = Seconds (m_rng->GetValue (m_minTriggeredUpdateDelay.GetSeconds (), m_maxTriggeredUpdateDelay.GetSeconds ())); + m_nextTriggeredUpdate = Simulator::Schedule (delay, &RipNg::DoSendRouteUpdate, this, false); +} + +void RipNg::SendUnsolicitedRouteUpdate () +{ + NS_LOG_FUNCTION (this); + + if (m_nextTriggeredUpdate.IsRunning()) + { + m_nextTriggeredUpdate.Cancel (); + } + + DoSendRouteUpdate (true); + + Time delay = m_unsolicitedUpdate + Seconds (m_rng->GetValue (0, 0.5*m_unsolicitedUpdate.GetSeconds ()) ); + m_nextUnsolicitedUpdate = Simulator::Schedule (delay, &RipNg::SendUnsolicitedRouteUpdate, this); +} + +std::set RipNg::GetInterfaceExclusions () const +{ + return m_interfaceExclusions; +} + +void RipNg::SetInterfaceExclusions (std::set exceptions) +{ + NS_LOG_FUNCTION (this); + + m_interfaceExclusions = exceptions; +} + +uint8_t RipNg::GetInterfaceMetric (uint32_t interface) const +{ + NS_LOG_FUNCTION (this << interface); + + std::map::const_iterator iter = m_interfaceMetrics.find (interface); + if (iter != m_interfaceMetrics.end ()) + { + return iter->second; + } + return 1; +} + +void RipNg::SetInterfaceMetric (uint32_t interface, uint8_t metric) +{ + NS_LOG_FUNCTION (this << interface << int (metric)); + + if (metric < 16) + { + m_interfaceMetrics[interface] = metric; + } +} + +void RipNg::SendRouteRequest () +{ + NS_LOG_FUNCTION (this); + + Ptr p = Create (); + SocketIpv6HopLimitTag tag; + p->RemovePacketTag (tag); + tag.SetHopLimit (255); + p->AddPacketTag (tag); + + RipNgHeader hdr; + hdr.SetCommand (RipNgHeader::REQUEST); + + RipNgRte rte; + rte.SetPrefix (Ipv6Address::GetAny ()); + rte.SetPrefixLen (0); + rte.SetRouteMetric (16); + + hdr.AddRte (rte); + p->AddHeader (hdr); + + for (SocketListI iter = m_sendSocketList.begin (); iter != m_sendSocketList.end (); iter++ ) + { + uint32_t interface = iter->second; + + if (m_interfaceExclusions.find (interface) == m_interfaceExclusions.end ()) + { + NS_LOG_DEBUG ("SendTo: " << *p); + iter->first->SendTo (p, 0, Inet6SocketAddress (RIPNG_ALL_NODE, RIPNG_PORT)); + } + } +} + +void RipNg::AddDefaultRouteTo (Ipv6Address nextHop, uint32_t interface) +{ + NS_LOG_FUNCTION (this << interface); + + AddNetworkRouteTo (Ipv6Address ("::"), Ipv6Prefix::GetZero (), nextHop, interface, Ipv6Address ("::")); +} + + +/* + * RipNgRoutingTableEntry + */ + +RipNgRoutingTableEntry::RipNgRoutingTableEntry () + : m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false) +{ +} + +RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse) + : Ipv6RoutingTableEntry ( RipNgRoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, nextHop, interface, prefixToUse) ), + m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false) +{ +} + +RipNgRoutingTableEntry::RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface) + : Ipv6RoutingTableEntry ( Ipv6RoutingTableEntry::CreateNetworkRouteTo (network, networkPrefix, interface) ), + m_tag (0), m_metric (16), m_status (RIPNG_INVALID), m_changed (false) +{ +} + +RipNgRoutingTableEntry::~RipNgRoutingTableEntry () +{ +} + + +void RipNgRoutingTableEntry::SetRouteTag (uint16_t routeTag) +{ + if (m_tag != routeTag) + { + m_tag = routeTag; + m_changed = true; + } +} + +uint16_t RipNgRoutingTableEntry::GetRouteTag () const +{ + return m_tag; +} + +void RipNgRoutingTableEntry::SetRouteMetric (uint8_t routeMetric) +{ + if (m_metric != routeMetric) + { + m_metric = routeMetric; + m_changed = true; + } +} + +uint8_t RipNgRoutingTableEntry::GetRouteMetric () const +{ + return m_metric; +} + +void RipNgRoutingTableEntry::SetRouteStatus (Status_e status) +{ + if (m_status != status) + { + m_status = status; + m_changed = true; + } +} + +RipNgRoutingTableEntry::Status_e RipNgRoutingTableEntry::GetRouteStatus (void) const +{ + return m_status; +} + +void RipNgRoutingTableEntry::SetRouteChanged (bool changed) +{ + m_changed = changed; +} + +bool RipNgRoutingTableEntry::IsRouteChanged (void) const +{ + return m_changed; +} + + +std::ostream & operator << (std::ostream& os, const RipNgRoutingTableEntry& rte) +{ + os << static_cast(rte); + os << ", metric: " << int (rte.GetRouteMetric ()) << ", tag: " << int (rte.GetRouteTag ()); + + return os; +} + + +} + diff --git a/src/internet/model/ripng.h b/src/internet/model/ripng.h new file mode 100644 index 000000000..3f95e685f --- /dev/null +++ b/src/internet/model/ripng.h @@ -0,0 +1,411 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#ifndef RIPNG_H +#define RIPNG_H + +#include + +#include "ns3/ipv6-routing-protocol.h" +#include "ns3/ipv6-interface.h" +#include "ns3/inet6-socket-address.h" +#include "ns3/ipv6-l3-protocol.h" +#include "ns3/ipv6-routing-table-entry.h" +#include "ns3/random-variable-stream.h" +#include "ns3/ripng-header.h" + +namespace ns3 { + +/** + * \defgroup ripng RIPng + * + * The RIPng protocol (\rfc{2080}) is a unicast-only IPv6 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. + * + * RIPng 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 RIPng 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 ripng + * \brief RipNg Routing Table Entry + */ +class RipNgRoutingTableEntry : public Ipv6RoutingTableEntry +{ +public: + + /** + * Route status + */ + enum Status_e { + RIPNG_VALID, + RIPNG_INVALID, + }; + + RipNgRoutingTableEntry (void); + + /** + * \brief Constructor + * \param network network address + * \param networkPrefix network prefix + * \param nextHop next hop address to route the packet + * \param interface interface index + * \param prefixToUse prefix that should be used for source address for this destination + */ + RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse); + + /** + * \brief Constructor + * \param network network address + * \param networkPrefix network prefix + * \param interface interface index + */ + RipNgRoutingTableEntry (Ipv6Address network, Ipv6Prefix networkPrefix, uint32_t interface); + + virtual ~RipNgRoutingTableEntry (); + + /** + * \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 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 Ipv6 routing table entry + * \returns the reference to the output stream + */ +std::ostream& operator<< (std::ostream& os, RipNgRoutingTableEntry const& route); + + + +/** + * \ingroup ripng + * + * \brief RIPng Routing Protocol, defined in \rfc{2080}. + */ +class RipNg : public Ipv6RoutingProtocol +{ +public: + // /< C-tor + RipNg (); + virtual ~RipNg (); + + static TypeId GetTypeId (void); + + // \name From Ipv6RoutingProtocol + // \{ + Ptr RouteOutput (Ptr p, const Ipv6Header &header, Ptr oif, + Socket::SocketErrno &sockerr); + bool RouteInput (Ptr p, const Ipv6Header &header, Ptr 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, Ipv6InterfaceAddress address); + virtual void NotifyRemoveAddress (uint32_t interface, Ipv6InterfaceAddress address); + virtual void NotifyAddRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, + uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ()); + virtual void NotifyRemoveRoute (Ipv6Address dst, Ipv6Prefix mask, Ipv6Address nextHop, + uint32_t interface, Ipv6Address prefixToUse = Ipv6Address::GetZero ()); + virtual void SetIpv6 (Ptr ipv6); + virtual void PrintRoutingTable (Ptr stream) const; + // \} + + enum SplitHorizonType_e { + NO_SPLIT_HORIZON, + SPLIT_HORIZON, + POISON_REVERSE, + }; + + /** + * 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 GetInterfaceExclusions () const; + + /** + * \brief Set the set of interface excluded from the protocol + * \param exceptions the set of excluded interfaces + */ + void SetInterfaceExclusions (std::set 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 (Ipv6Address nextHop, uint32_t interface); + +protected: + /** + * \brief Dispose this object. + */ + virtual void DoDispose (); + + /** + * Start protocol operation + */ + void DoInitialize (); + +private: + /// Container for the network routes - pair RipNgRoutingTableEntry *, EventId (update event) + typedef std::list > Routes; + + /// Const Iterator for container for the network routes + typedef std::list >::const_iterator RoutesCI; + + /// Iterator for container for the network routes + typedef std::list >::iterator RoutesI; + + + /** + * \brief Receive RIPng packets. + * + * \param socket the socket the packet was received to. + */ + void Receive (Ptr socket); + + /** + * \brief Handle RIPng 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 (RipNgHeader hdr, Ipv6Address senderAddress, uint16_t senderPort, uint32_t incomingInterface, uint8_t hopLimit); + + /** + * \brief Handle RIPng responses. + * + * \param hdr message header (including RTEs) + * \param senderAddress sender address + * \param incomingInterface incoming interface + * \param hopLimit packet's hop limit + */ + void HandleResponses (RipNgHeader hdr, Ipv6Address 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 Ipv6Route to route the packet to reach dest address + */ + Ptr Lookup (Ipv6Address dest, Ptr = 0); + + /** + * Receive and process unicast packet + * \param socket socket where packet is arrived + */ + void RecvUnicastRipng (Ptr socket); + /** + * Receive and process multicast packet + * \param socket socket where packet is arrived + */ + void RecvMulticastRipng (Ptr 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 + * \param prefixToUse prefix that should be used for source address for this destination + * \param metric metric of route in case of multiple routes to same destination + */ + void AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix networkPrefix, Ipv6Address nextHop, uint32_t interface, Ipv6Address prefixToUse); + + /** + * \brief Add route to network. + * \param network network address + * \param networkPrefix network prefix + * \param interface interface index + * \param metric metric of route in case of multiple routes to same destination + */ + void AddNetworkRouteTo (Ipv6Address network, Ipv6Prefix 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 (RipNgRoutingTableEntry *route); + + /** + * \brief Delete a route. + * \param route the route to be removed + */ + void DeleteRoute (RipNgRoutingTableEntry *route); + + Routes m_routes; //!< the forwarding table for network. + Ptr m_ipv6; //!< IPv6 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, uint32_t> SocketList; + /// Socket list type iterator + typedef std::map, uint32_t>::iterator SocketListI; + /// Socket list type const iterator + typedef std::map, uint32_t>::const_iterator SocketListCI; + + SocketList m_sendSocketList; //!< list of sockets for sending (socket, interface index) + Ptr m_recvSocket; + + EventId m_nextUnsolicitedUpdate; //!< Next Unsolicited Update event + EventId m_nextTriggeredUpdate; //!< Next Triggered Update event + + Ptr m_rng; //!< Rng stream. + + std::set m_interfaceExclusions; // Set of excluded interfaces + std::map m_interfaceMetrics; // Map of interface metrics + + SplitHorizonType_e m_splitHorizonStrategy; // Split Horizon strategy + + bool m_initialized; // flag to allow socket's late-creation. +}; + +} // namespace ns3 +#endif /* RIPNG_H */ + diff --git a/src/internet/test/ipv6-ripng-test.cc b/src/internet/test/ipv6-ripng-test.cc new file mode 100644 index 000000000..9a21d88e8 --- /dev/null +++ b/src/internet/test/ipv6-ripng-test.cc @@ -0,0 +1,652 @@ +/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ +/* + * Copyright (c) 2014 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 + */ + +#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/inet6-socket-address.h" + +#include "ns3/internet-stack-helper.h" +#include "ns3/ipv6-address-helper.h" +#include "ns3/ipv6-l3-protocol.h" +#include "ns3/icmpv6-l4-protocol.h" +#include "ns3/udp-l4-protocol.h" +#include "ns3/ipv6-static-routing.h" +#include "ns3/ipv6-list-routing.h" +#include "ns3/ipv6-list-routing-helper.h" +#include "ns3/ripng.h" +#include "ns3/ripng-helper.h" +#include "ns3/node-container.h" + +#include +#include + +using namespace ns3; + +// Ipv6RipngTest + +class Ipv6RipngTest : public TestCase +{ + Ptr m_receivedPacket; + void DoSendData (Ptr socket, std::string to); + void SendData (Ptr socket, std::string to); + +public: + virtual void DoRun (void); + Ipv6RipngTest (); + + void ReceivePkt (Ptr socket); +}; + +Ipv6RipngTest::Ipv6RipngTest () + : TestCase ("RIPng") +{ +} + +void Ipv6RipngTest::ReceivePkt (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + m_receivedPacket = socket->Recv (std::numeric_limits::max (), 0); + NS_ASSERT (availableData == m_receivedPacket->GetSize ()); + //cast availableData to void, to suppress 'availableData' set but not used + //compiler warning + (void) availableData; +} + +void +Ipv6RipngTest::DoSendData (Ptr socket, std::string to) +{ + Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234); + NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create (123), 0, realTo), + 123, "100"); +} + +void +Ipv6RipngTest::SendData (Ptr socket, std::string to) +{ + m_receivedPacket = Create (); + Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60), + &Ipv6RipngTest::DoSendData, this, socket, to); + Simulator::Stop (Seconds (66)); + Simulator::Run (); +} + +void +Ipv6RipngTest::DoRun (void) +{ + // Create topology + + Ptr txNode = CreateObject (); + Ptr rxNode = CreateObject (); + Ptr routerA = CreateObject (); + Ptr routerB = CreateObject (); + Ptr routerC = CreateObject (); + + NodeContainer nodes (txNode, rxNode); + NodeContainer routers (routerA, routerB, routerC); + NodeContainer all (nodes, routers); + + RipNgHelper ripNgRouting; + Ipv6ListRoutingHelper listRH; + listRH.Add (ripNgRouting, 0); + InternetStackHelper internetv6routers; + internetv6routers.SetRoutingHelper (listRH); + internetv6routers.Install (routers); + + InternetStackHelper internetv6nodes; + internetv6nodes.Install (nodes); + + NetDeviceContainer net1; + NetDeviceContainer net2; + NetDeviceContainer net3; + NetDeviceContainer net4; + + // Sender Node + Ptr txDev; + { + txDev = CreateObject (); + txDev->SetAddress (Mac48Address ("00:00:00:00:00:01")); + txNode->AddDevice (txDev); + } + net1.Add (txDev); + + // Router A + Ptr fwDev1routerA, fwDev2routerA; + { // first interface + fwDev1routerA = CreateObject (); + fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02")); + routerA->AddDevice (fwDev1routerA); + } + net1.Add (fwDev1routerA); + + { // second interface + fwDev2routerA = CreateObject (); + fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03")); + routerA->AddDevice (fwDev2routerA); + } + net2.Add (fwDev2routerA); + + // Router B + Ptr fwDev1routerB, fwDev2routerB; + { // first interface + fwDev1routerB = CreateObject (); + fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04")); + routerB->AddDevice (fwDev1routerB); + } + net2.Add (fwDev1routerB); + + { // second interface + fwDev2routerB = CreateObject (); + fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05")); + routerB->AddDevice (fwDev2routerB); + } + net3.Add (fwDev2routerB); + + // Router C + Ptr fwDev1routerC, fwDev2routerC; + { // first interface + fwDev1routerC = CreateObject (); + fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06")); + routerC->AddDevice (fwDev1routerC); + } + net3.Add (fwDev1routerC); + + { // second interface + fwDev2routerC = CreateObject (); + fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07")); + routerC->AddDevice (fwDev2routerC); + } + net4.Add (fwDev2routerC); + + // Rx node + Ptr rxDev; + { // first interface + rxDev = CreateObject (); + rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08")); + rxNode->AddDevice (rxDev); + } + net4.Add (rxDev); + + // link the channels + Ptr channel1 = CreateObject (); + txDev->SetChannel (channel1); + fwDev1routerA->SetChannel (channel1); + + Ptr channel2 = CreateObject (); + fwDev2routerA->SetChannel (channel2); + fwDev1routerB->SetChannel (channel2); + + Ptr channel3 = CreateObject (); + fwDev2routerB->SetChannel (channel3); + fwDev1routerC->SetChannel (channel3); + + Ptr channel4 = CreateObject (); + fwDev2routerC->SetChannel (channel4); + rxDev->SetChannel (channel4); + + // Setup IPv6 addresses and forwarding + Ipv6AddressHelper ipv6; + + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic1 = ipv6.Assign (net1); + iic1.SetForwarding (1, true); + iic1.SetDefaultRouteInAllNodes (1); + + Ipv6InterfaceContainer iic2 = ipv6.AssignWithoutAddress (net2); + iic2.SetForwarding (0, true); + iic2.SetForwarding (1, true); + + Ipv6InterfaceContainer iic3 = ipv6.AssignWithoutAddress (net3); + iic3.SetForwarding (0, true); + iic3.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic4 = ipv6.Assign (net4); + iic4.SetForwarding (0, true); + iic4.SetDefaultRouteInAllNodes (0); + + // Create the UDP sockets + Ptr rxSocketFactory = rxNode->GetObject (); + Ptr rxSocket = rxSocketFactory->CreateSocket (); + NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:2::200:ff:fe00:8"), 1234)), 0, "trivial"); + rxSocket->SetRecvCallback (MakeCallback (&Ipv6RipngTest::ReceivePkt, this)); + + Ptr txSocketFactory = txNode->GetObject (); + Ptr txSocket = txSocketFactory->CreateSocket (); + txSocket->SetAllowBroadcast (true); + + // ------ Now the tests ------------ + + // Unicast test + SendData (txSocket, "2001:2::200:ff:fe00:8"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 123, "IPv6 RIPng should work."); + + m_receivedPacket->RemoveAllByteTags (); + + Simulator::Destroy (); +} + +// Ipv6RipngCountToInfinityTest + +class Ipv6RipngCountToInfinityTest : public TestCase +{ + Ptr m_receivedPacket; + void DoSendData (Ptr socket, std::string to); + void SendData (Ptr socket, std::string to); + +public: + virtual void DoRun (void); + Ipv6RipngCountToInfinityTest (); + + void ReceivePkt (Ptr socket); +}; + +Ipv6RipngCountToInfinityTest::Ipv6RipngCountToInfinityTest () + : TestCase ("RIPng counting to infinity") +{ +} + +void Ipv6RipngCountToInfinityTest::ReceivePkt (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + m_receivedPacket = socket->Recv (std::numeric_limits::max (), 0); + NS_ASSERT (availableData == m_receivedPacket->GetSize ()); + //cast availableData to void, to suppress 'availableData' set but not used + //compiler warning + (void) availableData; +} + +void +Ipv6RipngCountToInfinityTest::DoSendData (Ptr socket, std::string to) +{ + Address realTo = Inet6SocketAddress (Ipv6Address (to.c_str ()), 1234); + NS_TEST_EXPECT_MSG_EQ (socket->SendTo (Create (123), 0, realTo), + 123, "100"); +} + +void +Ipv6RipngCountToInfinityTest::SendData (Ptr socket, std::string to) +{ + m_receivedPacket = Create (); + Simulator::ScheduleWithContext (socket->GetNode ()->GetId (), Seconds (60), + &Ipv6RipngCountToInfinityTest::DoSendData, this, socket, to); + Simulator::Stop (Seconds (66)); + Simulator::Run (); +} + +void +Ipv6RipngCountToInfinityTest::DoRun (void) +{ + // Create topology + + Ptr txNode = CreateObject (); + Ptr rxNode = CreateObject (); + Ptr routerA = CreateObject (); + Ptr routerB = CreateObject (); + Ptr routerC = CreateObject (); + + NodeContainer nodes (txNode, rxNode); + NodeContainer routers (routerA, routerB, routerC); + NodeContainer all (nodes, routers); + + RipNgHelper 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); + + Ipv6ListRoutingHelper listRH; + listRH.Add (ripNgRouting, 0); + InternetStackHelper internetv6routers; + internetv6routers.SetRoutingHelper (listRH); + internetv6routers.Install (routers); + + InternetStackHelper internetv6nodes; + internetv6nodes.Install (nodes); + + NetDeviceContainer net1; + NetDeviceContainer net2; + NetDeviceContainer net3; + NetDeviceContainer net4; + + // Sender Node + Ptr txDev; + { + txDev = CreateObject (); + txDev->SetAddress (Mac48Address ("00:00:00:00:00:01")); + txNode->AddDevice (txDev); + } + net1.Add (txDev); + + // Router A + Ptr fwDev1routerA, fwDev2routerA; + { // first interface + fwDev1routerA = CreateObject (); + fwDev1routerA->SetAddress (Mac48Address ("00:00:00:00:00:02")); + routerA->AddDevice (fwDev1routerA); + } + net1.Add (fwDev1routerA); + + { // second interface + fwDev2routerA = CreateObject (); + fwDev2routerA->SetAddress (Mac48Address ("00:00:00:00:00:03")); + routerA->AddDevice (fwDev2routerA); + } + net2.Add (fwDev2routerA); + + // Router B + Ptr fwDev1routerB, fwDev2routerB; + { // first interface + fwDev1routerB = CreateObject (); + fwDev1routerB->SetAddress (Mac48Address ("00:00:00:00:00:04")); + routerB->AddDevice (fwDev1routerB); + } + net2.Add (fwDev1routerB); + + { // second interface + fwDev2routerB = CreateObject (); + fwDev2routerB->SetAddress (Mac48Address ("00:00:00:00:00:05")); + routerB->AddDevice (fwDev2routerB); + } + net3.Add (fwDev2routerB); + + // Router C + Ptr fwDev1routerC, fwDev2routerC; + { // first interface + fwDev1routerC = CreateObject (); + fwDev1routerC->SetAddress (Mac48Address ("00:00:00:00:00:06")); + routerC->AddDevice (fwDev1routerC); + } + net3.Add (fwDev1routerC); + + { // second interface + fwDev2routerC = CreateObject (); + fwDev2routerC->SetAddress (Mac48Address ("00:00:00:00:00:07")); + routerC->AddDevice (fwDev2routerC); + } + net4.Add (fwDev2routerC); + + // Rx node + Ptr rxDev; + { // first interface + rxDev = CreateObject (); + rxDev->SetAddress (Mac48Address ("00:00:00:00:00:08")); + rxNode->AddDevice (rxDev); + } + net4.Add (rxDev); + + // link the channels + Ptr channel1 = CreateObject (); + txDev->SetChannel (channel1); + fwDev1routerA->SetChannel (channel1); + + Ptr channel2 = CreateObject (); + fwDev2routerA->SetChannel (channel2); + fwDev1routerB->SetChannel (channel2); + + Ptr channel3 = CreateObject (); + fwDev2routerB->SetChannel (channel3); + fwDev1routerC->SetChannel (channel3); + + Ptr channel4 = CreateObject (); + fwDev2routerC->SetChannel (channel4); + rxDev->SetChannel (channel4); + + // Setup IPv6 addresses and forwarding + Ipv6AddressHelper ipv6; + + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic1 = ipv6.Assign (net1); + iic1.SetForwarding (1, true); + iic1.SetDefaultRouteInAllNodes (1); + + Ipv6InterfaceContainer iic2 = ipv6.AssignWithoutAddress (net2); + iic2.SetForwarding (0, true); + iic2.SetForwarding (1, true); + + Ipv6InterfaceContainer iic3 = ipv6.AssignWithoutAddress (net3); + iic3.SetForwarding (0, true); + iic3.SetForwarding (1, true); + + ipv6.SetBase (Ipv6Address ("2001:2::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic4 = ipv6.Assign (net4); + iic4.SetForwarding (0, true); + iic4.SetDefaultRouteInAllNodes (0); + + // Create the UDP sockets + Ptr rxSocketFactory = rxNode->GetObject (); + Ptr rxSocket = rxSocketFactory->CreateSocket (); + NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("2001:2::200:ff:fe00:8"), 1234)), 0, "trivial"); + rxSocket->SetRecvCallback (MakeCallback (&Ipv6RipngCountToInfinityTest::ReceivePkt, this)); + + Ptr txSocketFactory = txNode->GetObject (); + Ptr txSocket = txSocketFactory->CreateSocket (); + txSocket->SetAllowBroadcast (true); + + // ------ Now the tests ------------ + + SendData (txSocket, "2001:2::200:ff:fe00:8"); + NS_TEST_EXPECT_MSG_EQ (m_receivedPacket->GetSize (), 0, "RIPng counting to infinity."); + + Simulator::Destroy (); +} + +// Ipv6RipngSplitHorizonStrategyTest + +class Ipv6RipngSplitHorizonStrategyTest : public TestCase +{ + RipNg::SplitHorizonType_e m_setStrategy; + RipNg::SplitHorizonType_e m_detectedStrategy; + +public: + virtual void DoRun (void); + Ipv6RipngSplitHorizonStrategyTest (RipNg::SplitHorizonType_e strategy); + + void ReceivePktProbe (Ptr socket); +}; + +Ipv6RipngSplitHorizonStrategyTest::Ipv6RipngSplitHorizonStrategyTest (RipNg::SplitHorizonType_e strategy) + : TestCase ("RIPng Split Horizon strategy") +{ + m_setStrategy = strategy; +} + +void Ipv6RipngSplitHorizonStrategyTest::ReceivePktProbe (Ptr socket) +{ + uint32_t availableData; + availableData = socket->GetRxAvailable (); + Ptr receivedPacketProbe = socket->Recv (std::numeric_limits::max (), 0); + NS_ASSERT (availableData == receivedPacketProbe->GetSize ()); + SocketAddressTag tag; + receivedPacketProbe->RemovePacketTag (tag); + Ipv6Address senderAddress = Inet6SocketAddress::ConvertFrom (tag.GetAddress ()).GetIpv6 (); + + if (senderAddress == "fe80::200:ff:fe00:4") + { + RipNgHeader hdr; + receivedPacketProbe->RemoveHeader (hdr); + std::list rtes = hdr.GetRteList (); + + // validate the RTEs before processing + for (std::list::iterator iter = rtes.begin (); + iter != rtes.end (); iter++) + { + if (iter->GetPrefix () == "2001:1::") + { + bool correct = false; + if (iter->GetRouteMetric () == 16) + { + correct = true; + m_detectedStrategy = RipNg::POISON_REVERSE; + } + else if (iter->GetRouteMetric () == 2) + { + correct = true; + m_detectedStrategy = RipNg::NO_SPLIT_HORIZON; + } + NS_TEST_EXPECT_MSG_EQ (correct, true, "RIPng: unexpected metric value: " << iter->GetRouteMetric ()); + } + } + } + + //cast availableData to void, to suppress 'availableData' set but not used + //compiler warning + (void) availableData; +} + +void +Ipv6RipngSplitHorizonStrategyTest::DoRun (void) +{ + // Create topology + + Ptr fakeNode = CreateObject (); + Ptr listener = CreateObject (); + + Ptr routerA = CreateObject (); + Ptr routerB = CreateObject (); + + NodeContainer listeners (listener, fakeNode); + NodeContainer routers (routerA, routerB); + NodeContainer all (routers, listeners); + + RipNgHelper ripNgRouting; + ripNgRouting.Set ("SplitHorizon", EnumValue (m_setStrategy)); + + Ipv6ListRoutingHelper listRH; + listRH.Add (ripNgRouting, 0); + InternetStackHelper internetv6routers; + internetv6routers.SetRoutingHelper (listRH); + internetv6routers.Install (routers); + + InternetStackHelper internetv6nodes; + internetv6nodes.Install (listeners); + + NetDeviceContainer net0; + NetDeviceContainer net1; + + // Fake Node + Ptr silentDev; + { + silentDev = CreateObject (); + silentDev->SetAddress (Mac48Address ("00:00:00:00:00:01")); + fakeNode->AddDevice (silentDev); + } + net0.Add (silentDev); + + // Router A + Ptr silentDevRouterA, fwDevRouterA; + { // silent interface + silentDevRouterA = CreateObject (); + silentDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:02")); + routerA->AddDevice (silentDevRouterA); + } + net0.Add (silentDevRouterA); + + { // first interface + fwDevRouterA = CreateObject (); + fwDevRouterA->SetAddress (Mac48Address ("00:00:00:00:00:03")); + routerA->AddDevice (fwDevRouterA); + } + net1.Add (fwDevRouterA); + + // Router B + Ptr fwDevRouterB; + { // first interface + fwDevRouterB = CreateObject (); + fwDevRouterB->SetAddress (Mac48Address ("00:00:00:00:00:04")); + routerB->AddDevice (fwDevRouterB); + } + net1.Add (fwDevRouterB); + + // listener A + Ptr listenerDev; + { + listenerDev = CreateObject (); + listenerDev->SetAddress (Mac48Address ("00:00:00:00:00:05")); + listener->AddDevice (listenerDev); + } + net1.Add (listenerDev); + + // link the channels + Ptr channel0 = CreateObject (); + silentDev->SetChannel (channel0); + silentDevRouterA->SetChannel (channel0); + + Ptr channel1 = CreateObject (); + fwDevRouterA->SetChannel (channel1); + fwDevRouterB->SetChannel (channel1); + listenerDev->SetChannel (channel1); + + // Setup IPv6 addresses and forwarding + Ipv6AddressHelper ipv6; + + ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64)); + Ipv6InterfaceContainer iic0 = ipv6.Assign (net0); + + Ipv6InterfaceContainer iic1 = ipv6.AssignWithoutAddress (net1); + iic1.SetForwarding (0, true); + iic1.SetForwarding (1, true); + + // Create the UDP sockets + Ptr rxSocketFactory = listener->GetObject (); + Ptr rxSocket = rxSocketFactory->CreateSocket (); + NS_TEST_EXPECT_MSG_EQ (rxSocket->Bind (Inet6SocketAddress (Ipv6Address ("ff02::9"), 521)), 0, "trivial"); + rxSocket->SetRecvCallback (MakeCallback (&Ipv6RipngSplitHorizonStrategyTest::ReceivePktProbe, this)); + + // ------ Now the tests ------------ + + // If the strategy is Split Horizon, then no packet will be received. + m_detectedStrategy = RipNg::SPLIT_HORIZON; + + Simulator::Stop (Seconds (66)); + Simulator::Run (); + NS_TEST_EXPECT_MSG_EQ (m_detectedStrategy, m_setStrategy, "RIPng counting to infinity."); + + Simulator::Destroy (); +} + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +class Ipv6RipngTestSuite : public TestSuite +{ +public: + Ipv6RipngTestSuite () : TestSuite ("ipv6-ripng", UNIT) + { + AddTestCase (new Ipv6RipngTest, TestCase::QUICK); + AddTestCase (new Ipv6RipngCountToInfinityTest, TestCase::QUICK); + AddTestCase (new Ipv6RipngSplitHorizonStrategyTest (RipNg::POISON_REVERSE), TestCase::QUICK); + AddTestCase (new Ipv6RipngSplitHorizonStrategyTest (RipNg::SPLIT_HORIZON), TestCase::QUICK); + AddTestCase (new Ipv6RipngSplitHorizonStrategyTest (RipNg::NO_SPLIT_HORIZON), TestCase::QUICK); + } +} g_ipv6ripngTestSuite; diff --git a/src/internet/wscript b/src/internet/wscript index 9c180220f..da99ff1e3 100644 --- a/src/internet/wscript +++ b/src/internet/wscript @@ -192,6 +192,9 @@ def build(bld): 'model/ipv4-packet-probe.cc', 'model/ipv6-packet-probe.cc', 'model/ipv6-pmtu-cache.cc', + 'model/ripng.cc', + 'model/ripng-header.cc', + 'helper/ripng-helper.cc', ] internet_test = bld.create_ns3_module_test_library('internet') @@ -218,7 +221,8 @@ def build(bld): 'test/ipv6-dual-stack-test-suite.cc', 'test/ipv6-fragmentation-test.cc', 'test/ipv6-forwarding-test.cc', - 'test/ipv6-address-helper-test-suite.cc', + 'test/ipv6-ripng-test.cc', + 'test/ipv6-address-helper-test-suite.cc', 'test/rtt-test.cc', ] headers = bld(features='ns3header') @@ -305,6 +309,9 @@ def build(bld): 'model/ipv4-packet-probe.h', 'model/ipv6-packet-probe.h', 'model/ipv6-pmtu-cache.h', + 'model/ripng.h', + 'model/ripng-header.h', + 'helper/ripng-helper.h', ] if bld.env['NSC_ENABLED']: