/* * 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 "ns3/core-module.h" #include "ns3/csma-module.h" #include "ns3/internet-apps-module.h" #include "ns3/internet-module.h" #include "ns3/ipv6-routing-table-entry.h" #include "ns3/ipv6-static-routing-helper.h" #include 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(__FILE__); 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); Ipv6StaticRoutingHelper staticRh; listRH.Add(staticRh, 5); 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."); return 0; }