--- a/CHANGES.html Tue Dec 21 21:57:50 2010 -0800
+++ b/CHANGES.html Tue Dec 21 22:43:06 2010 -0800
@@ -103,6 +103,9 @@
<p>New class methods and helpers for printing IPv4 routing tables
to an output stream. </p></li>
+<li><b>Destination-Sequenced Distance Vector (DSDV) routing protocol</b>
+<p>Derives from Ipv4RoutingProtocol and contains a DsdvHelper class. </p></li>
+
</ul>
<h2>Changes to existing API:</h2>
--- a/RELEASE_NOTES Tue Dec 21 21:57:50 2010 -0800
+++ b/RELEASE_NOTES Tue Dec 21 22:43:06 2010 -0800
@@ -86,6 +86,12 @@
set for WHOI acoustic transducer. Li-Ion battery model added
into energy models folder.
+ - Destination-Sequenced Distance Vector (DSDV) routing protocol
+ is a proactive, table-driven routing protocol for MANETs
+ developed by Charles E. Perkins and Pravin Bhagwat in 1994.
+ This implementation is for IPv4 routing and was contributed
+ by ResilNets Research Group.
+
Bugs fixed
----------
The following lists many of the bugs fixed or small feature additions
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/doc/dsdv.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,78 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra, Yufei Cheng
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ * Author: Yufei Cheng <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef DSDV_H_
+#define DSDV_H_
+
+/**
+ * \ingroup routing
+ * \defgroup dsdv
+ *
+ * \brief Destination-Sequenced Distance Vector (DSDV) routing protocol is a pro-active, table-driven routing protocol
+ * for MANETs developed by Charles E. Perkins and Pravin Bhagwat in 1994. It uses the hop count as metric in route
+ * selection.
+ *
+ * DSDV Routing Table: Every node will maintain a table listing all the other nodes it has known either directly
+ * or through some neighbors. Every node has a single entry in the routing table. The entry will have information
+ * about the node's IP address, last known sequence number and the hop count to reach that node. Along with these
+ * details the table also keeps track of the nexthop neighbor to reach the destination node, the timestamp of the last
+ * update received for that node.
+ *
+ * The DSDV update message consists of three fields, Destination Address, Sequence Number and Hop Count.
+ *
+ * Each node uses 2 mechanisms to send out the DSDV updates. They are,
+ * 1. Periodic Updates
+ * Periodic updates are sent out after every m_periodicUpdateInterval(default:15s). In this update the node broadcasts
+ * out its entire routing table.
+ * 2. Trigger Updates
+ * Trigger Updates are small updates in-between the periodic updates. These updates are sent out whenever a node
+ * receives a DSDV packet that caused a change in its routing table. The original paper did not clearly mention
+ * when for what change in the table should a DSDV update be sent out. The current implemntation sends out an update
+ * irrespective of the change in the routing table.
+ *
+ * The updates are accepted based on the metric for a particular node. The first factor determinig the acceptance of
+ * an update is the sequence number. It has to accept the update if the sequence number of the update message is higher
+ * irrespective of the metric. If the update with same sequence number is received, then the update with least metric
+ * (hopCount) is given precedence.
+ *
+ * In highly mobile scenarios, there is a high chance of route fluctuations, thus we have the concept of weighted
+ * settling time where an update with change in metric will not be advertised to neighbors. The node waits for
+ * the settling time to make sure that it did not receive the update from its old neighbor before sending out
+ * that update.
+ *
+ * The current implementation covers all the above features of DSDV. The current implementation also has a request queue
+ * to buffer packets that have no routes to destination. The default is set to buffer up to 5 packets per destination.
+ *
+ * Link to the Paper: http://portal.acm.org/citation.cfm?doid=190314.190336
+ *
+ */
+
+#endif /* DSDV_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/examples/dsdv-manet.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,328 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "ns3/core-module.h"
+#include "ns3/common-module.h"
+#include "ns3/node-module.h"
+#include "ns3/helper-module.h"
+#include "ns3/mobility-module.h"
+#include "ns3/contrib-module.h"
+#include "ns3/wifi-module.h"
+#include "ns3/dsdv-helper.h"
+#include <iostream>
+#include <cmath>
+
+using namespace ns3;
+
+uint16_t port = 9;
+
+NS_LOG_COMPONENT_DEFINE ("DsdvManetExample");
+
+class DsdvManetExample
+{
+public:
+ DsdvManetExample ();
+ void CaseRun (uint32_t nWifis,
+ uint32_t nSinks,
+ double totalTime,
+ std::string rate,
+ std::string phyMode,
+ uint32_t nodeSpeed,
+ uint32_t periodicUpdateInterval,
+ uint32_t settlingTime,
+ double dataStart,
+ bool printRoutes,
+ std::string CSVfileName);
+
+private:
+ uint32_t m_nWifis;
+ uint32_t m_nSinks;
+ double m_totalTime;
+ std::string m_rate;
+ std::string m_phyMode;
+ uint32_t m_nodeSpeed;
+ uint32_t m_periodicUpdateInterval;
+ uint32_t m_settlingTime;
+ double m_dataStart;
+ uint32_t bytesTotal;
+ uint32_t packetsReceived;
+ bool m_printRoutes;
+ std::string m_CSVfileName;
+
+ NodeContainer nodes;
+ NetDeviceContainer devices;
+ Ipv4InterfaceContainer interfaces;
+
+private:
+ void CreateNodes ();
+ void CreateDevices (std::string tr_name);
+ void InstallInternetStack (std::string tr_name);
+ void InstallApplications ();
+ void SetupMobility ();
+ void ReceivePacket (Ptr <Socket> );
+ Ptr <Socket> SetupPacketReceive (Ipv4Address, Ptr <Node> );
+ void CheckThroughput ();
+
+};
+
+int main (int argc, char **argv)
+{
+ DsdvManetExample test;
+ uint32_t nWifis = 30;
+ uint32_t nSinks = 10;
+ double totalTime = 100.0;
+ std::string rate ("8kbps");
+ std::string phyMode ("DsssRate11Mbps");
+ uint32_t nodeSpeed = 10; // in m/s
+ std::string appl = "all";
+ uint32_t periodicUpdateInterval = 15;
+ uint32_t settlingTime = 6;
+ double dataStart = 50.0;
+ bool printRoutingTable = true;
+ std::string CSVfileName = "DsdvManetExample.csv";
+
+ CommandLine cmd;
+ cmd.AddValue ("nWifis", "Number of wifi nodes[Default:30]", nWifis);
+ cmd.AddValue ("nSinks", "Number of wifi sink nodes[Default:10]", nSinks);
+ cmd.AddValue ("totalTime", "Total Simulation time[Default:100]", totalTime);
+ cmd.AddValue ("phyMode", "Wifi Phy mode[Default:DsssRate11Mbps]", phyMode);
+ cmd.AddValue ("rate", "CBR traffic rate[Default:8kbps]", rate);
+ cmd.AddValue ("nodeSpeed", "Node speed in RandomWayPoint model[Default:10]", nodeSpeed);
+ cmd.AddValue ("periodicUpdateInterval", "Periodic Interval Time[Default=15]", periodicUpdateInterval);
+ cmd.AddValue ("settlingTime", "Settling Time before sending out an update for changed metric[Default=6]", settlingTime);
+ cmd.AddValue ("dataStart", "Time at which nodes start to transmit data[Default=50.0]", dataStart);
+ cmd.AddValue ("printRoutingTable", "print routing table for nodes[Default:1]", printRoutingTable);
+ cmd.AddValue ("CSVfileName", "The name of the CSV output file name[Default:DsdvManetExample.csv]", CSVfileName);
+ cmd.Parse (argc, argv);
+
+ std::ofstream out (CSVfileName.c_str ());
+ out << "SimulationSecond," <<
+ "ReceiveRate," <<
+ "PacketsReceived," <<
+ "NumberOfSinks," <<
+ std::endl;
+ out.close ();
+
+ SeedManager::SetSeed (12345);
+
+ Config::SetDefault ("ns3::OnOffApplication::PacketSize", StringValue ("1000"));
+ Config::SetDefault ("ns3::OnOffApplication::DataRate", StringValue (rate));
+ Config::SetDefault ("ns3::WifiRemoteStationManager::NonUnicastMode", StringValue (phyMode));
+ Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", StringValue ("2000"));
+
+ test = DsdvManetExample ();
+ test.CaseRun (nWifis, nSinks, totalTime, rate, phyMode, nodeSpeed, periodicUpdateInterval,
+ settlingTime, dataStart, printRoutingTable, CSVfileName);
+
+ return 0;
+}
+
+DsdvManetExample::DsdvManetExample ()
+ : bytesTotal (0),
+ packetsReceived (0)
+{
+}
+
+void
+DsdvManetExample::ReceivePacket (Ptr <Socket> socket)
+{
+ NS_LOG_UNCOND (Simulator::Now ().GetSeconds () << " Received one packet!");
+ Ptr <Packet> packet;
+ while (packet = socket->Recv ())
+ {
+ bytesTotal += packet->GetSize ();
+ packetsReceived += 1;
+ }
+}
+
+void
+DsdvManetExample::CheckThroughput ()
+{
+ double kbs = (bytesTotal * 8.0) / 1000;
+ bytesTotal = 0;
+
+ std::ofstream out (m_CSVfileName.c_str (), std::ios::app);
+
+ out << (Simulator::Now ()).GetSeconds () << "," << kbs << "," << packetsReceived << "," << m_nSinks << std::endl;
+
+ out.close ();
+ packetsReceived = 0;
+ Simulator::Schedule (Seconds (1.0), &DsdvManetExample::CheckThroughput, this);
+}
+
+Ptr <Socket>
+DsdvManetExample::SetupPacketReceive (Ipv4Address addr, Ptr <Node> node)
+{
+
+ TypeId tid = TypeId::LookupByName ("ns3::UdpSocketFactory");
+ Ptr <Socket> sink = Socket::CreateSocket (node, tid);
+ InetSocketAddress local = InetSocketAddress (addr, port);
+ sink->Bind (local);
+ sink->SetRecvCallback (MakeCallback ( &DsdvManetExample::ReceivePacket, this));
+
+ return sink;
+}
+
+void
+DsdvManetExample::CaseRun (uint32_t nWifis, uint32_t nSinks, double totalTime, std::string rate,
+ std::string phyMode, uint32_t nodeSpeed, uint32_t periodicUpdateInterval, uint32_t settlingTime,
+ double dataStart, bool printRoutes, std::string CSVfileName)
+{
+ m_nWifis = nWifis;
+ m_nSinks = nSinks;
+ m_totalTime = totalTime;
+ m_rate = rate;
+ m_phyMode = phyMode;
+ m_nodeSpeed = nodeSpeed;
+ m_periodicUpdateInterval = periodicUpdateInterval;
+ m_settlingTime = settlingTime;
+ m_dataStart = dataStart;
+ m_printRoutes = printRoutes;
+ m_CSVfileName = CSVfileName;
+
+ std::stringstream ss;
+ ss << m_nWifis;
+ std::string t_nodes = ss.str ();
+
+ std::stringstream ss3;
+ ss3 << m_totalTime;
+ std::string sTotalTime = ss3.str ();
+
+ std::string tr_name = "Dsdv_Manet_" + t_nodes + "Nodes_" + sTotalTime + "SimTime";
+ std::cout << "Trace file generated is " << tr_name << ".tr\n";
+
+ CreateNodes ();
+ CreateDevices (tr_name);
+ SetupMobility ();
+ InstallInternetStack (tr_name);
+ InstallApplications ();
+
+ std::cout << "\nStarting simulation for " << m_totalTime << " s ...\n";
+
+ CheckThroughput ();
+
+ Simulator::Stop (Seconds (m_totalTime));
+ Simulator::Run ();
+ Simulator::Destroy ();
+}
+
+void
+DsdvManetExample::CreateNodes ()
+{
+ std::cout << "Creating " << (unsigned) m_nWifis << " nodes.\n";
+ nodes.Create (m_nWifis);
+ NS_ASSERT_MSG (m_nWifis > m_nSinks, "Sinks must be less or equal to the number of nodes in network");
+}
+
+void
+DsdvManetExample::SetupMobility ()
+{
+ MobilityHelper mobility;
+ ObjectFactory pos;
+ pos.SetTypeId ("ns3::RandomRectanglePositionAllocator");
+ pos.Set ("X", RandomVariableValue (UniformVariable (0, 1000)));
+ pos.Set ("Y", RandomVariableValue (UniformVariable (0, 1000)));
+
+ Ptr <PositionAllocator> taPositionAlloc = pos.Create ()->GetObject <PositionAllocator> ();
+ mobility.SetMobilityModel ("ns3::RandomWaypointMobilityModel", "Speed", RandomVariableValue (ConstantVariable (m_nodeSpeed)),
+ "Pause", RandomVariableValue (ConstantVariable (2.0)), "PositionAllocator", PointerValue (taPositionAlloc));
+ mobility.SetPositionAllocator (taPositionAlloc);
+ mobility.Install (nodes);
+}
+
+void
+DsdvManetExample::CreateDevices (std::string tr_name)
+{
+ NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+ wifiMac.SetType ("ns3::AdhocWifiMac");
+ YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+ YansWifiChannelHelper wifiChannel;
+ wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
+ wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
+ wifiPhy.SetChannel (wifiChannel.Create ());
+ WifiHelper wifi;
+ wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
+ wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue (m_phyMode), "ControlMode",
+ StringValue (m_phyMode));
+ devices = wifi.Install (wifiPhy, wifiMac, nodes);
+
+ AsciiTraceHelper ascii;
+ wifiPhy.EnableAsciiAll (ascii.CreateFileStream (tr_name + ".tr"));
+ wifiPhy.EnablePcapAll (tr_name);
+}
+
+void
+DsdvManetExample::InstallInternetStack (std::string tr_name)
+{
+ DsdvHelper dsdv;
+ dsdv.Set ("PeriodicUpdateInterval", TimeValue (Seconds (m_periodicUpdateInterval)));
+ dsdv.Set ("SettlingTime", TimeValue (Seconds (m_settlingTime)));
+ InternetStackHelper stack;
+ stack.SetRoutingHelper (dsdv);
+ stack.Install (nodes);
+ Ipv4AddressHelper address;
+ address.SetBase ("10.1.1.0", "255.255.255.0");
+ interfaces = address.Assign (devices);
+ if (m_printRoutes)
+ {
+ Ptr<OutputStreamWrapper> routingStream = Create<OutputStreamWrapper> ((tr_name + ".routes"), std::ios::out);
+ dsdv.PrintRoutingTableAllAt (Seconds (m_periodicUpdateInterval), routingStream);
+ }
+}
+
+void
+DsdvManetExample::InstallApplications ()
+{
+ for (uint32_t i = 0; i <= m_nSinks - 1; i++ )
+ {
+ Ptr<Node> node = NodeList::GetNode (i);
+ Ipv4Address nodeAddress = node->GetObject<Ipv4> ()->GetAddress (1, 0).GetLocal ();
+ Ptr<Socket> sink = SetupPacketReceive (nodeAddress, node);
+ }
+
+ for (uint32_t clientNode = 0; clientNode <= m_nWifis - 1; clientNode++ )
+ {
+ for (uint32_t j = 0; j <= m_nSinks - 1; j++ )
+ {
+ OnOffHelper onoff1 ("ns3::UdpSocketFactory", Address (InetSocketAddress (interfaces.GetAddress (j), port)));
+ onoff1.SetAttribute ("OnTime", RandomVariableValue (ConstantVariable (1)));
+ onoff1.SetAttribute ("OffTime", RandomVariableValue (ConstantVariable (0)));
+
+ if (j != clientNode)
+ {
+ ApplicationContainer apps1 = onoff1.Install (nodes.Get (clientNode));
+ UniformVariable var;
+ apps1.Start (Seconds (var.GetValue (m_dataStart, m_dataStart + 1)));
+ apps1.Stop (Seconds (m_totalTime));
+ }
+ }
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/examples/wscript Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,6 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ obj = bld.create_ns3_program('dsdv-manet', ['wifi', 'internet-stack', 'dsdv'])
+ obj.source = 'dsdv-manet.cc'
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/helper/dsdv-helper.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,67 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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
+ *
+ * Authors: Hemanth Narra <hemanth@ittc.ku.com>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "dsdv-helper.h"
+#include "ns3/dsdv-routing-protocol.h"
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+#include "ns3/ipv4-list-routing.h"
+
+namespace ns3 {
+DsdvHelper::~DsdvHelper ()
+{
+}
+
+DsdvHelper::DsdvHelper () : Ipv4RoutingHelper ()
+{
+ m_agentFactory.SetTypeId ("ns3::dsdv::RoutingProtocol");
+}
+
+DsdvHelper*
+DsdvHelper::Copy (void) const
+{
+ return new DsdvHelper (*this);
+}
+
+Ptr<Ipv4RoutingProtocol>
+DsdvHelper::Create (Ptr<Node> node) const
+{
+ Ptr<dsdv::RoutingProtocol> agent = m_agentFactory.Create<dsdv::RoutingProtocol> ();
+ node->AggregateObject (agent);
+ return agent;
+}
+
+void
+DsdvHelper::Set (std::string name, const AttributeValue &value)
+{
+ m_agentFactory.Set (name, value);
+}
+
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/helper/dsdv-helper.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,79 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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
+ *
+ * Authors: Hemanth Narra <hemanth@ittc.ku.com>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef DSDVHELPER_H_
+#define DSDVHELPER_H_
+
+#include "ns3/object-factory.h"
+#include "ns3/node.h"
+#include "ns3/node-container.h"
+#include "ns3/ipv4-routing-helper.h"
+
+namespace ns3 {
+/**
+ * \ingroup dsdv
+ * \brief Helper class that adds DSDV routing to nodes.
+ */
+class DsdvHelper : public Ipv4RoutingHelper
+{
+public:
+ DsdvHelper ();
+ ~DsdvHelper ();
+ /**
+ * \internal
+ * \returns pointer to clone of this DsdvHelper
+ *
+ * This method is mainly for internal use by the other helpers;
+ * clients are expected to free the dynamic memory allocated by this method
+ */
+ DsdvHelper* Copy (void) const;
+
+ /**
+ * \param node the node on which the routing protocol will run
+ * \returns a newly-created routing protocol
+ *
+ * This method will be called by ns3::InternetStackHelper::Install
+ *
+ */
+ virtual Ptr<Ipv4RoutingProtocol> Create (Ptr<Node> node) const;
+ /**
+ * \param name the name of the attribute to set
+ * \param value the value of the attribute to set.
+ *
+ * This method controls the attributes of ns3::dsdv::RoutingProtocol
+ */
+ void Set (std::string name, const AttributeValue &value);
+
+private:
+ ObjectFactory m_agentFactory;
+};
+
+}
+#endif /* DSDVHELPER_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-packet-queue.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,185 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "dsdv-packet-queue.h"
+#include <algorithm>
+#include <functional>
+#include "ns3/ipv4-route.h"
+#include "ns3/socket.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsdvPacketQueue");
+
+namespace ns3 {
+namespace dsdv {
+uint32_t
+PacketQueue::GetSize ()
+{
+ Purge ();
+ return m_queue.size ();
+}
+
+bool
+PacketQueue::Enqueue (QueueEntry & entry)
+{
+ NS_LOG_FUNCTION ("Enqueing packet destined for" << entry.GetIpv4Header ().GetDestination ());
+ Purge ();
+ uint32_t numPacketswithdst;
+ for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
+ != m_queue.end (); ++i)
+ {
+ if ((i->GetPacket ()->GetUid () == entry.GetPacket ()->GetUid ())
+ && (i->GetIpv4Header ().GetDestination ()
+ == entry.GetIpv4Header ().GetDestination ()))
+ {
+ return false;
+ }
+ }
+ numPacketswithdst = GetCountForPacketsWithDst (entry.GetIpv4Header ().GetDestination ());
+ NS_LOG_DEBUG ("Number of packets with this destination: " << numPacketswithdst);
+ /** For Brock Paper comparision*/
+ if (numPacketswithdst >= m_maxLenPerDst || m_queue.size () >= m_maxLen)
+ {
+ NS_LOG_DEBUG ("Max packets reached for this destination. Not queuing any further packets");
+ return false;
+ }
+ else
+ {
+ // NS_LOG_DEBUG("Packet size while enqueing "<<entry.GetPacket()->GetSize());
+ entry.SetExpireTime (m_queueTimeout);
+ m_queue.push_back (entry);
+ return true;
+ }
+}
+
+void
+PacketQueue::DropPacketWithDst (Ipv4Address dst)
+{
+ NS_LOG_FUNCTION ("Dropping packet to " << dst);
+ Purge ();
+ const Ipv4Address addr = dst;
+ for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i
+ != m_queue.end (); ++i)
+ {
+ if (IsEqual (*i, dst))
+ {
+ Drop (*i, "DropPacketWithDst ");
+ }
+ }
+ m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (),
+ std::bind2nd (std::ptr_fun (PacketQueue::IsEqual), dst)), m_queue.end ());
+}
+
+bool
+PacketQueue::Dequeue (Ipv4Address dst, QueueEntry & entry)
+{
+ NS_LOG_FUNCTION ("Dequeueing packet destined for" << dst);
+ Purge ();
+ for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i != m_queue.end (); ++i)
+ {
+ if (i->GetIpv4Header ().GetDestination () == dst)
+ {
+ entry = *i;
+ m_queue.erase (i);
+ return true;
+ }
+ }
+ return false;
+}
+
+bool
+PacketQueue::Find (Ipv4Address dst)
+{
+ for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
+ != m_queue.end (); ++i)
+ {
+ if (i->GetIpv4Header ().GetDestination () == dst)
+ {
+ NS_LOG_DEBUG ("Find");
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t
+PacketQueue::GetCountForPacketsWithDst (Ipv4Address dst)
+{
+ uint32_t count = 0;
+ for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
+ != m_queue.end (); ++i)
+ {
+ if (i->GetIpv4Header ().GetDestination () == dst)
+ {
+ count++;
+ }
+ }
+ return count;
+}
+
+struct IsExpired
+{
+ bool
+ operator() (QueueEntry const & e) const
+ {
+ // NS_LOG_DEBUG("Expire time for packet in req queue: "<<e.GetExpireTime ());
+ return (e.GetExpireTime () < Seconds (0));
+ }
+};
+
+void
+PacketQueue::Purge ()
+{
+ // NS_LOG_DEBUG("Purging Queue");
+ IsExpired pred;
+ for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i
+ != m_queue.end (); ++i)
+ {
+ if (pred (*i))
+ {
+ NS_LOG_DEBUG ("Dropping outdated Packets");
+ Drop (*i, "Drop outdated packet ");
+ }
+ }
+ m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (), pred),
+ m_queue.end ());
+}
+
+void
+PacketQueue::Drop (QueueEntry en, std::string reason)
+{
+ NS_LOG_LOGIC (reason << en.GetPacket ()->GetUid () << " " << en.GetIpv4Header ().GetDestination ());
+ // en.GetErrorCallback () (en.GetPacket (), en.GetIpv4Header (),
+ // Socket::ERROR_NOROUTETOHOST);
+ return;
+}
+
+}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-packet-queue.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef __DSDV_PACKETQUEUE_H__
+#define __DSDV_PACKETQUEUE_H__
+
+#include <vector>
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/simulator.h"
+
+namespace ns3 {
+namespace dsdv {
+/**
+ * \ingroup dsdv
+ * \brief DSDV Queue Entry
+ */
+class QueueEntry
+{
+public:
+ typedef Ipv4RoutingProtocol::UnicastForwardCallback UnicastForwardCallback;
+ typedef Ipv4RoutingProtocol::ErrorCallback ErrorCallback;
+ // / c-tor
+ QueueEntry (Ptr<const Packet> pa = 0, Ipv4Header const & h = Ipv4Header (),
+ UnicastForwardCallback ucb = UnicastForwardCallback (),
+ ErrorCallback ecb = ErrorCallback ())
+ : m_packet (pa),
+ m_header (h),
+ m_ucb (ucb),
+ m_ecb (ecb),
+ m_expire (Seconds (0))
+ {
+ }
+
+ /**
+ * Compare queue entries
+ * \return true if equal
+ */
+ bool operator== (QueueEntry const & o) const
+ {
+ return ((m_packet == o.m_packet) && (m_header.GetDestination () == o.m_header.GetDestination ()) && (m_expire == o.m_expire));
+ }
+ // /\name Fields
+ // \{
+ UnicastForwardCallback GetUnicastForwardCallback () const
+ {
+ return m_ucb;
+ }
+ void SetUnicastForwardCallback (UnicastForwardCallback ucb)
+ {
+ m_ucb = ucb;
+ }
+ ErrorCallback GetErrorCallback () const
+ {
+ return m_ecb;
+ }
+ void SetErrorCallback (ErrorCallback ecb)
+ {
+ m_ecb = ecb;
+ }
+ Ptr<const Packet> GetPacket () const
+ {
+ return m_packet;
+ }
+ void SetPacket (Ptr<const Packet> p)
+ {
+ m_packet = p;
+ }
+ Ipv4Header GetIpv4Header () const
+ {
+ return m_header;
+ }
+ void SetIpv4Header (Ipv4Header h)
+ {
+ m_header = h;
+ }
+ void SetExpireTime (Time exp)
+ {
+ m_expire = exp + Simulator::Now ();
+ }
+ Time GetExpireTime () const
+ {
+ return m_expire - Simulator::Now ();
+ }
+ // \}
+private:
+ // / Data packet
+ Ptr<const Packet> m_packet;
+ // / IP header
+ Ipv4Header m_header;
+ // / Unicast forward callback
+ UnicastForwardCallback m_ucb;
+ // / Error callback
+ ErrorCallback m_ecb;
+ // / Expire time for queue entry
+ Time m_expire;
+};
+/**
+ * \ingroup dsdv
+ * \brief DSDV Packet queue
+ *
+ * When a route is not available, the packets are queued. Every node can buffer up to 5 packets per
+ * destination. We have implemented a "drop front on full" queue where the first queued packet will be dropped
+ * to accommodate newer packets.
+ */
+class PacketQueue
+{
+public:
+ // / Default c-tor
+ PacketQueue ()
+ {
+ }
+ // / Push entry in queue, if there is no entry with the same packet and destination address in queue.
+ bool Enqueue (QueueEntry & entry);
+ // / Return first found (the earliest) entry for given destination
+ bool Dequeue (Ipv4Address dst, QueueEntry & entry);
+ // / Remove all packets with destination IP address dst
+ void DropPacketWithDst (Ipv4Address dst);
+ // / Finds whether a packet with destination dst exists in the queue
+ bool Find (Ipv4Address dst);
+ // / Get count of packets with destination dst in the queue
+ uint32_t
+ GetCountForPacketsWithDst (Ipv4Address dst);
+ // / Number of entries
+ uint32_t GetSize ();
+ // /\name Fields
+ // \{
+ uint32_t GetMaxQueueLen () const
+ {
+ return m_maxLen;
+ }
+ void SetMaxQueueLen (uint32_t len)
+ {
+ m_maxLen = len;
+ }
+ uint32_t GetMaxPacketsPerDst () const
+ {
+ return m_maxLenPerDst;
+ }
+ void SetMaxPacketsPerDst (uint32_t len)
+ {
+ m_maxLenPerDst = len;
+ }
+ Time GetQueueTimeout () const
+ {
+ return m_queueTimeout;
+ }
+ void SetQueueTimeout (Time t)
+ {
+ m_queueTimeout = t;
+ }
+ // \}
+
+private:
+ std::vector<QueueEntry> m_queue;
+ // / Remove all expired entries
+ void Purge ();
+ // / Notify that packet is dropped from queue by timeout
+ void Drop (QueueEntry en, std::string reason);
+ // / The maximum number of packets that we allow a routing protocol to buffer.
+ uint32_t m_maxLen;
+ // / The maximum number of packets that we allow per destination to buffer.
+ uint32_t m_maxLenPerDst;
+ // / The maximum period of time that a routing protocol is allowed to buffer a packet for, seconds.
+ Time m_queueTimeout;
+ static bool IsEqual (QueueEntry en, const Ipv4Address dst)
+ {
+ return (en.GetIpv4Header ().GetDestination () == dst);
+ }
+};
+}
+}
+#endif /* __DSDV_PACKETQUEUE_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-packet.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,101 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "dsdv-packet.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+
+namespace ns3 {
+namespace dsdv {
+NS_OBJECT_ENSURE_REGISTERED (DsdvHeader);
+DsdvHeader::DsdvHeader (Ipv4Address dst, uint32_t hopCount, uint32_t dstSeqNo)
+ : m_dst (dst),
+ m_hopCount (hopCount),
+ m_dstSeqNo (dstSeqNo)
+{
+}
+
+DsdvHeader::~DsdvHeader ()
+{
+}
+
+TypeId
+DsdvHeader::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::dsdv::DsdvHeader")
+ .SetParent<Header> ()
+ .AddConstructor<DsdvHeader> ();
+ return tid;
+}
+
+TypeId
+DsdvHeader::GetInstanceTypeId () const
+{
+ return GetTypeId ();
+}
+
+uint32_t
+DsdvHeader::GetSerializedSize () const
+{
+ return 12;
+}
+
+void
+DsdvHeader::Serialize (Buffer::Iterator i) const
+{
+ WriteTo (i, m_dst);
+ i.WriteHtonU32 (m_hopCount);
+ i.WriteHtonU32 (m_dstSeqNo);
+
+}
+
+uint32_t
+DsdvHeader::Deserialize (Buffer::Iterator start)
+{
+ Buffer::Iterator i = start;
+
+ ReadFrom (i, m_dst);
+ m_hopCount = i.ReadNtohU32 ();
+ m_dstSeqNo = i.ReadNtohU32 ();
+
+ uint32_t dist = i.GetDistanceFrom (start);
+ NS_ASSERT (dist == GetSerializedSize ());
+ return dist;
+}
+
+void
+DsdvHeader::Print (std::ostream &os) const
+{
+ os << "DestinationIpv4: " << m_dst
+ << " Hopcount: " << m_hopCount
+ << " SequenceNumber: " << m_dstSeqNo;
+}
+}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-packet.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,110 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef DSDVPACKET_H_
+#define DSDVPACKET_H_
+
+#include <iostream>
+#include "ns3/header.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/nstime.h"
+
+namespace ns3 {
+namespace dsdv {
+/**
+ * \ingroup dsdv
+ * \brief DSDV Update Packet Format
+ * \verbatim
+ | 0 | 1 | 2 | 3 |
+ 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Destination Address |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | HopCount |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | Sequence Number |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+class DsdvHeader : public Header
+{
+public:
+ DsdvHeader (Ipv4Address dst = Ipv4Address (), uint32_t hopcount = 0, uint32_t dstSeqNo = 0);
+ virtual ~DsdvHeader ();
+ static TypeId GetTypeId (void);
+ virtual TypeId GetInstanceTypeId (void) const;
+ virtual uint32_t GetSerializedSize () const;
+ virtual void Serialize (Buffer::Iterator start) const;
+ virtual uint32_t Deserialize (Buffer::Iterator start);
+ virtual void Print (std::ostream &os) const;
+
+ void
+ SetDst (Ipv4Address destination)
+ {
+ m_dst = destination;
+ }
+ Ipv4Address
+ GetDst () const
+ {
+ return m_dst;
+ }
+ void
+ SetHopCount (uint32_t hopCount)
+ {
+ m_hopCount = hopCount;
+ }
+ uint32_t
+ GetHopCount () const
+ {
+ return m_hopCount;
+ }
+ void
+ SetDstSeqno (uint32_t sequenceNumber)
+ {
+ m_dstSeqNo = sequenceNumber;
+ }
+ uint32_t
+ GetDstSeqno () const
+ {
+ return m_dstSeqNo;
+ }
+private:
+ Ipv4Address m_dst; // /< Destination IP Address
+ uint32_t m_hopCount; // /< Number of Hops
+ uint32_t m_dstSeqNo; // /< Destination Sequence Number
+};
+static inline std::ostream & operator<< (std::ostream& os, const DsdvHeader & packet)
+{
+ packet.Print (os);
+ return os;
+}
+}
+}
+#endif /* DSDVPACKET_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-routing-protocol.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,1180 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra, Yufei Cheng
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ * Author: Yufei Cheng <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+
+#include "dsdv-routing-protocol.h"
+#include "ns3/log.h"
+#include "ns3/random-variable.h"
+#include "ns3/inet-socket-address.h"
+#include "ns3/trace-source-accessor.h"
+#include "ns3/udp-socket-factory.h"
+#include "ns3/wifi-net-device.h"
+#include "ns3/boolean.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsdvRoutingProtocol");
+
+namespace ns3 {
+namespace dsdv {
+NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
+
+// / UDP Port for DSDV control traffic
+const uint32_t RoutingProtocol::DSDV_PORT = 269;
+
+// / Tag used by DSDV implementation
+struct DeferredRouteOutputTag : public Tag
+{
+ // / Positive if output device is fixed in RouteOutput
+ int32_t oif;
+
+ DeferredRouteOutputTag (int32_t o = -1)
+ : Tag (),
+ oif (o)
+ {
+ }
+
+ static TypeId
+ GetTypeId ()
+ {
+ static TypeId tid = TypeId ("ns3::dsdv::DeferredRouteOutputTag").SetParent<Tag> ();
+ return tid;
+ }
+
+ TypeId
+ GetInstanceTypeId () const
+ {
+ return GetTypeId ();
+ }
+
+ uint32_t
+ GetSerializedSize () const
+ {
+ return sizeof(int32_t);
+ }
+
+ void
+ Serialize (TagBuffer i) const
+ {
+ i.WriteU32 (oif);
+ }
+
+ void
+ Deserialize (TagBuffer i)
+ {
+ oif = i.ReadU32 ();
+ }
+
+ void
+ Print (std::ostream &os) const
+ {
+ os << "DeferredRouteOutputTag: output interface = " << oif;
+ }
+};
+
+TypeId
+RoutingProtocol::GetTypeId (void)
+{
+ static TypeId tid = TypeId ("ns3::dsdv::RoutingProtocol")
+ .SetParent<Ipv4RoutingProtocol> ()
+ .AddConstructor<RoutingProtocol> ()
+ .AddAttribute ("PeriodicUpdateInterval","Periodic interval between exchange of full routing tables among nodes. ",
+ TimeValue (Seconds (15)),
+ MakeTimeAccessor (&RoutingProtocol::m_periodicUpdateInterval),
+ MakeTimeChecker ())
+ .AddAttribute ("SettlingTime", "Minimum time an update is to be stored in adv table before sending out"
+ "in case of change in metric (in seconds)",
+ TimeValue (Seconds (5)),
+ MakeTimeAccessor (&RoutingProtocol::m_settlingTime),
+ MakeTimeChecker ())
+ .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a routing protocol to buffer.",
+ UintegerValue (500 /*assuming maximum nodes in simulation is 100*/),
+ MakeUintegerAccessor (&RoutingProtocol::m_maxQueueLen),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("MaxQueuedPacketsPerDst", "Maximum number of packets that we allow per destination to buffer.",
+ UintegerValue (5),
+ MakeUintegerAccessor (&RoutingProtocol::m_maxQueuedPacketsPerDst),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("MaxQueueTime","Maximum time packets can be queued (in seconds)",
+ TimeValue (Seconds (30)),
+ MakeTimeAccessor (&RoutingProtocol::m_maxQueueTime),
+ MakeTimeChecker ())
+ .AddAttribute ("EnableBuffering","Enables buffering of data packets if no route to destination is available",
+ BooleanValue (true),
+ MakeBooleanAccessor (&RoutingProtocol::SetEnableBufferFlag,
+ &RoutingProtocol::GetEnableBufferFlag),
+ MakeBooleanChecker ())
+ .AddAttribute ("EnableWST","Enables Weighted Settling Time for the updates before advertising",
+ BooleanValue (true),
+ MakeBooleanAccessor (&RoutingProtocol::SetWSTFlag,
+ &RoutingProtocol::GetWSTFlag),
+ MakeBooleanChecker ())
+ .AddAttribute ("Holdtimes","Times the forwarding Interval to purge the route.",
+ UintegerValue (3),
+ MakeUintegerAccessor (&RoutingProtocol::Holdtimes),
+ MakeUintegerChecker<uint32_t> ())
+ .AddAttribute ("WeightedFactor","WeightedFactor for the settling time if Weighted Settling Time is enabled",
+ DoubleValue (0.875),
+ MakeDoubleAccessor (&RoutingProtocol::m_weightedFactor),
+ MakeDoubleChecker<double> ())
+ .AddAttribute ("EnableRouteAggregation","Enables Weighted Settling Time for the updates before advertising",
+ BooleanValue (false),
+ MakeBooleanAccessor (&RoutingProtocol::SetEnableRAFlag,
+ &RoutingProtocol::GetEnableRAFlag),
+ MakeBooleanChecker ())
+ .AddAttribute ("RouteAggregationTime","Time to aggregate updates before sending them out (in seconds)",
+ TimeValue (Seconds (1)),
+ MakeTimeAccessor (&RoutingProtocol::m_routeAggregationTime),
+ MakeTimeChecker ());
+ return tid;
+}
+
+void
+RoutingProtocol::SetEnableBufferFlag (bool f)
+{
+ EnableBuffering = f;
+}
+bool
+RoutingProtocol::GetEnableBufferFlag () const
+{
+ return EnableBuffering;
+}
+void
+RoutingProtocol::SetWSTFlag (bool f)
+{
+ EnableWST = f;
+}
+bool
+RoutingProtocol::GetWSTFlag () const
+{
+ return EnableWST;
+}
+void
+RoutingProtocol::SetEnableRAFlag (bool f)
+{
+ EnableRouteAggregation = f;
+}
+bool
+RoutingProtocol::GetEnableRAFlag () const
+{
+ return EnableRouteAggregation;
+}
+
+RoutingProtocol::RoutingProtocol ()
+ : m_routingTable (),
+ m_advRoutingTable (),
+ m_queue (),
+ m_periodicUpdateTimer (Timer::CANCEL_ON_DESTROY)
+{
+}
+
+RoutingProtocol::~RoutingProtocol ()
+{
+}
+
+void
+RoutingProtocol::DoDispose ()
+{
+ m_ipv4 = 0;
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::iterator iter = m_socketAddresses.begin (); iter
+ != m_socketAddresses.end (); iter++)
+ {
+ iter->first->Close ();
+ }
+ m_socketAddresses.clear ();
+ Ipv4RoutingProtocol::DoDispose ();
+}
+
+void
+RoutingProtocol::PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const
+{
+ *stream->GetStream () << "Node: " << m_ipv4->GetObject<Node> ()->GetId () << " Time: " << Simulator::Now ().GetSeconds () << "s ";
+ m_routingTable.Print (stream);
+}
+
+void
+RoutingProtocol::Start ()
+{
+ m_queue.SetMaxPacketsPerDst (m_maxQueuedPacketsPerDst);
+ m_queue.SetMaxQueueLen (m_maxQueueLen);
+ m_queue.SetQueueTimeout (m_maxQueueTime);
+ m_routingTable.Setholddowntime (Scalar (Holdtimes) * m_periodicUpdateInterval);
+ m_advRoutingTable.Setholddowntime (Scalar (Holdtimes) * m_periodicUpdateInterval);
+ m_scb = MakeCallback (&RoutingProtocol::Send,this);
+ m_ecb = MakeCallback (&RoutingProtocol::Drop,this);
+ m_periodicUpdateTimer.SetFunction (&RoutingProtocol::SendPeriodicUpdate,this);
+ m_periodicUpdateTimer.Schedule (MicroSeconds (UniformVariable ().GetInteger (0,1000)));
+}
+
+Ptr<Ipv4Route>
+RoutingProtocol::RouteOutput (Ptr<Packet> p,
+ const Ipv4Header &header,
+ Ptr<NetDevice> oif,
+ Socket::SocketErrno &sockerr)
+{
+ NS_LOG_FUNCTION (this << header << (oif ? oif->GetIfIndex () : 0));
+
+ if (!p)
+ {
+ return LoopbackRoute (header,oif);
+ }
+ if (m_socketAddresses.empty ())
+ {
+ sockerr = Socket::ERROR_NOROUTETOHOST;
+ NS_LOG_LOGIC ("No dsdv interfaces");
+ Ptr<Ipv4Route> route;
+ return route;
+ }
+ std::map<Ipv4Address, RoutingTableEntry> removedAddresses;
+ sockerr = Socket::ERROR_NOTERROR;
+ Ptr<Ipv4Route> route;
+ Ipv4Address dst = header.GetDestination ();
+ NS_LOG_DEBUG ("Packet Size: " << p->GetSize ()
+ << ", Packet id: " << p->GetUid () << ", Destination address in Packet: " << dst);
+ RoutingTableEntry rt;
+ m_routingTable.Purge (removedAddresses);
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator rmItr = removedAddresses.begin ();
+ rmItr != removedAddresses.end (); ++rmItr)
+ {
+ rmItr->second.SetEntriesChanged (true);
+ rmItr->second.SetSeqNo (rmItr->second.GetSeqNo () + 1);
+ m_advRoutingTable.AddRoute (rmItr->second);
+ }
+ if (!removedAddresses.empty ())
+ {
+ Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0,1000)),&RoutingProtocol::SendTriggeredUpdate,this);
+ }
+ if (m_routingTable.LookupRoute (dst,rt))
+ {
+ if (EnableBuffering)
+ {
+ LookForQueuedPackets ();
+ }
+ if (rt.GetHop () == 1)
+ {
+ route = rt.GetRoute ();
+ NS_ASSERT (route != 0);
+ NS_LOG_DEBUG ("A route exists from " << route->GetSource ()
+ << " to neighboring destination "
+ << route->GetDestination ());
+ if (oif != 0 && route->GetOutputDevice () != oif)
+ {
+ NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
+ sockerr = Socket::ERROR_NOROUTETOHOST;
+ return Ptr<Ipv4Route> ();
+ }
+ return route;
+ }
+ else
+ {
+ RoutingTableEntry newrt;
+ if (m_routingTable.LookupRoute (rt.GetNextHop (),newrt))
+ {
+ route = newrt.GetRoute ();
+ NS_ASSERT (route != 0);
+ NS_LOG_DEBUG ("A route exists from " << route->GetSource ()
+ << " to destination " << dst << " via "
+ << rt.GetNextHop ());
+ if (oif != 0 && route->GetOutputDevice () != oif)
+ {
+ NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
+ sockerr = Socket::ERROR_NOROUTETOHOST;
+ return Ptr<Ipv4Route> ();
+ }
+ return route;
+ }
+ }
+ }
+
+ if (EnableBuffering)
+ {
+ uint32_t iif = (oif ? m_ipv4->GetInterfaceForDevice (oif) : -1);
+ DeferredRouteOutputTag tag (iif);
+ if (!p->PeekPacketTag (tag))
+ {
+ p->AddPacketTag (tag);
+ }
+ }
+ return LoopbackRoute (header,oif);
+}
+
+void
+RoutingProtocol::DeferredRouteOutput (Ptr<const Packet> p,
+ const Ipv4Header & header,
+ UnicastForwardCallback ucb,
+ ErrorCallback ecb)
+{
+ NS_LOG_FUNCTION (this << p << header);
+ NS_ASSERT (p != 0 && p != Ptr<Packet> ());
+ QueueEntry newEntry (p,header,ucb,ecb);
+ bool result = m_queue.Enqueue (newEntry);
+ if (result)
+ {
+ NS_LOG_DEBUG ("Added packet " << p->GetUid () << " to queue.");
+ }
+}
+
+bool
+RoutingProtocol::RouteInput (Ptr<const Packet> p,
+ const Ipv4Header &header,
+ Ptr<const NetDevice> idev,
+ UnicastForwardCallback ucb,
+ MulticastForwardCallback mcb,
+ LocalDeliverCallback lcb,
+ ErrorCallback ecb)
+{
+ NS_LOG_FUNCTION (m_mainAddress << " received packet " << p->GetUid ()
+ << " from " << header.GetSource ()
+ << " on interface " << idev->GetAddress ()
+ << " to destination " << header.GetDestination ());
+ if (m_socketAddresses.empty ())
+ {
+ NS_LOG_DEBUG ("No dsdv interfaces");
+ return false;
+ }
+ NS_ASSERT (m_ipv4 != 0);
+ // Check if input device supports IP
+ NS_ASSERT (m_ipv4->GetInterfaceForDevice (idev) >= 0);
+ int32_t iif = m_ipv4->GetInterfaceForDevice (idev);
+
+ Ipv4Address dst = header.GetDestination ();
+ Ipv4Address origin = header.GetSource ();
+
+ // Deferred route request
+ if (EnableBuffering == true && idev == m_lo)
+ {
+ DeferredRouteOutputTag tag;
+ if (p->PeekPacketTag (tag))
+ {
+ DeferredRouteOutput (p,header,ucb,ecb);
+ return true;
+ }
+ }
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j =
+ m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
+ {
+ Ipv4InterfaceAddress iface = j->second;
+ if (origin == iface.GetLocal ())
+ {
+ return true;
+ }
+ }
+ // LOCAL DELIVARY TO DSDV INTERFACES
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j
+ != m_socketAddresses.end (); ++j)
+ {
+ Ipv4InterfaceAddress iface = j->second;
+ if (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()) == iif)
+ {
+ if (dst == iface.GetBroadcast () || dst.IsBroadcast ())
+ {
+ NS_LOG_LOGIC ("Broadcast local delivery to " << iface.GetLocal ());
+ Ptr<Packet> packet = p->Copy ();
+ lcb (p,header,iif);
+ if (header.GetTtl () > 1)
+ {
+ NS_LOG_LOGIC ("Forward broadcast. TTL " << (uint16_t) header.GetTtl ());
+ RoutingTableEntry toBroadcast;
+ if (m_routingTable.LookupRoute (dst,toBroadcast,true))
+ {
+ Ptr<Ipv4Route> route = toBroadcast.GetRoute ();
+ ucb (route,packet,header);
+ }
+ else
+ {
+ NS_LOG_DEBUG ("No route to forward. Drop packet " << p->GetUid ());
+ }
+ }
+ return true;
+ }
+ }
+ }
+
+ if (m_ipv4->IsDestinationAddress (dst, iif))
+ {
+ NS_LOG_LOGIC ("Unicast local delivery to " << dst);
+ lcb (p, header, iif);
+ return true;
+ }
+ RoutingTableEntry toDst;
+ if (m_routingTable.LookupRoute (dst,toDst))
+ {
+ RoutingTableEntry ne;
+ if (m_routingTable.LookupRoute (toDst.GetNextHop (),ne))
+ {
+ Ptr<Ipv4Route> route = ne.GetRoute ();
+ NS_LOG_LOGIC (m_mainAddress << " is forwarding packet " << p->GetUid ()
+ << " to " << dst
+ << " from " << header.GetSource ()
+ << " via nexthop neighbor " << toDst.GetNextHop ());
+ ucb (route,p,header);
+ return true;
+ }
+ }
+ NS_LOG_LOGIC ("Drop packet " << p->GetUid ()
+ << " as there is no route to forward it.");
+ return false;
+}
+
+Ptr<Ipv4Route>
+RoutingProtocol::LoopbackRoute (const Ipv4Header & hdr, Ptr<NetDevice> oif) const
+{
+ NS_ASSERT (m_lo != 0);
+ Ptr<Ipv4Route> rt = Create<Ipv4Route> ();
+ rt->SetDestination (hdr.GetDestination ());
+ // rt->SetSource (hdr.GetSource ());
+ //
+ // Source address selection here is tricky. The loopback route is
+ // returned when DSDV does not have a route; this causes the packet
+ // to be looped back and handled (cached) in RouteInput() method
+ // while a route is found. However, connection-oriented protocols
+ // like TCP need to create an endpoint four-tuple (src, src port,
+ // dst, dst port) and create a pseudo-header for checksumming. So,
+ // DSDV needs to guess correctly what the eventual source address
+ // will be.
+ //
+ // For single interface, single address nodes, this is not a problem.
+ // When there are possibly multiple outgoing interfaces, the policy
+ // implemented here is to pick the first available DSDV interface.
+ // If RouteOutput() caller specified an outgoing interface, that
+ // further constrains the selection of source address
+ //
+ std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin ();
+ if (oif)
+ {
+ // Iterate to find an address on the oif device
+ for (j = m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
+ {
+ Ipv4Address addr = j->second.GetLocal ();
+ int32_t interface = m_ipv4->GetInterfaceForAddress (addr);
+ if (oif == m_ipv4->GetNetDevice (static_cast<uint32_t> (interface)))
+ {
+ rt->SetSource (addr);
+ break;
+ }
+ }
+ }
+ else
+ {
+ rt->SetSource (j->second.GetLocal ());
+ }
+ NS_ASSERT_MSG (rt->GetSource () != Ipv4Address (), "Valid DSDV source address not found");
+ rt->SetGateway (Ipv4Address ("127.0.0.1"));
+ rt->SetOutputDevice (m_lo);
+ return rt;
+}
+
+void
+RoutingProtocol::RecvDsdv (Ptr<Socket> socket)
+{
+ Address sourceAddress;
+ Ptr<Packet> advpacket = Create<Packet> ();
+ Ptr<Packet> packet = socket->RecvFrom (sourceAddress);
+ InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
+ Ipv4Address sender = inetSourceAddr.GetIpv4 ();
+ Ipv4Address receiver = m_socketAddresses[socket].GetLocal ();
+ Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+ uint32_t packetSize = packet->GetSize ();
+ NS_LOG_FUNCTION (m_mainAddress << " received dsdv packet of size: " << packetSize
+ << " and packet id: " << packet->GetUid ());
+ uint32_t count = 0;
+ for (; packetSize > 0; packetSize = packetSize - 12)
+ {
+ count = 0;
+ DsdvHeader dsdvHeader, tempDsdvHeader;
+ packet->RemoveHeader (dsdvHeader);
+ NS_LOG_DEBUG ("Processing new update for " << dsdvHeader.GetDst ());
+ /*Verifying if the packets sent by me were returned back to me. If yes, discarding them!*/
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j
+ != m_socketAddresses.end (); ++j)
+ {
+ Ipv4InterfaceAddress interface = j->second;
+ if (dsdvHeader.GetDst () == interface.GetLocal ())
+ {
+ if (dsdvHeader.GetDstSeqno () % 2 == 1)
+ {
+ NS_LOG_DEBUG ("Sent Dsdv update back to the same Destination, "
+ "with infinite metric. Time left to send fwd update: "
+ << m_periodicUpdateTimer.GetDelayLeft ());
+ count++;
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Received update for my address. Discarding this.");
+ count++;
+ }
+ }
+ }
+ if (count > 0)
+ {
+ continue;
+ }
+ NS_LOG_DEBUG ("Received a DSDV packet from "
+ << sender << " to " << receiver << ". Details are: Destination: " << dsdvHeader.GetDst () << ", Seq No: "
+ << dsdvHeader.GetDstSeqno () << ", HopCount: " << dsdvHeader.GetHopCount ());
+ RoutingTableEntry fwdTableEntry, advTableEntry;
+ EventId event;
+ bool permanentTableVerifier = m_routingTable.LookupRoute (dsdvHeader.GetDst (),fwdTableEntry);
+ if (permanentTableVerifier == false)
+ {
+ if (dsdvHeader.GetDstSeqno () % 2 != 1)
+ {
+ NS_LOG_DEBUG ("Received New Route!");
+ RoutingTableEntry newEntry (
+ /*device=*/ dev, /*dst=*/
+ dsdvHeader.GetDst (), /*seqno=*/
+ dsdvHeader.GetDstSeqno (),
+ /*iface=*/ m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
+ /*hops=*/ dsdvHeader.GetHopCount (), /*next hop=*/
+ sender, /*lifetime=*/
+ Simulator::Now (), /*settlingTime*/
+ m_settlingTime, /*entries changed*/
+ true);
+ newEntry.SetFlag (VALID);
+ m_routingTable.AddRoute (newEntry);
+ NS_LOG_DEBUG ("New Route added to both tables");
+ m_advRoutingTable.AddRoute (newEntry);
+ }
+ else
+ {
+ // received update not present in main routing table and also with infinite metric
+ NS_LOG_DEBUG ("Discarding this update as this route is not present in "
+ "main routing table and received with infinite metric");
+ }
+ }
+ else
+ {
+ if (!m_advRoutingTable.LookupRoute (dsdvHeader.GetDst (),advTableEntry))
+ {
+ RoutingTableEntry tr;
+ std::map<Ipv4Address, RoutingTableEntry> allRoutes;
+ m_advRoutingTable.GetListOfAllRoutes (allRoutes);
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i)
+ {
+ NS_LOG_DEBUG ("ADV table routes are:" << i->second.GetDestination ());
+ }
+ // present in fwd table and not in advtable
+ m_advRoutingTable.AddRoute (fwdTableEntry);
+ m_advRoutingTable.LookupRoute (dsdvHeader.GetDst (),advTableEntry);
+ }
+ if (dsdvHeader.GetDstSeqno () % 2 != 1)
+ {
+ if (dsdvHeader.GetDstSeqno () > advTableEntry.GetSeqNo ())
+ {
+ // Received update with better seq number. Clear any old events that are running
+ if (m_advRoutingTable.ForceDeleteIpv4Event (dsdvHeader.GetDst ()))
+ {
+ NS_LOG_DEBUG ("Canceling the timer to update route with better seq number");
+ }
+ // if its a changed metric *nomatter* where the update came from, wait for WST
+ if (dsdvHeader.GetHopCount () != advTableEntry.GetHop ())
+ {
+ advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ());
+ advTableEntry.SetLifeTime (Simulator::Now ());
+ advTableEntry.SetFlag (VALID);
+ advTableEntry.SetEntriesChanged (true);
+ advTableEntry.SetNextHop (sender);
+ advTableEntry.SetHop (dsdvHeader.GetHopCount ());
+ NS_LOG_DEBUG ("Received update with better sequence number and changed metric.Waiting for WST");
+ Time tempSettlingtime = GetSettlingTime (dsdvHeader.GetDst ());
+ advTableEntry.SetSettlingTime (tempSettlingtime);
+ NS_LOG_DEBUG ("Added Settling Time:" << tempSettlingtime.GetSeconds ()
+ << "s as there is no event running for this route");
+ event = Simulator::Schedule (tempSettlingtime,&RoutingProtocol::SendTriggeredUpdate,this);
+ m_advRoutingTable.AddIpv4Event (dsdvHeader.GetDst (),event);
+ NS_LOG_DEBUG ("EventCreated EventUID: " << event.GetUid ());
+ // if received changed metric, use it but adv it only after wst
+ m_routingTable.Update (advTableEntry);
+ m_advRoutingTable.Update (advTableEntry);
+ }
+ else
+ {
+ // Received update with better seq number and same metric.
+ advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ());
+ advTableEntry.SetLifeTime (Simulator::Now ());
+ advTableEntry.SetFlag (VALID);
+ advTableEntry.SetEntriesChanged (true);
+ advTableEntry.SetNextHop (sender);
+ advTableEntry.SetHop (dsdvHeader.GetHopCount ());
+ m_advRoutingTable.Update (advTableEntry);
+ NS_LOG_DEBUG ("Route with better sequence number and same metric received. Advertised without WST");
+ }
+ }
+ else if (dsdvHeader.GetDstSeqno () == advTableEntry.GetSeqNo ())
+ {
+ if (dsdvHeader.GetHopCount () < advTableEntry.GetHop ())
+ {
+ /*Received update with same seq number and better hop count.
+ * As the metric is changed, we will have to wait for WST before sending out this update.
+ */
+ NS_LOG_DEBUG ("Canceling any existing timer to update route with same sequence number "
+ "and better hop count");
+ m_advRoutingTable.ForceDeleteIpv4Event (dsdvHeader.GetDst ());
+ advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ());
+ advTableEntry.SetLifeTime (Simulator::Now ());
+ advTableEntry.SetFlag (VALID);
+ advTableEntry.SetEntriesChanged (true);
+ advTableEntry.SetNextHop (sender);
+ advTableEntry.SetHop (dsdvHeader.GetHopCount ());
+ Time tempSettlingtime = GetSettlingTime (dsdvHeader.GetDst ());
+ advTableEntry.SetSettlingTime (tempSettlingtime);
+ NS_LOG_DEBUG ("Added Settling Time," << tempSettlingtime.GetSeconds ()
+ << " as there is no current event running for this route");
+ event = Simulator::Schedule (tempSettlingtime,&RoutingProtocol::SendTriggeredUpdate,this);
+ m_advRoutingTable.AddIpv4Event (dsdvHeader.GetDst (),event);
+ NS_LOG_DEBUG ("EventCreated EventUID: " << event.GetUid ());
+ // if received changed metric, use it but adv it only after wst
+ m_routingTable.Update (advTableEntry);
+ m_advRoutingTable.Update (advTableEntry);
+ }
+ else
+ {
+ /*Received update with same seq number but with same or greater hop count.
+ * Discard that update.
+ */
+ if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetDst ()))
+ {
+ /*update the timer only if nexthop address matches thus discarding
+ * updates to that destination from other nodes.
+ */
+ if (advTableEntry.GetNextHop () == sender)
+ {
+ advTableEntry.SetLifeTime (Simulator::Now ());
+ m_routingTable.Update (advTableEntry);
+ }
+ m_advRoutingTable.DeleteRoute (
+ dsdvHeader.GetDst ());
+ }
+ NS_LOG_DEBUG ("Received update with same seq number and "
+ "same/worst metric for, " << dsdvHeader.GetDst () << ". Discarding the update.");
+ }
+ }
+ else
+ {
+ // Received update with an old sequence number. Discard the update
+ if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetDst ()))
+ {
+ m_advRoutingTable.DeleteRoute (dsdvHeader.GetDst ());
+ }
+ NS_LOG_DEBUG (dsdvHeader.GetDst () << " : Received update with old seq number. Discarding the update.");
+ }
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Route with infinite metric received for "
+ << dsdvHeader.GetDst () << " from " << sender);
+ // Delete route only if update was received from my nexthop neighbor
+ if (sender == advTableEntry.GetNextHop ())
+ {
+ NS_LOG_DEBUG ("Triggering an update for this unreachable route:");
+ std::map<Ipv4Address, RoutingTableEntry> dstsWithNextHopSrc;
+ m_routingTable.GetListOfDestinationWithNextHop (dsdvHeader.GetDst (),dstsWithNextHopSrc);
+ m_routingTable.DeleteRoute (dsdvHeader.GetDst ());
+ advTableEntry.SetSeqNo (dsdvHeader.GetDstSeqno ());
+ advTableEntry.SetEntriesChanged (true);
+ m_advRoutingTable.Update (advTableEntry);
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = dstsWithNextHopSrc.begin (); i
+ != dstsWithNextHopSrc.end (); ++i)
+ {
+ i->second.SetSeqNo (i->second.GetSeqNo () + 1);
+ i->second.SetEntriesChanged (true);
+ m_advRoutingTable.AddRoute (i->second);
+ m_routingTable.DeleteRoute (i->second.GetDestination ());
+ }
+ }
+ else
+ {
+ if (not m_advRoutingTable.AnyRunningEvent (dsdvHeader.GetDst ()))
+ {
+ m_advRoutingTable.DeleteRoute (dsdvHeader.GetDst ());
+ }
+ NS_LOG_DEBUG (dsdvHeader.GetDst () <<
+ " : Discard this link break update as it was received from a different neighbor "
+ "and I can reach the destination");
+ }
+ }
+ }
+ }
+ std::map<Ipv4Address, RoutingTableEntry> allRoutes;
+ m_advRoutingTable.GetListOfAllRoutes (allRoutes);
+ if (EnableRouteAggregation && allRoutes.size () > 0)
+ {
+ Simulator::Schedule (m_routeAggregationTime,&RoutingProtocol::SendTriggeredUpdate,this);
+ }
+ else
+ {
+ Simulator::Schedule (MicroSeconds (UniformVariable ().GetInteger (0,1000)),&RoutingProtocol::SendTriggeredUpdate,this);
+ }
+}
+
+
+void
+RoutingProtocol::SendTriggeredUpdate ()
+{
+ NS_LOG_FUNCTION (m_mainAddress << " is sending a triggered update");
+ std::map<Ipv4Address, RoutingTableEntry> allRoutes;
+ m_advRoutingTable.GetListOfAllRoutes (allRoutes);
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j
+ != m_socketAddresses.end (); ++j)
+ {
+ DsdvHeader dsdvHeader;
+ Ptr<Socket> socket = j->first;
+ Ipv4InterfaceAddress iface = j->second;
+ Ptr<Packet> packet = Create<Packet> ();
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i)
+ {
+ NS_LOG_LOGIC ("Destination: " << i->second.GetDestination ()
+ << " SeqNo:" << i->second.GetSeqNo () << " HopCount:"
+ << i->second.GetHop () + 1);
+ RoutingTableEntry temp = i->second;
+ if ((i->second.GetEntriesChanged () == true) && (not m_advRoutingTable.AnyRunningEvent (temp.GetDestination ())))
+ {
+ dsdvHeader.SetDst (i->second.GetDestination ());
+ dsdvHeader.SetDstSeqno (i->second.GetSeqNo ());
+ dsdvHeader.SetHopCount (i->second.GetHop () + 1);
+ temp.SetFlag (VALID);
+ temp.SetEntriesChanged (false);
+ m_advRoutingTable.DeleteIpv4Event (temp.GetDestination ());
+ if (!(temp.GetSeqNo () % 2))
+ {
+ m_routingTable.Update (temp);
+ }
+ packet->AddHeader (dsdvHeader);
+ m_advRoutingTable.DeleteRoute (temp.GetDestination ());
+ NS_LOG_DEBUG ("Deleted this route from the advertised table");
+ }
+ else
+ {
+ EventId event = m_advRoutingTable.GetEventId (temp.GetDestination ());
+ NS_ASSERT (event.GetUid () != 0);
+ NS_LOG_DEBUG ("EventID " << event.GetUid () << " associated with "
+ << temp.GetDestination () << " has not expired, waiting in adv table");
+ }
+ }
+ if (packet->GetSize () >= 12)
+ {
+ RoutingTableEntry temp2;
+ m_routingTable.LookupRoute (m_ipv4->GetAddress (1, 0).GetBroadcast (), temp2);
+ dsdvHeader.SetDst (m_ipv4->GetAddress (1, 0).GetLocal ());
+ dsdvHeader.SetDstSeqno (temp2.GetSeqNo ());
+ dsdvHeader.SetHopCount (temp2.GetHop () + 1);
+ NS_LOG_DEBUG ("Adding my update as well to the packet");
+ packet->AddHeader (dsdvHeader);
+ // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
+ Ipv4Address destination;
+ if (iface.GetMask () == Ipv4Mask::GetOnes ())
+ {
+ destination = Ipv4Address ("255.255.255.255");
+ }
+ else
+ {
+ destination = iface.GetBroadcast ();
+ }
+ socket->SendTo (packet, 0, InetSocketAddress (destination, DSDV_PORT));
+ NS_LOG_FUNCTION ("Sent Triggered Update from "
+ << dsdvHeader.GetDst ()
+ << " with packet id : " << packet->GetUid () << " and packet Size: " << packet->GetSize ());
+ }
+ else
+ {
+ NS_LOG_FUNCTION ("Update not sent as there are no updates to be triggered");
+ }
+ }
+}
+
+void
+RoutingProtocol::SendPeriodicUpdate ()
+{
+ std::map<Ipv4Address, RoutingTableEntry> removedAddresses, allRoutes;
+ m_routingTable.Purge (removedAddresses);
+ MergeTriggerPeriodicUpdates ();
+ m_routingTable.GetListOfAllRoutes (allRoutes);
+ if (allRoutes.size () < 0)
+ {
+ return;
+ }
+ NS_LOG_FUNCTION (m_mainAddress << " is sending out its periodic update");
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j
+ != m_socketAddresses.end (); ++j)
+ {
+ Ptr<Socket> socket = j->first;
+ Ipv4InterfaceAddress iface = j->second;
+ Ptr<Packet> packet = Create<Packet> ();
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i)
+ {
+ DsdvHeader dsdvHeader;
+ if (i->second.GetHop () == 0)
+ {
+ RoutingTableEntry ownEntry;
+ dsdvHeader.SetDst (m_ipv4->GetAddress (1,0).GetLocal ());
+ dsdvHeader.SetDstSeqno (i->second.GetSeqNo () + 2);
+ dsdvHeader.SetHopCount (i->second.GetHop () + 1);
+ m_routingTable.LookupRoute (m_ipv4->GetAddress (1,0).GetBroadcast (),ownEntry);
+ ownEntry.SetSeqNo (dsdvHeader.GetDstSeqno ());
+ m_routingTable.Update (ownEntry);
+ packet->AddHeader (dsdvHeader);
+ }
+ else
+ {
+ dsdvHeader.SetDst (i->second.GetDestination ());
+ dsdvHeader.SetDstSeqno ((i->second.GetSeqNo ()));
+ dsdvHeader.SetHopCount (i->second.GetHop () + 1);
+ packet->AddHeader (dsdvHeader);
+ }
+ NS_LOG_DEBUG ("Forwarding the update for " << i->first);
+ NS_LOG_DEBUG ("Forwarding details are, Destination: " << dsdvHeader.GetDst ()
+ << ", SeqNo:" << dsdvHeader.GetDstSeqno ()
+ << ", HopCount:" << dsdvHeader.GetHopCount ()
+ << ", LifeTime: " << i->second.GetLifeTime ().GetSeconds ());
+ }
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator rmItr = removedAddresses.begin (); rmItr
+ != removedAddresses.end (); ++rmItr)
+ {
+ DsdvHeader removedHeader;
+ removedHeader.SetDst (rmItr->second.GetDestination ());
+ removedHeader.SetDstSeqno (rmItr->second.GetSeqNo () + 1);
+ removedHeader.SetHopCount (rmItr->second.GetHop () + 1);
+ packet->AddHeader (removedHeader);
+ NS_LOG_DEBUG ("Update for removed record is: Destination: " << removedHeader.GetDst ()
+ << " SeqNo:" << removedHeader.GetDstSeqno ()
+ << " HopCount:" << removedHeader.GetHopCount ());
+ }
+ socket->Send (packet);
+ // Send to all-hosts broadcast if on /32 addr, subnet-directed otherwise
+ Ipv4Address destination;
+ if (iface.GetMask () == Ipv4Mask::GetOnes ())
+ {
+ destination = Ipv4Address ("255.255.255.255");
+ }
+ else
+ {
+ destination = iface.GetBroadcast ();
+ }
+ socket->SendTo (packet, 0, InetSocketAddress (destination, DSDV_PORT));
+ NS_LOG_FUNCTION ("PeriodicUpdate Packet UID is : " << packet->GetUid ());
+ }
+ m_periodicUpdateTimer.Schedule (m_periodicUpdateInterval + MicroSeconds (25 * UniformVariable ().GetInteger (0,1000)));
+}
+
+void
+RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4)
+{
+ NS_ASSERT (ipv4 != 0);
+ NS_ASSERT (m_ipv4 == 0);
+ m_ipv4 = ipv4;
+ // Create lo route. It is asserted that the only one interface up for now is loopback
+ NS_ASSERT (m_ipv4->GetNInterfaces () == 1 && m_ipv4->GetAddress (0, 0).GetLocal () == Ipv4Address ("127.0.0.1"));
+ m_lo = m_ipv4->GetNetDevice (0);
+ NS_ASSERT (m_lo != 0);
+ // Remember lo route
+ RoutingTableEntry rt (
+ /*device=*/ m_lo, /*dst=*/
+ Ipv4Address::GetLoopback (), /*seqno=*/
+ 0,
+ /*iface=*/ Ipv4InterfaceAddress (Ipv4Address::GetLoopback (),Ipv4Mask ("255.0.0.0")),
+ /*hops=*/ 0, /*next hop=*/
+ Ipv4Address::GetLoopback (),
+ /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
+ rt.SetFlag (INVALID);
+ rt.SetEntriesChanged (false);
+ m_routingTable.AddRoute (rt);
+ Simulator::ScheduleNow (&RoutingProtocol::Start,this);
+}
+
+void
+RoutingProtocol::NotifyInterfaceUp (uint32_t i)
+{
+ NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ()
+ << " interface is up");
+ Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+ Ipv4InterfaceAddress iface = l3->GetAddress (i,0);
+ if (iface.GetLocal () == Ipv4Address ("127.0.0.1"))
+ {
+ return;
+ }
+ // Create a socket to listen only on this interface
+ Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());
+ NS_ASSERT (socket != 0);
+ socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this));
+ socket->BindToNetDevice (l3->GetNetDevice (i));
+ socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
+ socket->SetAllowBroadcast (true);
+ socket->SetAttribute ("IpTtl",UintegerValue (1));
+ m_socketAddresses.insert (std::make_pair (socket,iface));
+ // Add local broadcast record to the routing table
+ Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()));
+ RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (), /*seqno=*/ 0,/*iface=*/ iface,/*hops=*/ 0,
+ /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
+ m_routingTable.AddRoute (rt);
+ if (m_mainAddress == Ipv4Address ())
+ {
+ m_mainAddress = iface.GetLocal ();
+ }
+ NS_ASSERT (m_mainAddress != Ipv4Address ());
+}
+
+void
+RoutingProtocol::NotifyInterfaceDown (uint32_t i)
+{
+ Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+ Ptr<NetDevice> dev = l3->GetNetDevice (i);
+ Ptr<Socket> socket = FindSocketWithInterfaceAddress (m_ipv4->GetAddress (i,0));
+ NS_ASSERT (socket);
+ socket->Close ();
+ m_socketAddresses.erase (socket);
+ if (m_socketAddresses.empty ())
+ {
+ NS_LOG_LOGIC ("No dsdv interfaces");
+ m_routingTable.Clear ();
+ return;
+ }
+ m_routingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i,0));
+ m_advRoutingTable.DeleteAllRoutesFromInterface (m_ipv4->GetAddress (i,0));
+}
+
+void
+RoutingProtocol::NotifyAddAddress (uint32_t i,
+ Ipv4InterfaceAddress address)
+{
+ NS_LOG_FUNCTION (this << " interface " << i << " address " << address);
+ Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+ if (!l3->IsUp (i))
+ {
+ return;
+ }
+ Ipv4InterfaceAddress iface = l3->GetAddress (i,0);
+ Ptr<Socket> socket = FindSocketWithInterfaceAddress (iface);
+ if (!socket)
+ {
+ if (iface.GetLocal () == Ipv4Address ("127.0.0.1"))
+ {
+ return;
+ }
+ Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());
+ NS_ASSERT (socket != 0);
+ socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this));
+ socket->BindToNetDevice (l3->GetNetDevice (i));
+ // Bind to any IP address so that broadcasts can be received
+ socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
+ socket->SetAllowBroadcast (true);
+ m_socketAddresses.insert (std::make_pair (socket,iface));
+ Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (iface.GetLocal ()));
+ RoutingTableEntry rt (/*device=*/ dev, /*dst=*/ iface.GetBroadcast (),/*seqno=*/ 0, /*iface=*/ iface,/*hops=*/ 0,
+ /*next hop=*/ iface.GetBroadcast (), /*lifetime=*/ Simulator::GetMaximumSimulationTime ());
+ m_routingTable.AddRoute (rt);
+ }
+}
+
+void
+RoutingProtocol::NotifyRemoveAddress (uint32_t i,
+ Ipv4InterfaceAddress address)
+{
+ Ptr<Socket> socket = FindSocketWithInterfaceAddress (address);
+ if (socket)
+ {
+ m_socketAddresses.erase (socket);
+ Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+ if (l3->GetNAddresses (i))
+ {
+ Ipv4InterfaceAddress iface = l3->GetAddress (i,0);
+ // Create a socket to listen only on this interface
+ Ptr<Socket> socket = Socket::CreateSocket (GetObject<Node> (),UdpSocketFactory::GetTypeId ());
+ NS_ASSERT (socket != 0);
+ socket->SetRecvCallback (MakeCallback (&RoutingProtocol::RecvDsdv,this));
+ // Bind to any IP address so that broadcasts can be received
+ socket->Bind (InetSocketAddress (Ipv4Address::GetAny (), DSDV_PORT));
+ socket->SetAllowBroadcast (true);
+ m_socketAddresses.insert (std::make_pair (socket,iface));
+ }
+ }
+}
+
+Ptr<Socket>
+RoutingProtocol::FindSocketWithInterfaceAddress (Ipv4InterfaceAddress addr) const
+{
+ for (std::map<Ptr<Socket>, Ipv4InterfaceAddress>::const_iterator j = m_socketAddresses.begin (); j
+ != m_socketAddresses.end (); ++j)
+ {
+ Ptr<Socket> socket = j->first;
+ Ipv4InterfaceAddress iface = j->second;
+ if (iface == addr)
+ {
+ return socket;
+ }
+ }
+ Ptr<Socket> socket;
+ return socket;
+}
+
+void
+RoutingProtocol::Send (Ptr<Ipv4Route> route,
+ Ptr<const Packet> packet,
+ const Ipv4Header & header)
+{
+ Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+ NS_ASSERT (l3 != 0);
+ Ptr<Packet> p = packet->Copy ();
+ l3->Send (p,route->GetSource (),header.GetDestination (),header.GetProtocol (),route);
+}
+
+void
+RoutingProtocol::Drop (Ptr<const Packet> packet,
+ const Ipv4Header & header,
+ Socket::SocketErrno err)
+{
+ NS_LOG_DEBUG (m_mainAddress << " drop packet " << packet->GetUid () << " to "
+ << header.GetDestination () << " from queue. Error " << err);
+}
+
+void
+RoutingProtocol::LookForQueuedPackets ()
+{
+ NS_LOG_FUNCTION (this);
+ Ptr<Ipv4Route> route;
+ std::map<Ipv4Address, RoutingTableEntry> allRoutes;
+ m_routingTable.GetListOfAllRoutes (allRoutes);
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i)
+ {
+ RoutingTableEntry rt;
+ rt = i->second;
+ if (m_queue.Find (rt.GetDestination ()))
+ {
+ if (rt.GetHop () == 1)
+ {
+ route = rt.GetRoute ();
+ NS_LOG_LOGIC ("A route exists from " << route->GetSource ()
+ << " to neighboring destination "
+ << route->GetDestination ());
+ NS_ASSERT (route != 0);
+ }
+ else
+ {
+ RoutingTableEntry newrt;
+ m_routingTable.LookupRoute (rt.GetNextHop (),newrt);
+ route = newrt.GetRoute ();
+ NS_LOG_LOGIC ("A route exists from " << route->GetSource ()
+ << " to destination " << route->GetDestination () << " via "
+ << rt.GetNextHop ());
+ NS_ASSERT (route != 0);
+ }
+ SendPacketFromQueue (rt.GetDestination (),route);
+ }
+ }
+}
+
+void
+RoutingProtocol::SendPacketFromQueue (Ipv4Address dst,
+ Ptr<Ipv4Route> route)
+{
+ NS_LOG_DEBUG (m_mainAddress << " is sending a queued packet to destination " << dst);
+ QueueEntry queueEntry;
+ if (m_queue.Dequeue (dst,queueEntry))
+ {
+ DeferredRouteOutputTag tag;
+ Ptr<Packet> p = ConstCast<Packet> (queueEntry.GetPacket ());
+ if (p->RemovePacketTag (tag))
+ {
+ if (tag.oif != -1 && tag.oif != m_ipv4->GetInterfaceForDevice (route->GetOutputDevice ()))
+ {
+ NS_LOG_DEBUG ("Output device doesn't match. Dropped.");
+ return;
+ }
+ }
+ UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback ();
+ Ipv4Header header = queueEntry.GetIpv4Header ();
+ header.SetSource (route->GetSource ());
+ header.SetTtl (header.GetTtl () + 1); // compensate extra TTL decrement by fake loopback routing
+ ucb (route,p,header);
+ if (m_queue.GetSize () != 0 && m_queue.Find (dst))
+ {
+ Simulator::Schedule (MilliSeconds (UniformVariable ().GetInteger (0,100)),
+ &RoutingProtocol::SendPacketFromQueue,this,dst,route);
+ }
+ }
+}
+
+Time
+RoutingProtocol::GetSettlingTime (Ipv4Address address)
+{
+ NS_LOG_FUNCTION ("Calculating the settling time for " << address);
+ RoutingTableEntry mainrt;
+ Time weightedTime;
+ m_routingTable.LookupRoute (address,mainrt);
+ if (EnableWST)
+ {
+ if (mainrt.GetSettlingTime () == Seconds (0))
+ {
+ return Seconds (0);
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Route SettlingTime: " << mainrt.GetSettlingTime ().GetSeconds ()
+ << " and LifeTime:" << mainrt.GetLifeTime ().GetSeconds ());
+ weightedTime = (Scalar (m_weightedFactor) * mainrt.GetSettlingTime ()) + (Scalar (1.0 - m_weightedFactor)
+ * mainrt.GetLifeTime ());
+ NS_LOG_DEBUG ("Calculated weightedTime:" << weightedTime.GetSeconds ());
+ return weightedTime;
+ }
+ }
+ return mainrt.GetSettlingTime ();
+}
+
+void
+RoutingProtocol::MergeTriggerPeriodicUpdates ()
+{
+ NS_LOG_FUNCTION ("Merging advertised table changes with main table before sending out periodic update");
+ std::map<Ipv4Address, RoutingTableEntry> allRoutes;
+ m_advRoutingTable.GetListOfAllRoutes (allRoutes);
+ if (allRoutes.size () > 0)
+ {
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = allRoutes.begin (); i != allRoutes.end (); ++i)
+ {
+ RoutingTableEntry advEntry = i->second;
+ if ((advEntry.GetEntriesChanged () == true) && (not m_advRoutingTable.AnyRunningEvent (advEntry.GetDestination ())))
+ {
+ if (!(advEntry.GetSeqNo () % 2))
+ {
+ advEntry.SetFlag (VALID);
+ advEntry.SetEntriesChanged (false);
+ m_routingTable.Update (advEntry);
+ NS_LOG_DEBUG ("Merged update for " << advEntry.GetDestination () << " with main routing Table");
+ }
+ m_advRoutingTable.DeleteRoute (advEntry.GetDestination ());
+ }
+ else
+ {
+ NS_LOG_DEBUG ("Event currently running. Cannot Merge Routing Tables");
+ }
+ }
+ }
+}
+}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-routing-protocol.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,195 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra, Yufei Cheng
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ * Author: Yufei Cheng <yfcheng@ittc.ku.edu>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef DSDVROUTINGPROTOCOL_H_
+#define DSDVROUTINGPROTOCOL_H_
+
+#include "dsdv-rtable.h"
+#include "dsdv-packet-queue.h"
+#include "dsdv-packet.h"
+#include "ns3/node.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include "ns3/output-stream-wrapper.h"
+
+namespace ns3 {
+namespace dsdv {
+
+/**
+ * \ingroup dsdv
+ * \brief DSDV routing protocol.
+ */
+class RoutingProtocol : public Ipv4RoutingProtocol
+{
+public:
+ static TypeId
+ GetTypeId (void);
+ static const uint32_t DSDV_PORT;
+
+ // / c-tor
+ RoutingProtocol ();
+ virtual
+ ~RoutingProtocol ();
+ virtual void
+ DoDispose ();
+
+ // /\name From Ipv4RoutingProtocol
+ // \{
+ Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, Ptr<NetDevice> oif, Socket::SocketErrno &sockerr);
+ bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev, UnicastForwardCallback ucb,
+ MulticastForwardCallback mcb, LocalDeliverCallback lcb, ErrorCallback ecb);
+ virtual void PrintRoutingTable (Ptr<OutputStreamWrapper> stream) const;
+ virtual void NotifyInterfaceUp (uint32_t interface);
+ virtual void NotifyInterfaceDown (uint32_t interface);
+ virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
+ virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
+ virtual void SetIpv4 (Ptr<Ipv4> ipv4);
+ // \}
+ // /\name Methods to handle protocol parameters
+ // \{
+ void SetEnableBufferFlag (bool f);
+ bool GetEnableBufferFlag () const;
+ void SetWSTFlag (bool f);
+ bool GetWSTFlag () const;
+ void SetEnableRAFlag (bool f);
+ bool GetEnableRAFlag () const;
+ // \}
+
+private:
+ // /\name Protocol parameters.
+ // \{
+ // / \{Holdtimes is the multiplicative factor of PeriodicUpdateInterval for which the node waits since the last update
+ // / before flushing a route from the routing table. If PeriodicUpdateInterval is 8s and Holdtimes is 3, the node
+ // / waits for 24s since the last update to flush this route from its routing table. \}
+ uint32_t Holdtimes;
+ // / \{PeriodicUpdateInterval specifies the periodic time interval between which the a node broadcasts
+ // / its entire routing table.\}
+ Time m_periodicUpdateInterval;
+ // /\{ SettlingTime specifies the time for which a node waits before propagating an update.
+ // / It waits for this time interval in hope of receiving an update with a better metric.
+ // /\}
+ Time m_settlingTime;
+ // /Nodes IP address
+ Ipv4Address m_mainAddress;
+ // / IP protocol
+ Ptr<Ipv4> m_ipv4;
+ // / Raw socket per each IP interface, map socket -> iface address (IP + mask)
+ std::map<Ptr<Socket>, Ipv4InterfaceAddress> m_socketAddresses;
+ // / Loopback device used to defer route requests until a route is found
+ Ptr<NetDevice> m_lo;
+ // / Main Routing table for the node
+ RoutingTable m_routingTable;
+ // / Advertised Routing table for the node
+ RoutingTable m_advRoutingTable;
+ // / The maximum number of packets that we allow a routing protocol to buffer.
+ uint32_t m_maxQueueLen;
+ // / The maximum number of packets that we allow per destination to buffer.
+ uint32_t m_maxQueuedPacketsPerDst;
+ // /< The maximum period of time that a routing protocol is allowed to buffer a packet for.
+ Time m_maxQueueTime;
+ // / A "drop front on full" queue used by the routing layer to buffer packets to which it does not have a route.
+ PacketQueue m_queue;
+ // / Flag that is used to enable or disable buffering
+ bool EnableBuffering;
+ // / Flag that is used to enable or disable Weighted Settling Time
+ bool EnableWST;
+ // / This is the wighted factor to determine the weighted settling time
+ double m_weightedFactor;
+ // / This is a flag to enable route aggregation. Route aggregation will aggregate all routes for
+ // / 'RouteAggregationTime' from the time an update is received by a node and sends them as a single update .
+ bool EnableRouteAggregation;
+ // / Parameter that holds the route aggregation time interval
+ Time m_routeAggregationTime;
+ // / Unicast callback for own packets
+ UnicastForwardCallback m_scb;
+ // / Error callback for own packets
+ ErrorCallback m_ecb;
+ // /\}
+
+private:
+ // / Start protocol operation
+ void
+ Start ();
+ // / Queue packet untill we find a route
+ void
+ DeferredRouteOutput (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb);
+ // / Look for any queued packets to send them out
+ void
+ LookForQueuedPackets (void);
+ /**
+ * Send packet from queue
+ * \param dst - destination address to which we are sending the packet to
+ * \param route - route identified for this packet
+ */
+ void
+ SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route);
+ // / Find socket with local interface address iface
+ Ptr<Socket>
+ FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const;
+ // /\name Receive dsdv control packets
+ // \{
+ // / Receive and process dsdv control packet
+ void
+ RecvDsdv (Ptr<Socket> socket);
+ // \}
+ void
+ Send (Ptr<Ipv4Route>, Ptr<const Packet>, const Ipv4Header &);
+ // / Create loopback route for given header
+ Ptr<Ipv4Route>
+ LoopbackRoute (const Ipv4Header & header, Ptr<NetDevice> oif) const;
+ /**
+ * Get settlingTime for a destination
+ * \param dst - destination address
+ * \return settlingTime for the destination if found
+ */
+ Time
+ GetSettlingTime (Ipv4Address dst);
+ // / Sends trigger update from a node
+ void
+ SendTriggeredUpdate ();
+ // / Broadcasts the entire routing table for every PeriodicUpdateInterval
+ void
+ SendPeriodicUpdate ();
+ void
+ MergeTriggerPeriodicUpdates ();
+ // / Notify that packet is dropped for some reason
+ void
+ Drop (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno);
+ // / Timer to trigger periodic updates from a node
+ Timer m_periodicUpdateTimer;
+ // / Timer used by the trigger updates in case of Weighted Settling Time is used
+ Timer m_triggeredExpireTimer;
+};
+
+}
+}
+#endif /* DSDVROUTINGPROTOCOL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-rtable.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,350 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "dsdv-rtable.h"
+#include "ns3/simulator.h"
+#include <iomanip>
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("DsdvRoutingTable");
+
+namespace ns3 {
+namespace dsdv {
+RoutingTableEntry::RoutingTableEntry (Ptr<NetDevice> dev,
+ Ipv4Address dst,
+ u_int32_t seqNo,
+ Ipv4InterfaceAddress iface,
+ u_int32_t hops,
+ Ipv4Address nextHop,
+ Time lifetime,
+ Time SettlingTime,
+ bool areChanged)
+ : m_seqNo (seqNo),
+ m_hops (hops),
+ m_lifeTime (lifetime),
+ m_iface (iface),
+ m_flag (VALID),
+ m_settlingTime (SettlingTime),
+ m_entriesChanged (areChanged)
+{
+ m_ipv4Route = Create<Ipv4Route> ();
+ m_ipv4Route->SetDestination (dst);
+ m_ipv4Route->SetGateway (nextHop);
+ m_ipv4Route->SetSource (m_iface.GetLocal ());
+ m_ipv4Route->SetOutputDevice (dev);
+}
+RoutingTableEntry::~RoutingTableEntry ()
+{
+}
+RoutingTable::RoutingTable ()
+{
+}
+
+bool
+RoutingTable::LookupRoute (Ipv4Address id,
+ RoutingTableEntry & rt)
+{
+ if (m_ipv4AddressEntry.empty ())
+ {
+ return false;
+ }
+ std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.find (id);
+ if (i == m_ipv4AddressEntry.end ())
+ {
+ return false;
+ }
+ rt = i->second;
+ return true;
+}
+
+bool
+RoutingTable::LookupRoute (Ipv4Address id,
+ RoutingTableEntry & rt,
+ bool forRouteInput)
+{
+ if (m_ipv4AddressEntry.empty ())
+ {
+ return false;
+ }
+ std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.find (id);
+ if (i == m_ipv4AddressEntry.end ())
+ {
+ return false;
+ }
+ if (forRouteInput == true && id == i->second.GetInterface ().GetBroadcast ())
+ {
+ return false;
+ }
+ rt = i->second;
+ return true;
+}
+
+bool
+RoutingTable::DeleteRoute (Ipv4Address dst)
+{
+ if (m_ipv4AddressEntry.erase (dst) != 0)
+ {
+ // NS_LOG_DEBUG("Route erased");
+ return true;
+ }
+ return false;
+}
+
+uint32_t
+RoutingTable::RoutingTableSize ()
+{
+ return m_ipv4AddressEntry.size ();
+}
+
+bool
+RoutingTable::AddRoute (RoutingTableEntry & rt)
+{
+ std::pair<std::map<Ipv4Address, RoutingTableEntry>::iterator, bool> result = m_ipv4AddressEntry.insert (std::make_pair (
+ rt.GetDestination (),rt));
+ return result.second;
+}
+
+bool
+RoutingTable::Update (RoutingTableEntry & rt)
+{
+ std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.find (rt.GetDestination ());
+ if (i == m_ipv4AddressEntry.end ())
+ {
+ return false;
+ }
+ i->second = rt;
+ return true;
+}
+
+void
+RoutingTable::DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface)
+{
+ if (m_ipv4AddressEntry.empty ())
+ {
+ return;
+ }
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); )
+ {
+ if (i->second.GetInterface () == iface)
+ {
+ std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
+ ++i;
+ m_ipv4AddressEntry.erase (tmp);
+ }
+ else
+ {
+ ++i;
+ }
+ }
+}
+
+void
+RoutingTable::GetListOfAllRoutes (std::map<Ipv4Address, RoutingTableEntry> & allRoutes)
+{
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
+ {
+ if (i->second.GetDestination () != Ipv4Address ("127.0.0.1") && i->second.GetFlag () == VALID)
+ {
+ allRoutes.insert (
+ std::make_pair (i->first,i->second));
+ }
+ }
+}
+
+void
+RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop,
+ std::map<Ipv4Address, RoutingTableEntry> & unreachable)
+{
+ unreachable.clear ();
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.begin (); i
+ != m_ipv4AddressEntry.end (); ++i)
+ {
+ if (i->second.GetNextHop () == nextHop)
+ {
+ unreachable.insert (std::make_pair (i->first,i->second));
+ }
+ }
+}
+
+void
+RoutingTableEntry::Print (Ptr<OutputStreamWrapper> stream) const
+{
+ *stream->GetStream () << std::setiosflags (std::ios::fixed) << m_ipv4Route->GetDestination () << "\t\t" << m_ipv4Route->GetGateway () << "\t\t"
+ << m_iface.GetLocal () << "\t\t" << std::setiosflags (std::ios::left)
+ << std::setw (10) << m_hops << "\t" << std::setw (10) << m_seqNo << "\t"
+ << std::setprecision (3) << (Simulator::Now () - m_lifeTime).GetSeconds ()
+ << "s\t\t" << m_settlingTime.GetSeconds () << "s\n";
+}
+
+void
+RoutingTable::Purge (std::map<Ipv4Address, RoutingTableEntry> & removedAddresses)
+{
+ if (m_ipv4AddressEntry.empty ())
+ {
+ return;
+ }
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator i = m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); )
+ {
+ std::map<Ipv4Address, RoutingTableEntry>::iterator itmp = i;
+ if (i->second.GetLifeTime () > m_holddownTime && (i->second.GetHop () > 0))
+ {
+ for (std::map<Ipv4Address, RoutingTableEntry>::iterator j = m_ipv4AddressEntry.begin (); j != m_ipv4AddressEntry.end (); )
+ {
+ if ((j->second.GetNextHop () == i->second.GetDestination ()) && (i->second.GetHop () != j->second.GetHop ()))
+ {
+ std::map<Ipv4Address, RoutingTableEntry>::iterator jtmp = j;
+ removedAddresses.insert (std::make_pair (j->first,j->second));
+ ++j;
+ m_ipv4AddressEntry.erase (jtmp);
+ }
+ else
+ {
+ ++j;
+ }
+ }
+ removedAddresses.insert (std::make_pair (i->first,i->second));
+ ++i;
+ m_ipv4AddressEntry.erase (itmp);
+ }
+ // TODO: Need to decide when to invalidate a route
+ /* else if (i->second.GetLifeTime() > m_holddownTime)
+ {
+ ++i;
+ itmp->second.SetFlag(INVALID);
+ }*/
+ else
+ {
+ ++i;
+ }
+ }
+ return;
+}
+
+void
+RoutingTable::Print (Ptr<OutputStreamWrapper> stream) const
+{
+ *stream->GetStream () << "\nDSDV Routing table\n" << "Destination\t\tGateway\t\tInterface\t\tHopCount\t\tSeqNum\t\tLifeTime\t\tSettlingTime\n";
+ for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i = m_ipv4AddressEntry.begin (); i
+ != m_ipv4AddressEntry.end (); ++i)
+ {
+ i->second.Print (stream);
+ }
+ *stream->GetStream () << "\n";
+}
+
+bool
+RoutingTable::AddIpv4Event (Ipv4Address address,
+ EventId id)
+{
+ std::pair<std::map<Ipv4Address, EventId>::iterator, bool> result = m_ipv4Events.insert (std::make_pair (address,id));
+ return result.second;
+}
+
+bool
+RoutingTable::AnyRunningEvent (Ipv4Address address)
+{
+ EventId event;
+ std::map<Ipv4Address, EventId>::const_iterator i = m_ipv4Events.find (address);
+ if (m_ipv4Events.empty ())
+ {
+ return false;
+ }
+ if (i == m_ipv4Events.end ())
+ {
+ return false;
+ }
+ event = i->second;
+ if (event.IsRunning ())
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+bool
+RoutingTable::ForceDeleteIpv4Event (Ipv4Address address)
+{
+ EventId event;
+ std::map<Ipv4Address, EventId>::const_iterator i = m_ipv4Events.find (address);
+ if (m_ipv4Events.empty () || i == m_ipv4Events.end ())
+ {
+ return false;
+ }
+ event = i->second;
+ Simulator::Cancel (event);
+ m_ipv4Events.erase (address);
+ return true;
+}
+
+bool
+RoutingTable::DeleteIpv4Event (Ipv4Address address)
+{
+ EventId event;
+ std::map<Ipv4Address, EventId>::const_iterator i = m_ipv4Events.find (address);
+ if (m_ipv4Events.empty () || i == m_ipv4Events.end ())
+ {
+ return false;
+ }
+ event = i->second;
+ if (event.IsRunning ())
+ {
+ return false;
+ }
+ if (event.IsExpired ())
+ {
+ event.Cancel ();
+ m_ipv4Events.erase (address);
+ return true;
+ }
+ else
+ {
+ m_ipv4Events.erase (address);
+ return true;
+ }
+}
+
+EventId
+RoutingTable::GetEventId (Ipv4Address address)
+{
+ std::map <Ipv4Address, EventId>::const_iterator i = m_ipv4Events.find (address);
+ if (m_ipv4Events.empty () || i == m_ipv4Events.end ())
+ {
+ return EventId ();
+ }
+ else
+ {
+ return i->second;
+ }
+}
+}
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/model/dsdv-rtable.h Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,348 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#ifndef __DSDV_RTABLE_H__
+#define __DSDV_RTABLE_H__
+
+#include <cassert>
+#include <map>
+#include <sys/types.h>
+#include "ns3/ipv4.h"
+#include "ns3/ipv4-route.h"
+#include "ns3/timer.h"
+#include "ns3/net-device.h"
+#include "ns3/output-stream-wrapper.h"
+
+namespace ns3 {
+namespace dsdv {
+enum RouteFlags
+{
+ VALID = 0, // !< VALID
+ INVALID = 1, // !< INVALID
+};
+
+/**
+ * \ingroup dsdv
+ * \brief Routing table entry
+ */
+class RoutingTableEntry
+{
+public:
+ // / c-tor
+ RoutingTableEntry (Ptr<NetDevice> dev = 0, Ipv4Address dst = Ipv4Address (), u_int32_t m_seqNo = 0,
+ Ipv4InterfaceAddress iface = Ipv4InterfaceAddress (), u_int32_t hops = 0, Ipv4Address nextHop = Ipv4Address (),
+ Time lifetime = Simulator::Now (), Time SettlingTime = Simulator::Now (), bool changedEntries = false);
+
+ ~RoutingTableEntry ();
+ Ipv4Address
+ GetDestination () const
+ {
+ return m_ipv4Route->GetDestination ();
+ }
+ Ptr<Ipv4Route>
+ GetRoute () const
+ {
+ return m_ipv4Route;
+ }
+ void
+ SetRoute (Ptr<Ipv4Route> route)
+ {
+ m_ipv4Route = route;
+ }
+ void
+ SetNextHop (Ipv4Address nextHop)
+ {
+ m_ipv4Route->SetGateway (nextHop);
+ }
+ Ipv4Address
+ GetNextHop () const
+ {
+ return m_ipv4Route->GetGateway ();
+ }
+ void
+ SetOutputDevice (Ptr<NetDevice> device)
+ {
+ m_ipv4Route->SetOutputDevice (device);
+ }
+ Ptr<NetDevice>
+ GetOutputDevice () const
+ {
+ return m_ipv4Route->GetOutputDevice ();
+ }
+ Ipv4InterfaceAddress
+ GetInterface () const
+ {
+ return m_iface;
+ }
+ void
+ SetInterface (Ipv4InterfaceAddress iface)
+ {
+ m_iface = iface;
+ }
+ void
+ SetSeqNo (uint32_t sequenceNumber)
+ {
+ m_seqNo = sequenceNumber;
+ }
+ uint32_t
+ GetSeqNo () const
+ {
+ return m_seqNo;
+ }
+ void
+ SetHop (uint32_t hopCount)
+ {
+ m_hops = hopCount;
+ }
+ uint32_t
+ GetHop () const
+ {
+ return m_hops;
+ }
+ void
+ SetLifeTime (Time lifeTime)
+ {
+ m_lifeTime = lifeTime;
+ }
+ Time
+ GetLifeTime () const
+ {
+ return (Simulator::Now () - m_lifeTime);
+ }
+ void
+ SetSettlingTime (Time settlingTime)
+ {
+ m_settlingTime = settlingTime;
+ }
+ Time
+ GetSettlingTime () const
+ {
+ return (m_settlingTime);
+ }
+ void
+ SetFlag (RouteFlags flag)
+ {
+ m_flag = flag;
+ }
+ RouteFlags
+ GetFlag () const
+ {
+ return m_flag;
+ }
+ void
+ SetEntriesChanged (bool entriesChanged)
+ {
+ m_entriesChanged = entriesChanged;
+ }
+ bool
+ GetEntriesChanged () const
+ {
+ return m_entriesChanged;
+ }
+ /**
+ * \brief Compare destination address
+ * \return true if equal
+ */
+ bool
+ operator== (Ipv4Address const destination) const
+ {
+ return (m_ipv4Route->GetDestination () == destination);
+ }
+ void
+ Print (Ptr<OutputStreamWrapper> stream) const;
+
+private:
+ // /\name Fields
+ // \{
+ // / Destination Sequence Number
+ uint32_t m_seqNo;
+ // / Hop Count (number of hops needed to reach destination)
+ uint32_t m_hops;
+ /**
+ * \brief Expiration or deletion time of the route
+ * Lifetime field in the routing table plays dual role --
+ * for an active route it is the expiration time, and for an invalid route
+ * it is the deletion time.
+ */
+ Time m_lifeTime;
+ /** Ip route, include
+ * - destination address
+ * - source address
+ * - next hop address (gateway)
+ * - output device
+ */
+ Ptr<Ipv4Route> m_ipv4Route;
+ // / Output interface address
+ Ipv4InterfaceAddress m_iface;
+ // / Routing flags: valid, invalid or in search
+ RouteFlags m_flag;
+ // / Time for which the node retains an update with changed metric before broadcasting it.
+ // / A node does that in hope of receiving a better update.
+ Time m_settlingTime;
+ // / Flag to show if any of the routing table entries were changed with the routing update.
+ uint32_t m_entriesChanged;
+ // \}
+};
+
+/**
+ * \ingroup dsdv
+ * \brief The Routing table used by DSDV protocol
+ */
+class RoutingTable
+{
+public:
+ // / c-tor
+ RoutingTable ();
+ /**
+ * Add routing table entry if it doesn't yet exist in routing table
+ * \param r routing table entry
+ * \return true in success
+ */
+ bool
+ AddRoute (RoutingTableEntry & r);
+ /**
+ * Delete routing table entry with destination address dst, if it exists.
+ * \param dst destination address
+ * \return true on success
+ */
+ bool
+ DeleteRoute (Ipv4Address dst);
+ /**
+ * Lookup routing table entry with destination address dst
+ * \param dst destination address
+ * \param rt entry with destination address dst, if exists
+ * \return true on success
+ */
+ bool
+ LookupRoute (Ipv4Address dst, RoutingTableEntry & rt);
+ bool
+ LookupRoute (Ipv4Address id, RoutingTableEntry & rt, bool forRouteInput);
+ /**
+ * Updating the routing Table with routing table entry rt
+ * \param routing table entry rt
+ * \return true on success
+ */
+ bool
+ Update (RoutingTableEntry & rt);
+ /**
+ * Lookup list of addresses for which nxtHp is the next Hop address
+ * \param nexthop's address for which we want the list of destinations
+ * \param dstList is the list that will hold all these destination addresses
+ */
+ void
+ GetListOfDestinationWithNextHop (Ipv4Address nxtHp, std::map<Ipv4Address, RoutingTableEntry> & dstList);
+ /**
+ * Lookup list of all addresses in the routing table
+ * \param allRoutes is the list that will hold all these addresses present in the nodes routing table
+ */
+ void
+ GetListOfAllRoutes (std::map<Ipv4Address, RoutingTableEntry> & allRoutes);
+ // / Delete all route from interface with address iface
+ void
+ DeleteAllRoutesFromInterface (Ipv4InterfaceAddress iface);
+ // / Delete all entries from routing table
+ void
+ Clear ()
+ {
+ m_ipv4AddressEntry.clear ();
+ }
+ // / Delete all outdated entries if Lifetime is expired
+ void
+ Purge (std::map<Ipv4Address, RoutingTableEntry> & removedAddresses);
+ // / Print routing table
+ void
+ Print (Ptr<OutputStreamWrapper> stream) const;
+ // / Provides the number of routes present in that nodes routing table.
+ uint32_t
+ RoutingTableSize ();
+ /**
+ * Add an event for a destination address so that the update to for that destination is sent
+ * after the event is completed.
+ * \param destination address for which this event is running.
+ * \param unique eventid that was generated.
+ */
+ bool
+ AddIpv4Event (Ipv4Address, EventId);
+ /**
+ * Clear up the entry from the map after the event is completed
+ * \param destination address for which this event is running.
+ * \return true on success
+ */
+ bool
+ DeleteIpv4Event (Ipv4Address address);
+ /**
+ * Force delete an update waiting for settling time to complete as a better update to
+ * same destination was received.
+ * \param destination address for which this event is running.
+ * \return true on success
+ */
+ bool
+ AnyRunningEvent (Ipv4Address address);
+ /**
+ * Force delete an update waiting for settling time to complete as a better update to
+ * same destination was received.
+ * \param destination address for which this event is running.
+ * \return true on finding out that an event is already running for that destination address.
+ */
+ bool
+ ForceDeleteIpv4Event (Ipv4Address address);
+ /**
+ * Get the EcentId associated with that address.
+ * \param destination address for which this event is running.
+ * \return EventId on finding out an event is associated else return NULL.
+ */
+ EventId
+ GetEventId (Ipv4Address address);
+ // /\name Handle life time of invalid route
+ // \{
+ Time Getholddowntime () const
+ {
+ return m_holddownTime;
+ }
+ void Setholddowntime (Time t)
+ {
+ m_holddownTime = t;
+ }
+ // \}
+
+private:
+ // /\name Fields
+ // \{
+ // / an entry in the routing table.
+ std::map<Ipv4Address, RoutingTableEntry> m_ipv4AddressEntry;
+ // / an entry in the event table.
+ std::map<Ipv4Address, EventId> m_ipv4Events;
+ // /
+ Time m_holddownTime;
+ // \}
+};
+}
+}
+#endif /*__DSDV_RTABLE_H__ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/test/dsdv-testcase.cc Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,199 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2010 Hemanth Narra
+ *
+ * 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: Hemanth Narra <hemanth@ittc.ku.com>
+ *
+ * James P.G. Sterbenz <jpgs@ittc.ku.edu>, director
+ * ResiliNets Research Group http://wiki.ittc.ku.edu/resilinets
+ * Information and Telecommunication Technology Center (ITTC)
+ * and Department of Electrical Engineering and Computer Science
+ * The University of Kansas Lawrence, KS USA.
+ *
+ * Work supported in part by NSF FIND (Future Internet Design) Program
+ * under grant CNS-0626918 (Postmodern Internet Architecture),
+ * NSF grant CNS-1050226 (Multilayer Network Resilience Analysis and Experimentation on GENI),
+ * US Department of Defense (DoD), and ITTC at The University of Kansas.
+ */
+#include "ns3/test.h"
+#include "ns3/mesh-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/nqos-wifi-mac-helper.h"
+#include "ns3/dsdv-helper.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/v4ping-helper.h"
+#include "ns3/string.h"
+#include "ns3/boolean.h"
+#include "ns3/yans-wifi-helper.h"
+#include "ns3/pcap-file.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/dsdv-packet.h"
+#include "ns3/dsdv-rtable.h"
+
+namespace ns3 {
+class DsdvHeaderTestCase : public TestCase
+{
+public:
+ DsdvHeaderTestCase ();
+ ~DsdvHeaderTestCase ();
+ virtual bool
+ DoRun (void);
+};
+DsdvHeaderTestCase::DsdvHeaderTestCase ()
+ : TestCase ("Verifying the DSDV header")
+{
+}
+DsdvHeaderTestCase::~DsdvHeaderTestCase ()
+{
+}
+bool
+DsdvHeaderTestCase::DoRun ()
+{
+ Ptr<Packet> packet = Create<Packet> ();
+
+ {
+ dsdv::DsdvHeader hdr1;
+ hdr1.SetDst (Ipv4Address ("10.1.1.2"));
+ hdr1.SetDstSeqno (2);
+ hdr1.SetHopCount (2);
+ packet->AddHeader (hdr1);
+ dsdv::DsdvHeader hdr2;
+ hdr2.SetDst (Ipv4Address ("10.1.1.3"));
+ hdr2.SetDstSeqno (4);
+ hdr2.SetHopCount (1);
+ packet->AddHeader (hdr2);
+ NS_TEST_ASSERT_MSG_EQ (packet->GetSize (), 24, "XXX");
+ }
+
+ {
+ dsdv::DsdvHeader hdr2;
+ packet->RemoveHeader (hdr2);
+ NS_TEST_ASSERT_MSG_EQ (hdr2.GetSerializedSize (),12,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr2.GetDst (),Ipv4Address ("10.1.1.3"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr2.GetDstSeqno (),4,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr2.GetHopCount (),1,"XXX");
+ dsdv::DsdvHeader hdr1;
+ packet->RemoveHeader (hdr1);
+ NS_TEST_ASSERT_MSG_EQ (hdr1.GetSerializedSize (),12,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr1.GetDst (),Ipv4Address ("10.1.1.2"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr1.GetDstSeqno (),2,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (hdr1.GetHopCount (),2,"XXX");
+ }
+
+ return GetErrorStatus ();
+}
+
+class DsdvTableTestCase : public TestCase
+{
+public:
+ DsdvTableTestCase ();
+ ~DsdvTableTestCase ();
+ virtual bool
+ DoRun (void);
+};
+
+DsdvTableTestCase::DsdvTableTestCase ()
+ : TestCase ("Dsdv Routing Table test case")
+{
+}
+DsdvTableTestCase::~DsdvTableTestCase ()
+{
+}
+bool
+DsdvTableTestCase::DoRun ()
+{
+ dsdv::RoutingTable rtable;
+ Ptr<NetDevice> dev;
+ {
+ dsdv::RoutingTableEntry rEntry1 (
+ /*device=*/ dev, /*dst=*/
+ Ipv4Address ("10.1.1.4"), /*seqno=*/ 2,
+ /*iface=*/ Ipv4InterfaceAddress (Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")),
+ /*hops=*/ 2, /*next hop=*/
+ Ipv4Address ("10.1.1.2"),
+ /*lifetime=*/ Seconds (10));
+ NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rEntry1),true,"add route");
+ dsdv::RoutingTableEntry rEntry2 (
+ /*device=*/ dev, /*dst=*/
+ Ipv4Address ("10.1.1.2"), /*seqno=*/ 4,
+ /*iface=*/ Ipv4InterfaceAddress (Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")),
+ /*hops=*/ 1, /*next hop=*/
+ Ipv4Address ("10.1.1.2"),
+ /*lifetime=*/ Seconds (10));
+ NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rEntry2),true,"add route");
+ dsdv::RoutingTableEntry rEntry3 (
+ /*device=*/ dev, /*dst=*/
+ Ipv4Address ("10.1.1.3"), /*seqno=*/ 4,
+ /*iface=*/ Ipv4InterfaceAddress (Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")),
+ /*hops=*/ 1, /*next hop=*/
+ Ipv4Address ("10.1.1.3"),
+ /*lifetime=*/ Seconds (10));
+ NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rEntry3),true,"add route");
+ dsdv::RoutingTableEntry rEntry4 (
+ /*device=*/ dev, /*dst=*/
+ Ipv4Address ("10.1.1.255"), /*seqno=*/ 0,
+ /*iface=*/ Ipv4InterfaceAddress (Ipv4Address ("10.1.1.1"), Ipv4Mask ("255.255.255.0")),
+ /*hops=*/ 0, /*next hop=*/
+ Ipv4Address ("10.1.1.255"),
+ /*lifetime=*/ Seconds (10));
+ NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rEntry4),true,"add route");
+ }
+ {
+ dsdv::RoutingTableEntry rEntry;
+ if (rtable.LookupRoute (Ipv4Address ("10.1.1.4"), rEntry))
+ {
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetDestination (),Ipv4Address ("10.1.1.4"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetSeqNo (),2,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetHop (),2,"XXX");
+ }
+ if (rtable.LookupRoute (Ipv4Address ("10.1.1.2"), rEntry))
+ {
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetDestination (),Ipv4Address ("10.1.1.2"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetSeqNo (),4,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetHop (),1,"XXX");
+ }
+ if (rtable.LookupRoute (Ipv4Address ("10.1.1.3"), rEntry))
+ {
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetDestination (),Ipv4Address ("10.1.1.3"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetSeqNo (),4,"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetHop (),1,"XXX");
+ }
+ if (rtable.LookupRoute (Ipv4Address ("10.1.1.255"), rEntry))
+ {
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetDestination (),Ipv4Address ("10.1.1.255"),"XXX");
+ }
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetInterface ().GetLocal (),Ipv4Address ("10.1.1.1"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rEntry.GetInterface ().GetBroadcast (),Ipv4Address ("10.1.1.255"),"XXX");
+ NS_TEST_ASSERT_MSG_EQ (rtable.RoutingTableSize (),4,"Rtable size incorrect");
+ }
+ Simulator::Destroy ();
+ return GetErrorStatus ();
+}
+
+class DsdvTestSuite : public TestSuite
+{
+public:
+ DsdvTestSuite () : TestSuite ("routing-dsdv", UNIT)
+ {
+ AddTestCase (new DsdvHeaderTestCase ());
+ AddTestCase (new DsdvTableTestCase ());
+ }
+} g_dsdvTestSuite;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/dsdv/wscript Tue Dec 21 22:43:06 2010 -0800
@@ -0,0 +1,25 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+ module = bld.create_ns3_module('dsdv', ['internet-stack', 'contrib', 'wifi'])
+ module.includes = '.'
+ module.source = [
+ 'model/dsdv-rtable.cc',
+ 'model/dsdv-packet-queue.cc',
+ 'model/dsdv-packet.cc',
+ 'model/dsdv-routing-protocol.cc',
+ 'helper/dsdv-helper.cc',
+ 'test/dsdv-testcase.cc',
+ ]
+
+ headers = bld.new_task_gen('ns3header')
+ headers.module = 'dsdv'
+ headers.source = [
+ 'model/dsdv-rtable.h',
+ 'model/dsdv-packet-queue.h',
+ 'model/dsdv-packet.h',
+ 'model/dsdv-routing-protocol.h',
+ 'helper/dsdv-helper.h',
+ ]
+ if (bld.env['ENABLE_EXAMPLES']):
+ bld.add_subdirs('examples')
--- a/src/wscript Tue Dec 21 21:57:50 2010 -0800
+++ b/src/wscript Tue Dec 21 22:43:06 2010 -0800
@@ -40,6 +40,7 @@
'routing/static-routing',
'routing/list-routing',
'routing/aodv',
+ 'routing/dsdv',
'mobility',
'devices/wifi',
'helper',