Merge.
authorSebastien Vincent <sebastien.vincent@turnserver.org>
Tue, 24 Nov 2009 20:38:21 +0100
changeset 5811 99638575fedc
parent 5806 032bee420987 (current diff)
parent 5810 6afb0f719e53 (diff)
child 5812 bb8a3a22d015
Merge.
src/internet-stack/wscript
--- a/AUTHORS	Tue Nov 24 20:37:29 2009 +0100
+++ b/AUTHORS	Tue Nov 24 20:38:21 2009 +0100
@@ -6,6 +6,7 @@
 Raj Bhattacharjea (raj.b@gatech.edu)
 Timo Bingmann (timo.bingmann@student.kit.edu)
 Pavel Boyko (boyko@iitp.ru)
+Elena Buchatskaia (borovkovaes@iitp.ru)
 Gustavo Carneiro (gjc@inescporto.pt, gjcarneiro@gmail.com)
 Angelos Chatzipapas (chatzipa@ceid.upatras.gr)
 Luis Cortes (cortes@gatech.edu)
--- a/CHANGES.html	Tue Nov 24 20:37:29 2009 +0100
+++ b/CHANGES.html	Tue Nov 24 20:38:21 2009 +0100
@@ -56,9 +56,15 @@
 'context' (a 32bit integer which, by convention identifies a node by its id). Simulator::GetContext
 returns the context of the currently-executing event while Simulator::ScheduleWithContext creates an
 event with a context different from the execution context of the caller. This API is used
-by the ns-3 logging system to report the execution context of each log line.
+by the ns-3 logging system to report the execution context of each log line.</li>
+
 <li><b>Object::DoStart</b>: Users who need to complete their object setup at the start of a simulation
-can override this virtual method, perform their adhoc setup, and then, must chain up to their parent.
+can override this virtual method, perform their adhoc setup, and then, must chain up to their parent.</li>
+
+<li><b>Aod hoc On-Demand Distance Vector (AODV)</b> routing model, 
+<a href=http://www.ietf.org/rfc/rfc3561.txt>RFC 3561</a> </li>
+
+<li><b>IPv6 extension support</b></li>
 </ul>
 
 <h2>Changes to existing API:</h2>
@@ -122,6 +128,9 @@
 Simulator::SetScheduler (sched);
 </pre>
 
+<li> Extensions to IPv4 <b>Ping</b> application: verbose output and the ability to configure different ping 
+sizes and time intervals (via new attributes)</li>
+
 </ul>
 
 <h2>Changed behavior:</h2>
--- a/RELEASE_NOTES	Tue Nov 24 20:37:29 2009 +0100
+++ b/RELEASE_NOTES	Tue Nov 24 20:38:21 2009 +0100
@@ -31,10 +31,14 @@
 New user-visible features
 -------------------------
 
-  * The ns-3 logging macros (NS_LOG_*) now report automatically the node id
-    of the event which called the macro.
+  a) The ns-3 logging macros (NS_LOG_*) now report automatically the node id
+     of the event which called the macro.
 
-API changes from ns-3.5
+  b) Ad hoc On-Demand Distance Vector (AODV) routing model according to RFC 3561.
+
+  c) IPv6 extensions support and two new examples for fragmentation and loose routing.
+
+API changes from ns-3.6
 -----------------------
 API changes for this release are documented in the file CHANGES.html. 
 
--- a/examples/ipv6/fragmentation-ipv6.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/examples/ipv6/fragmentation-ipv6.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -45,26 +45,25 @@
  */
 class StackHelper
 {
-  public:
-
-    /**
-     * \brief Add an address to a IPv6 node.
-     * \param n node
-     * \param interface interface index
-     * \param address IPv6 address to add
-     */
-    inline void AddAddress (Ptr<Node>& n, uint32_t interface, Ipv6Address address)
-    {
+public:
+  /**
+   * \brief Add an address to a IPv6 node.
+   * \param n node
+   * \param interface interface index
+   * \param address IPv6 address to add
+   */
+  inline void AddAddress (Ptr<Node>& n, uint32_t interface, Ipv6Address address)
+  {
       Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
       ipv6->AddAddress (interface, address);
     }
 
-    /**
-     * \brief Print the routing table.
-     * \param n the node
-     */
-    inline void PrintRoutingTable (Ptr<Node>& n)
-    {
+  /**
+   * \brief Print the routing table.
+   * \param n the node
+   */
+  inline void PrintRoutingTable (Ptr<Node>& n)
+  {
       Ptr<Ipv6StaticRouting> routing = 0;
       Ipv6StaticRoutingHelper routingHelper;
       Ptr<Ipv6> ipv6 = n->GetObject<Ipv6> ();
@@ -78,15 +77,15 @@
 
       nbRoutes = routing->GetNRoutes ();
       for (uint32_t i = 0 ; i < nbRoutes ; i++)
-      {
-        route = routing->GetRoute (i);
-        std::cout << route.GetDest () << "\t"
-          << route.GetGateway () << "\t"
-          << route.GetInterface () << "\t"
-          << route.GetPrefixToUse () << "\t"
-          << std::endl;
-      }
-    }
+        {
+          route = routing->GetRoute (i);
+          std::cout << route.GetDest () << "\t"
+            << route.GetGateway () << "\t"
+            << route.GetInterface () << "\t"
+            << route.GetPrefixToUse () << "\t"
+            << std::endl;
+        }
+  } 
 };
 
 int main (int argc, char** argv)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/routing/aodv.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,214 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * This is an example script for AODV manet routing protocol. 
+ *
+ * Authors: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "ns3/aodv-module.h"
+#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/v4ping-helper.h"
+#include <iostream>
+#include <cmath>
+
+using namespace ns3;
+
+/**
+ * \brief Test script.
+ * 
+ * This script creates 1-dimensional grid topology and then ping last node from the first one:
+ * 
+ * [10.0.0.1] <-- step --> [10.0.0.2] <-- step --> [10.0.0.3] <-- step --> [10.0.04]
+ * 
+ * ping 10.0.0.4
+ */
+class AodvExample 
+{
+public:
+  AodvExample ();
+  /// Configure script parameters, \return true on successful configuration
+  bool Configure (int argc, char **argv);
+  /// Run simulation
+  void Run ();
+  /// Report results
+  void Report (std::ostream & os);
+  
+private:
+  ///\name parameters
+  //\{
+  /// Number of nodes
+  uint32_t size;
+  /// Distance between nodes, meters
+  double step;
+  /// Simulation time, seconds
+  double totalTime;
+  /// Write per-device PCAP traces if true
+  bool pcap;
+  //\}
+  
+  ///\name network
+  //\{
+  NodeContainer nodes;
+  NetDeviceContainer devices;
+  Ipv4InterfaceContainer interfaces;
+  //\}
+  
+private:
+  void CreateNodes ();
+  void CreateDevices ();
+  void InstallInternetStack ();
+  void InstallApplications ();
+};
+
+int main (int argc, char **argv)
+{
+  AodvExample test;
+  if (! test.Configure(argc, argv)) 
+    NS_FATAL_ERROR ("Configuration failed. Aborted.");
+  
+  test.Run ();
+  test.Report (std::cout);
+  return 0;
+}
+
+//-----------------------------------------------------------------------------
+AodvExample::AodvExample () :
+  size (10),
+  step (120),
+  totalTime (10),
+  pcap (true)
+{
+}
+
+bool
+AodvExample::Configure (int argc, char **argv)
+{
+  // Enable AODV logs by default. Comment this if too noisy
+  // LogComponentEnable("AodvRoutingProtocol", LOG_LEVEL_ALL);
+  
+  SeedManager::SetSeed(12345);
+  CommandLine cmd;
+  
+  cmd.AddValue ("pcap", "Write PCAP traces.", pcap);
+  cmd.AddValue ("size", "Number of nodes.", size);
+  cmd.AddValue ("time", "Simulation time, s.", totalTime);
+  cmd.AddValue ("step", "Grid step, m", step);
+  
+  cmd.Parse (argc, argv);
+  return true;
+}
+
+void
+AodvExample::Run ()
+{
+//  Config::SetDefault ("ns3::WifiRemoteStationManager::RtsCtsThreshold", UintegerValue (1)); // enable rts cts all the time.
+  CreateNodes ();
+  CreateDevices ();
+  InstallInternetStack ();
+  InstallApplications ();
+  
+  std::cout << "Starting simulation for " << totalTime << " s ...\n";
+  
+  Simulator::Stop (Seconds (totalTime));
+  Simulator::Run ();
+  Simulator::Destroy ();
+}
+
+void
+AodvExample::Report (std::ostream &)
+{ 
+}
+
+void
+AodvExample::CreateNodes ()
+{
+  std::cout << "Creating " << (unsigned)size << " nodes " << step << " m apart.\n";
+  nodes.Create (size);
+  // Name nodes
+  for (uint32_t i = 0; i < size; ++i)
+     {
+       std::ostringstream os;
+       os << "node-" << i;
+       Names::Add (os.str (), nodes.Get (i));
+     }
+  // Create static grid
+  MobilityHelper mobility;
+  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+                                "MinX", DoubleValue (0.0),
+                                "MinY", DoubleValue (0.0),
+                                "DeltaX", DoubleValue (step),
+                                "DeltaY", DoubleValue (0),
+                                "GridWidth", UintegerValue (size),
+                                "LayoutType", StringValue ("RowFirst"));
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (nodes);
+}
+
+void
+AodvExample::CreateDevices ()
+{
+  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+  wifiMac.SetType ("ns3::AdhocWifiMac");
+  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+  YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+  wifiPhy.SetChannel (wifiChannel.Create ());
+  WifiHelper wifi = WifiHelper::Default ();
+  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("wifia-6mbs"), "RtsCtsThreshold", UintegerValue (0));
+  devices = wifi.Install (wifiPhy, wifiMac, nodes); 
+  
+  if (pcap)
+    {
+      wifiPhy.EnablePcapAll (std::string ("aodv"));
+    }
+}
+
+void
+AodvExample::InstallInternetStack ()
+{
+  AodvHelper aodv;
+  // you can configure AODV attributes here using aodv.Set(name, value)
+  InternetStackHelper stack;
+  stack.SetRoutingHelper (aodv);
+  stack.Install (nodes);
+  Ipv4AddressHelper address;
+  address.SetBase ("10.0.0.0", "255.0.0.0");
+  interfaces = address.Assign (devices);
+}
+
+void
+AodvExample::InstallApplications ()
+{
+  V4PingHelper ping (interfaces.GetAddress (size - 1));
+  ping.SetAttribute ("Verbose", BooleanValue (true));
+  
+  ApplicationContainer p = ping.Install (nodes.Get (0));
+  p.Start (Seconds (0));
+  p.Stop (Seconds (totalTime));
+
+  // move node away
+  Ptr<Node> node = nodes.Get (size/2);
+  Ptr<MobilityModel> mob = node->GetObject<MobilityModel> ();
+  Simulator::Schedule (Seconds (totalTime/3), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5));
+}
+
--- a/examples/routing/wscript	Tue Nov 24 20:37:29 2009 +0100
+++ b/examples/routing/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -44,3 +44,7 @@
     obj = bld.create_ns3_program('simple-routing-ping6',
       ['csma', 'internet-stack'])
     obj.source = 'simple-routing-ping6.cc'
+    
+    obj = bld.create_ns3_program('aodv',
+                                 ['wifi', 'internet-stack', 'aodv'])
+    obj.source = 'aodv.cc'
--- a/src/applications/v4ping/v4ping.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/applications/v4ping/v4ping.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -20,10 +20,10 @@
 #include "ns3/ipv4-address.h"
 #include "ns3/socket.h"
 #include "ns3/uinteger.h"
+#include "ns3/boolean.h"
 #include "ns3/inet-socket-address.h"
 #include "ns3/packet.h"
 #include "ns3/trace-source-accessor.h"
-#include "ns3/simulator.h"
 
 namespace ns3 {
 
@@ -41,6 +41,19 @@
 		   Ipv4AddressValue (),
 		   MakeIpv4AddressAccessor (&V4Ping::m_remote),
 		   MakeIpv4AddressChecker ())
+    .AddAttribute ("Verbose",
+                   "Produce usual output.",
+                   BooleanValue (false),
+                   MakeBooleanAccessor (&V4Ping::m_verbose),
+                   MakeBooleanChecker ())
+    .AddAttribute ("Interval", "Wait  interval  seconds between sending each packet.",
+                   TimeValue (Seconds (1)),
+                   MakeTimeAccessor (&V4Ping::m_interval),
+                   MakeTimeChecker ())
+    .AddAttribute ("Size", "The number of data bytes to be sent, real packet will be 8 (ICMP) + 20 (IP) bytes longer.",
+                   UintegerValue (56),
+                   MakeUintegerAccessor (&V4Ping::m_size),
+                   MakeUintegerChecker<uint32_t> (16))
     .AddTraceSource ("Rtt",
 		     "The rtt calculated by the ping.",
 		     MakeTraceSourceAccessor (&V4Ping::m_traceRtt));
@@ -49,9 +62,14 @@
 }
 
 V4Ping::V4Ping ()
-  : m_socket (0),
-    m_seq (0)
-{}
+  : m_interval (Seconds (1)),
+    m_size (56),
+    m_socket (0),
+    m_seq (0),
+    m_verbose (false),
+    m_recv (0)
+{
+}
 V4Ping::~V4Ping ()
 {}
 
@@ -92,6 +110,7 @@
       NS_ASSERT (realFrom.GetPort () == 1); // protocol should be icmp.
       Ipv4Header ipv4;
       p->RemoveHeader (ipv4);
+      uint32_t recvSize = p->GetSize ();
       NS_ASSERT (ipv4.GetProtocol () == 1); // protocol should be icmp.
       Icmpv4Header icmp;
       p->RemoveHeader (icmp);
@@ -99,10 +118,11 @@
 	{
 	  Icmpv4Echo echo;
 	  p->RemoveHeader (echo);
-	  if (echo.GetSequenceNumber () == (m_seq - 1) &&
-	      echo.GetIdentifier () == 0)
+	  std::map<uint16_t, Time>::iterator i = m_sent.find(echo.GetSequenceNumber());
+	  
+	  if (i != m_sent.end () && echo.GetIdentifier () == 0)
 	    {
-              uint32_t buf[4];
+              uint32_t buf[m_size / 4];
 	      uint32_t dataSize = echo.GetDataSize ();
 	      if (dataSize == sizeof(buf))
 		{
@@ -111,13 +131,22 @@
 		  if (buf[0] == GetNode ()->GetId () &&
 		      buf[1] == GetApplicationId ())
 		    {
-		      int64_t ts = buf[3];
-		      ts <<= 32;
-		      ts |= buf[2];
-		      Time sendTime = TimeStep (ts);
+		      Time sendTime = i->second;
 		      NS_ASSERT (Simulator::Now () > sendTime);
 		      Time delta = Simulator::Now () - sendTime;
+		      
+		      m_sent.erase (i);
+		      m_avgRtt.Update (delta.GetMilliSeconds());
+		      m_recv++;
 		      m_traceRtt (delta);
+		      
+		      if (m_verbose)
+		        {
+		          std::cout << recvSize << " bytes from " << realFrom.GetIpv4() << ":"
+                                    << " icmp_seq=" << echo.GetSequenceNumber ()
+                                    << " ttl=" << (unsigned)ipv4.GetTtl ()
+                                    << " time=" << delta.GetMilliSeconds() << " ms\n";
+		        }
 		    }
 		}
 	    }
@@ -135,20 +164,8 @@
 }
 
 void 
-V4Ping::StartApplication (void)
+V4Ping::Send ()
 {
-  NS_LOG_FUNCTION (this);
-  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
-  NS_ASSERT (m_socket != 0);
-  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
-  m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this));
-  InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
-  int status;
-  status = m_socket->Bind (src);
-  NS_ASSERT (status != -1);
-  InetSocketAddress dst = InetSocketAddress (m_remote, 0);
-  status = m_socket->Connect (dst);
-  NS_ASSERT (status != -1);
   Ptr<Packet> p = Create<Packet> ();
   Icmpv4Echo echo;
   echo.SetSequenceNumber (m_seq);
@@ -161,22 +178,17 @@
   // (where any difference would show up anyway) and borrow that code.  Don't
   // be too surprised when you see that this is a little endian convention.
   //
-  uint8_t data[4 * sizeof(uint32_t)];
+  uint8_t data[m_size];
+  for (uint32_t i = 0; i < m_size; ++i) data[i] = 0;
+  NS_ASSERT (m_size >= 16);
+  
   uint32_t tmp = GetNode ()->GetId ();
   Write32 (&data[0 * sizeof(uint32_t)], tmp);
 
   tmp = GetApplicationId ();
   Write32 (&data[1 * sizeof(uint32_t)], tmp);
 
-  int64_t now = Simulator::Now ().GetTimeStep ();
-  tmp = now & 0xffffffff;
-  Write32 (&data[2 * sizeof(uint32_t)], tmp);
-
-  now >>= 32;
-  tmp = now & 0xffffffff;
-  Write32 (&data[3 * sizeof(uint32_t)], tmp);
-
-  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) &data, 16);
+  Ptr<Packet> dataPacket = Create<Packet> ((uint8_t *) &data, m_size);
   echo.SetData (dataPacket);
   p->AddHeader (echo);
   Icmpv4Header header;
@@ -184,13 +196,57 @@
   header.SetCode (0);
   p->AddHeader (header);
   m_socket->Send (p, 0);
+  m_sent.insert (std::make_pair (m_seq - 1, Simulator::Now()));  
+  m_next = Simulator::Schedule (m_interval, & V4Ping::Send, this);
+}
+
+void 
+V4Ping::StartApplication (void)
+{
+  NS_LOG_FUNCTION (this);
   
+  m_started = Simulator::Now ();
+  if (m_verbose)
+    {
+      std::cout << "PING  " << m_remote << " 56(84) bytes of data.\n";
+    }
+  
+  m_socket = Socket::CreateSocket (GetNode (), TypeId::LookupByName ("ns3::Ipv4RawSocketFactory"));
+  NS_ASSERT (m_socket != 0);
+  m_socket->SetAttribute ("Protocol", UintegerValue (1)); // icmp
+  m_socket->SetRecvCallback (MakeCallback (&V4Ping::Receive, this));
+  InetSocketAddress src = InetSocketAddress (Ipv4Address::GetAny (), 0);
+  int status;
+  status = m_socket->Bind (src);
+  NS_ASSERT (status != -1);
+  InetSocketAddress dst = InetSocketAddress (m_remote, 0);
+  status = m_socket->Connect (dst);
+  NS_ASSERT (status != -1);
+  
+  Send ();
 }
 void 
 V4Ping::StopApplication (void)
 {
   NS_LOG_FUNCTION (this);
+  m_next.Cancel();
   m_socket->Close ();
+  
+  if (m_verbose)
+    {
+      std::ostringstream os;
+      os.precision (4);
+      os << "--- " << m_remote << " ping statistics ---\n" 
+                << m_seq << " packets transmitted, " << m_recv << " received, " 
+                << ((m_seq - m_recv) * 100 / m_seq) << "% packet loss, "
+                << "time " << (Simulator::Now () - m_started).GetMilliSeconds () << "ms\n";
+      
+      if (m_avgRtt.Count () > 0)
+        os << "rtt min/avg/max/mdev = " << m_avgRtt.Min() << "/" << m_avgRtt.Avg() << "/"
+                                               << m_avgRtt.Max() << "/" << m_avgRtt.Err()
+                                               << " ms\n";
+      std::cout << os.str();
+    }
 }
 
 
--- a/src/applications/v4ping/v4ping.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/applications/v4ping/v4ping.h	Tue Nov 24 20:38:21 2009 +0100
@@ -1,9 +1,27 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * 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
+ */
 #ifndef V4PING_H
 #define V4PING_H
 
 #include "ns3/application.h"
 #include "ns3/traced-callback.h"
 #include "ns3/nstime.h"
+#include "ns3/average.h"
+#include "ns3/simulator.h"
+#include <map>
 
 namespace ns3 {
 
@@ -35,11 +53,32 @@
   virtual void DoDispose (void);
   uint32_t GetApplicationId (void) const;
   void Receive (Ptr<Socket> socket);
+  void Send ();
 
+  /// Remote address
   Ipv4Address m_remote;
+  /// Wait  interval  seconds between sending each packet
+  Time m_interval;
+  /** 
+   * Specifies  the number of data bytes to be sent. 
+   * The default is 56, which translates into 64 ICMP data bytes when combined with the 8 bytes of ICMP header data.
+   */
+  uint32_t m_size;
   Ptr<Socket> m_socket;
   uint16_t m_seq;
   TracedCallback<Time> m_traceRtt;
+  /// produce ping-style output if true
+  bool m_verbose;
+  /// received packets counter
+  uint32_t m_recv;
+  /// Start time to report total ping time
+  Time m_started;
+  /// Average rtt is ms
+  Average<double> m_avgRtt;
+  /// Next packet will be sent
+  EventId m_next;
+  /// All sent but not answered packets. Map icmp seqno -> when sent
+  std::map<uint16_t, Time> m_sent;
 };
 
 } // namespace ns3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/contrib/average.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,82 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef AVERAGE_H
+#define AVERAGE_H
+#include <cmath>
+#include <iostream>
+#include <limits>
+
+/// Simple average, min, max and std. deviation calculator
+template <typename T = double>
+class Average
+{
+public:
+  Average () : 
+    size (0), min (std::numeric_limits<T>::max ()), max (0), avg (0), avg2 (0) 
+  {
+  }
+
+  /// Add new value
+  void Update (T const & x)
+  {
+    min = std::min (x, min);
+    max = std::max (x, max);
+    avg = (size * avg + x) / (size + 1);
+    avg2 = (size * avg2 + x * x) / (size + 1);
+    size++;
+  }
+  /// Reset statistics
+  void Reset ()
+  {
+    size = 0;
+    min = std::numeric_limits<T>::max ();
+    max = 0;
+    avg = 0;
+    avg2 = 0;
+  }
+
+  ///\name Access results
+  //\{
+  uint32_t Count () const { return size; }
+  T        Min   () const { return min; }
+  T        Max   () const { return max; }
+  double   Avg   () const { return avg; }
+  double   Err   () const { return sqrt ((avg2 - avg*avg)/(size - 1)); }
+  //\}
+
+private:
+  uint32_t size;
+  T      min, max;
+  double avg, avg2;
+};
+
+/// Print avg (err) [min, max]
+template <typename T>
+std::ostream & operator<< (std::ostream & os, Average<T> const & x)
+{
+  if (x.Count () != 0)
+    os << x.Avg () << " (" << x.Err () << ") [" << x.Min () << ", " << x.Max () << "]";
+  else
+    os << "NA"; // not avaliable
+  return os;
+}
+
+#endif /* AVERAGE_H */
--- a/src/contrib/wscript	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/contrib/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -43,6 +43,7 @@
         'file-config.h',
         'config-store.h',
         'flow-id-tag.h',
+        'average.h',
         ]
 
     if bld.env['ENABLE_GTK_CONFIG_STORE']:
--- a/src/devices/point-to-point/ppp-header.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/devices/point-to-point/ppp-header.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -56,7 +56,20 @@
 void 
 PppHeader::Print (std::ostream &os) const
 {
-  os << "Point-to-Point Protocol: " << m_protocol;
+  std::string proto;
+  
+  switch(m_protocol)
+  {
+    case 0x0021: /* IPv4 */
+      proto = "IP (0x0021)";
+      break;
+    case 0x0057: /* IPv6 */
+      proto = "IPv6 (0x0057)";
+      break;
+    default:
+      NS_ASSERT_MSG(false, "PPP Protocol number not defined!");
+  }
+  os << "Point-to-Point Protocol: " << proto; 
 }
 
   uint32_t
--- a/src/devices/wifi/adhoc-wifi-mac.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/devices/wifi/adhoc-wifi-mac.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -28,6 +28,7 @@
 #include "ns3/pointer.h"
 #include "ns3/packet.h"
 #include "ns3/log.h"
+#include "ns3/trace-source-accessor.h"
 
 NS_LOG_COMPONENT_DEFINE ("AdhocWifiMac");
 
@@ -48,6 +49,16 @@
                    PointerValue (),
                    MakePointerAccessor (&AdhocWifiMac::GetDcaTxop),
                    MakePointerChecker<DcaTxop> ()) 
+  .AddTraceSource ( "TxOkHeader",
+                    "The header of successfully transmitted packet",
+                    MakeTraceSourceAccessor (
+                      &AdhocWifiMac::m_txOkCallback)
+                  )
+  .AddTraceSource ( "TxErrHeader",
+                    "The header of unsuccessfully transmitted packet",
+                    MakeTraceSourceAccessor (
+                      &AdhocWifiMac::m_txErrCallback)
+                  )
     ;
   return tid;
 }
@@ -67,6 +78,7 @@
   m_dca = CreateObject<DcaTxop> ();
   m_dca->SetLow (m_low);
   m_dca->SetManager (m_dcfManager);
+  m_dca->SetTxFailedCallback (MakeCallback (&AdhocWifiMac::TxFailed, this));
 }
 AdhocWifiMac::~AdhocWifiMac ()
 {}
@@ -276,6 +288,14 @@
       break;
     }
 }
-
-
+void
+AdhocWifiMac::TxOk (const WifiMacHeader &hdr)
+{
+  m_txOkCallback (hdr);
+}
+void
+AdhocWifiMac::TxFailed (const WifiMacHeader &hdr)
+{
+  m_txErrCallback (hdr);
+}
 } // namespace ns3
--- a/src/devices/wifi/adhoc-wifi-mac.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/devices/wifi/adhoc-wifi-mac.h	Tue Nov 24 20:38:21 2009 +0100
@@ -87,8 +87,9 @@
   AdhocWifiMac (const AdhocWifiMac & ctor_arg);
   AdhocWifiMac &operator = (const AdhocWifiMac &o);
   Ptr<DcaTxop> GetDcaTxop(void) const;
+  void TxOk (WifiMacHeader const &hdr);
+  void TxFailed (WifiMacHeader const &hdr);
   virtual void FinishConfigureStandard (enum WifiPhyStandard standard);
-
   Ptr<DcaTxop> m_dca;
   Callback<void,Ptr<Packet>, Mac48Address, Mac48Address> m_upCallback;
   Ptr<WifiRemoteStationManager> m_stationManager;
@@ -97,6 +98,8 @@
   MacRxMiddle *m_rxMiddle;
   Ptr<MacLow> m_low;
   Ssid m_ssid;
+  TracedCallback<WifiMacHeader const &> m_txOkCallback;
+  TracedCallback<WifiMacHeader const &> m_txErrCallback;
 };
 
 } // namespace ns3
--- a/src/devices/wifi/wifi-net-device.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/devices/wifi/wifi-net-device.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -92,6 +92,15 @@
 }
 
 void
+WifiNetDevice::DoStart (void)
+{
+  m_phy->Start ();
+  m_mac->Start ();
+  m_stationManager->Start ();
+  NetDevice::DoStart ();
+}
+
+void
 WifiNetDevice::CompleteConfig (void)
 {
   if (m_mac == 0 || 
--- a/src/devices/wifi/wifi-net-device.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/devices/wifi/wifi-net-device.h	Tue Nov 24 20:38:21 2009 +0100
@@ -104,6 +104,7 @@
 
 private:
   virtual void DoDispose (void);
+  virtual void DoStart (void);
   void ForwardUp (Ptr<Packet> packet, Mac48Address from, Mac48Address to);
   void LinkUp (void);
   void LinkDown (void);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/aodv-helper.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,55 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#include "aodv-helper.h"
+#include "ns3/aodv-routing-protocol.h"
+#include "ns3/node-list.h"
+#include "ns3/names.h"
+#include "ns3/ipv4-list-routing.h"
+
+namespace ns3
+{
+
+AodvHelper::AodvHelper() : 
+  Ipv4RoutingHelper ()
+{
+  m_agentFactory.SetTypeId ("ns3::aodv::RoutingProtocol");
+}
+
+AodvHelper* 
+AodvHelper::Copy (void) const 
+{
+  return new AodvHelper (*this); 
+}
+
+Ptr<Ipv4RoutingProtocol> 
+AodvHelper::Create (Ptr<Node> node) const
+{
+  Ptr<aodv::RoutingProtocol> agent = m_agentFactory.Create<aodv::RoutingProtocol> ();
+  node->AggregateObject (agent);
+  return agent;
+}
+
+void 
+AodvHelper::Set (std::string name, const AttributeValue &value)
+{
+  m_agentFactory.Set (name, value);
+}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/helper/aodv-helper.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,70 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>, written after OlsrHelper by Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
+ */
+#ifndef AODVHELPER_H_
+#define AODVHELPER_H_
+
+#include "ns3/object-factory.h"
+#include "ns3/node.h"
+#include "node-container.h"
+#include "ipv4-routing-helper.h"
+
+namespace ns3
+{
+/**
+ * \ingroup aodv
+ * \brief Helper class that adds AODV routing to nodes.
+ */
+class AodvHelper : public Ipv4RoutingHelper
+{
+public:
+  AodvHelper();
+
+  /**
+   * \internal
+   * \returns pointer to clone of this OlsrHelper 
+   * 
+   * This method is mainly for internal use by the other helpers;
+   * clients are expected to free the dynamic memory allocated by this method
+   */
+  AodvHelper* 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
+   * 
+   * TODO: support installing AODV on the subset of all available IP interfaces
+   */
+  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::aodv::RoutingProtocol
+   */
+  void Set (std::string name, const AttributeValue &value);
+  
+private:
+  ObjectFactory m_agentFactory;
+};
+
+}
+#endif /* AODVHELPER_H_ */
--- a/src/helper/v4ping-helper.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/helper/v4ping-helper.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -30,6 +30,12 @@
   m_factory.Set ("Remote", Ipv4AddressValue (remote));
 }
 
+void 
+V4PingHelper::SetAttribute (std::string name, const AttributeValue &value)
+{
+  m_factory.Set (name, value);
+}
+
 ApplicationContainer
 V4PingHelper::Install (Ptr<Node> node) const
 {
--- a/src/helper/v4ping-helper.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/helper/v4ping-helper.h	Tue Nov 24 20:38:21 2009 +0100
@@ -55,6 +55,12 @@
    */
   ApplicationContainer Install (std::string nodeName) const;
 
+  /**
+   * \brief Configure ping applications attribute 
+   * \param name   attribute's name
+   * \param value  attribute's value
+   */
+  void SetAttribute (std::string name, const AttributeValue &value);
 private:
   /**
    * \internal
--- a/src/helper/wscript	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/helper/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -1,7 +1,7 @@
 ## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
 
 def build(bld):
-    helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'nix-vector-routing', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
+    helper = bld.create_ns3_module('helper', ['internet-stack', 'wifi', 'point-to-point', 'csma', 'olsr', 'global-routing', 'onoff', 'packet-sink', 'udp-echo'])
     helper.source = [
         'node-container.cc',
         'net-device-container.cc',
@@ -29,6 +29,7 @@
         'ipv4-global-routing-helper.cc',
         'ipv4-list-routing-helper.cc',
         'ipv4-routing-helper.cc',
+        'aodv-helper.cc',
         'mesh-helper.cc',
         'dot11s-installer.cc',
         'flame-installer.cc',
@@ -68,9 +69,10 @@
         'nqos-wifi-mac-helper.h',
         'qos-wifi-mac-helper.h',
         'ipv4-nix-vector-helper.h',
-        'ipv4-global-routing-helper.h',
+	'ipv4-global-routing-helper.h',
         'ipv4-list-routing-helper.h',
         'ipv4-routing-helper.h',
+        'aodv-helper.h',
         'mesh-helper.h',
         'mesh-stack-installer.h',
         'dot11s-installer.h',
--- a/src/internet-stack/icmpv4-l4-protocol.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/icmpv4-l4-protocol.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -86,6 +86,7 @@
   NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0);
   Ipv4Header header;
   header.SetDestination (dest);
+  header.SetProtocol (PROT_NUMBER);
   Socket::SocketErrno errno_;
   Ptr<Ipv4Route> route;
   uint32_t oif = 0; //specify non-zero if bound to a source address
--- a/src/internet-stack/ipv4-interface.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv4-interface.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -42,7 +42,8 @@
     .AddAttribute ("ArpCache",
                    "The arp cache for this ipv4 interface",
                    PointerValue (0),
-                   MakePointerAccessor (&Ipv4Interface::m_cache),
+                   MakePointerAccessor (&Ipv4Interface::SetArpCache, 
+                                        &Ipv4Interface::GetArpCache),
                    MakePointerChecker<ArpCache> ())
     ;
     ;
@@ -128,6 +129,18 @@
   return m_metric;
 }
 
+void
+Ipv4Interface::SetArpCache (Ptr<ArpCache> a)
+{
+  m_cache = a;
+}
+
+Ptr<ArpCache>
+Ipv4Interface::GetArpCache () const
+{
+  return m_cache;
+}
+
 /**
  * These are IP interface states and may be distinct from 
  * NetDevice states, such as found in real implementations
--- a/src/internet-stack/ipv4-interface.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv4-interface.h	Tue Nov 24 20:38:21 2009 +0100
@@ -56,12 +56,17 @@
 
   void SetNode (Ptr<Node> node); 
   void SetDevice (Ptr<NetDevice> device);
+  void SetArpCache (Ptr<ArpCache>);
 
   /**
    * \returns the underlying NetDevice. This method cannot return zero.
    */
   Ptr<NetDevice> GetDevice (void) const;
-
+  /**
+   * \return ARP cache used by this interface
+   */
+  Ptr<ArpCache> GetArpCache () const;
+  
   /**
    * \param metric configured routing metric (cost) of this interface
    *
--- a/src/internet-stack/ipv4-l3-protocol.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv4-l3-protocol.h	Tue Nov 24 20:38:21 2009 +0100
@@ -241,7 +241,6 @@
   bool m_ipForward;
   L4List_t m_protocols;
   Ipv4InterfaceList m_interfaces;
-  uint32_t m_nInterfaces;
   uint8_t m_defaultTtl;
   uint16_t m_identification;
   Ptr<Node> m_node;
--- a/src/internet-stack/ipv4-raw-socket-impl.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv4-raw-socket-impl.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -174,6 +174,7 @@
     {
       Ipv4Header header;
       header.SetDestination (dst);
+      header.SetProtocol (m_protocol);
       SocketErrno errno_ = ERROR_NOTERROR;//do not use errno as it is the standard C last error number 
       Ptr<Ipv4Route> route;
       uint32_t oif = 0; //specify non-zero if bound to a source address
@@ -247,6 +248,7 @@
     {
       return false;
     }
+  NS_LOG_LOGIC ("src = " << m_src << " dst = " << m_dst);
   if ((m_src == Ipv4Address::GetAny () || ipHeader.GetDestination () == m_src) &&
       (m_dst == Ipv4Address::GetAny () || ipHeader.GetSource () == m_dst) &&
       ipHeader.GetProtocol () == m_protocol)
--- a/src/internet-stack/ipv6-extension-demux.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-extension-demux.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -35,9 +35,9 @@
   static TypeId tid = TypeId ("ns3::Ipv6ExtensionDemux")
     .SetParent<Object> ()
     .AddAttribute ("Extensions", "The set of IPv6 extensions registered with this demux.",
-        ObjectVectorValue (),
-        MakeObjectVectorAccessor (&Ipv6ExtensionDemux::m_extensions),
-        MakeObjectVectorChecker<Ipv6Extension> ())
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&Ipv6ExtensionDemux::m_extensions),
+                   MakeObjectVectorChecker<Ipv6Extension> ())
     ;
   return tid;
 }
@@ -53,10 +53,10 @@
 void Ipv6ExtensionDemux::DoDispose ()
 {
   for (Ipv6ExtensionList_t::iterator it = m_extensions.begin (); it != m_extensions.end (); it++)
-  {
-    (*it)->Dispose ();
-    *it = 0;
-  }
+    {
+      (*it)->Dispose ();
+      *it = 0;
+    }
   m_extensions.clear ();
   m_node = 0;
   Object::DoDispose ();
@@ -75,12 +75,12 @@
 Ptr<Ipv6Extension> Ipv6ExtensionDemux::GetExtension (uint8_t extensionNumber)
 {
   for (Ipv6ExtensionList_t::iterator i = m_extensions.begin (); i != m_extensions.end (); ++i)
-  {
-    if ((*i)->GetExtensionNumber () == extensionNumber)
     {
-      return *i;
+      if ((*i)->GetExtensionNumber () == extensionNumber)
+        {
+          return *i;
+        }
     }
-  }
   return 0;
 }
 
--- a/src/internet-stack/ipv6-extension-demux.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-extension-demux.h	Tue Nov 24 20:38:21 2009 +0100
@@ -37,66 +37,66 @@
  */
 class Ipv6ExtensionDemux : public Object
 {
-  public:
-    /**
-     * \brief The interface ID.
-     * \return type ID
-     */
-    static TypeId GetTypeId (void);
+public:
+  /**
+   * \brief The interface ID.
+   * \return type ID
+   */
+  static TypeId GetTypeId (void);
 
-    /**
-     * \brief Constructor.
-     */
-    Ipv6ExtensionDemux ();
+  /**
+   * \brief Constructor.
+   */
+  Ipv6ExtensionDemux ();
 
-    /**
-     * \brief Destructor.
-     */
-    virtual ~Ipv6ExtensionDemux ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~Ipv6ExtensionDemux ();
 
-    /**
-     * \brief Set the node.
-     * \param node the node to set
-     */
-    void SetNode (Ptr<Node> node);
+  /**
+   * \brief Set the node.
+   * \param node the node to set
+   */
+  void SetNode (Ptr<Node> node);
 
-    /**
-     * \brief Insert a new IPv6 Extension.
-     * \param extension the extension to insert
-     */
-    void Insert (Ptr<Ipv6Extension> extension);
+  /**
+   * \brief Insert a new IPv6 Extension.
+   * \param extension the extension to insert
+   */
+  void Insert (Ptr<Ipv6Extension> extension);
 
-    /**
-     * \brief Get the extension corresponding to extensionNumber.
-     * \param extensionNumber extension number of the extension to retrieve
-     * \return a matching IPv6 extension
-     */
-    Ptr<Ipv6Extension> GetExtension (uint8_t extensionNumber);
+  /**
+   * \brief Get the extension corresponding to extensionNumber.
+   * \param extensionNumber extension number of the extension to retrieve
+   * \return a matching IPv6 extension
+   */
+  Ptr<Ipv6Extension> GetExtension (uint8_t extensionNumber);
 
-    /**
-     * \brief Remove an extension from this demux.
-     * \param extension pointer on the extension to remove
-     */
-    void Remove (Ptr<Ipv6Extension> extension);
+  /**
+   * \brief Remove an extension from this demux.
+   * \param extension pointer on the extension to remove
+   */
+  void Remove (Ptr<Ipv6Extension> extension);
 
-  protected:   
-    /**
-     * \brief Dispose object.
-     */
-    virtual void DoDispose ();
+protected:   
+  /**
+   * \brief Dispose object.
+   */
+  virtual void DoDispose ();
 
-  private:
-    typedef std::list<Ptr<Ipv6Extension> > Ipv6ExtensionList_t;
+private:
+  typedef std::list<Ptr<Ipv6Extension> > Ipv6ExtensionList_t;
 
-    /**
-     * \brief List of IPv6 Extensions supported.
-     */
-    Ipv6ExtensionList_t m_extensions;
+  /**
+   * \brief List of IPv6 Extensions supported.
+   */
+  Ipv6ExtensionList_t m_extensions;
 
-    /**
-     * \brief The node.
-     */
-    Ptr<Node> m_node;
+  /**
+   * \brief The node.
+   */
+  Ptr<Node> m_node;
 };
 
 } /* namespace ns3 */
--- a/src/internet-stack/ipv6-extension-header.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-extension-header.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -45,7 +45,7 @@
 }
 
 Ipv6ExtensionHeader::Ipv6ExtensionHeader ()
-  : m_nextHeader (0),
+: m_nextHeader (0),
   m_length (0),
   m_data (0)
 {
@@ -106,13 +106,13 @@
   i.Read (data, dataLength);
 
   if (dataLength > m_data.GetSize ())
-  {
-    m_data.AddAtEnd (dataLength - m_data.GetSize ());
-  }
+    {
+      m_data.AddAtEnd (dataLength - m_data.GetSize ());
+    }
   else 
-  {
-    m_data.RemoveAtEnd (m_data.GetSize () - dataLength);
-  }
+    {
+      m_data.RemoveAtEnd (m_data.GetSize () - dataLength);
+    }
 
   i = m_data.Begin ();
   i.Write (data, dataLength);
@@ -121,7 +121,7 @@
 }
 
 OptionField::OptionField (uint32_t optionsOffset)
-  : m_optionData (0),
+: m_optionData (0),
   m_optionsOffset (optionsOffset)
 {
 }
@@ -141,13 +141,13 @@
   uint32_t fill = CalculatePad ((Ipv6OptionHeader::Alignment) {8,0});
   NS_LOG_LOGIC ("fill with " << fill << " bytes padding");
   switch (fill)
-  {
+    {
     case 0: return;
     case 1: Ipv6OptionPad1Header ().Serialize (start);
             return;
     default: Ipv6OptionPadnHeader (fill).Serialize (start);
              return;
-  }
+    }
 }
 
 uint32_t OptionField::Deserialize (Buffer::Iterator start, uint32_t length)
@@ -167,13 +167,13 @@
   uint32_t pad = CalculatePad (option.GetAlignment ());
   NS_LOG_LOGIC ("need " << pad << " bytes padding");
   switch (pad)
-  {
+    {
     case 0: break; //no padding needed
     case 1: AddOption (Ipv6OptionPad1Header ());
-      break;
+            break;
     default: AddOption (Ipv6OptionPadnHeader (pad));
-      break;
-  }
+             break;
+    }
 
   m_optionData.AddAtEnd (option.GetSerializedSize ());
   Buffer::Iterator it = m_optionData.End ();
@@ -214,7 +214,7 @@
 }
 
 Ipv6ExtensionHopByHopHeader::Ipv6ExtensionHopByHopHeader ()
-  : OptionField (2)
+: OptionField (2)
 {
 }
 
@@ -269,7 +269,7 @@
 }
 
 Ipv6ExtensionDestinationHeader::Ipv6ExtensionDestinationHeader ()
-  : OptionField (2)
+: OptionField (2)
 {
 }
 
@@ -325,7 +325,7 @@
 }
 
 Ipv6ExtensionFragmentHeader::Ipv6ExtensionFragmentHeader ()
-  : m_offset (0),
+: m_offset (0),
   m_identification (0)
 {
 }
@@ -416,7 +416,7 @@
 }
 
 Ipv6ExtensionRoutingHeader::Ipv6ExtensionRoutingHeader ()
-  : m_typeRouting (0),
+: m_typeRouting (0),
   m_segmentsLeft (0)
 {
 }
@@ -495,7 +495,7 @@
 }
 
 Ipv6ExtensionLooseRoutingHeader::Ipv6ExtensionLooseRoutingHeader ()
-  : m_routersAddress (0)
+: m_routersAddress (0)
 {
 }
 
@@ -535,9 +535,9 @@
     << " typeRouting = " << (uint32_t)GetTypeRouting () << " segmentsLeft = " << (uint32_t)GetSegmentsLeft () << " ";
 
   for (std::vector<Ipv6Address>::const_iterator it = m_routersAddress.begin (); it != m_routersAddress.end (); it++)
-  {
-    os << *it << " ";
-  }
+    {
+      os << *it << " ";
+    }
 
   os << " )";
 }
@@ -559,10 +559,10 @@
   i.WriteU32 (0);
 
   for (VectorIpv6Address_t::const_iterator it = m_routersAddress.begin (); it != m_routersAddress.end () ; it++)
-  {
-    it->Serialize (buff);
-    i.Write (buff, 16);
-  }
+    {
+      it->Serialize (buff);
+      i.Write (buff, 16);
+    }
 }
 
 uint32_t Ipv6ExtensionLooseRoutingHeader::Deserialize (Buffer::Iterator start) 
@@ -577,10 +577,10 @@
   i.ReadU32 ();
 
   for (std::vector<Ipv6Address>::iterator it = m_routersAddress.begin (); it != m_routersAddress.end (); it++)
-  {
-    i.Read (buff, 16);
-    it->Set (buff);
-  }
+    {
+      i.Read (buff, 16);
+      it->Set (buff);
+    }
 
   return GetSerializedSize ();
 }
--- a/src/internet-stack/ipv6-extension.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-extension.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -53,11 +53,11 @@
   static TypeId tid = TypeId ("ns3::Ipv6Extension")
     .SetParent<Object> ()
     .AddAttribute ("ExtensionNumber", "The IPv6 extension number.",
-        UintegerValue (0),
-        MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
-        MakeUintegerChecker<uint8_t> ())
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&Ipv6Extension::GetExtensionNumber),
+                   MakeUintegerChecker<uint8_t> ())
     .AddTraceSource ("Drop", "Drop ipv6 packet",
-        MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace))
+                     MakeTraceSourceAccessor (&Ipv6Extension::m_dropTrace))
     ;
   return tid;
 }
@@ -102,65 +102,65 @@
   uint8_t optionLength = 0;
 
   while (length > processedSize && !isDropped)
-  {
-    optionType = *(data + processedSize);
-    ipv6Option = ipv6OptionDemux->GetOption (optionType);
+    {
+      optionType = *(data + processedSize);
+      ipv6Option = ipv6OptionDemux->GetOption (optionType);
 
-    if (ipv6Option == 0)
-    {
-      optionType >>= 6;
-      switch (optionType)
-      {
-        case 0:
-          optionLength = *(data + processedSize + 1);
-          break;
+      if (ipv6Option == 0)
+        {
+          optionType >>= 6;
+          switch (optionType)
+            {
+            case 0:
+              optionLength = *(data + processedSize + 1);
+              break;
 
-        case 1:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
+            case 1:
+              NS_LOG_LOGIC ("Unknown Option. Drop!");
+              m_dropTrace (packet);
+              optionLength = 0;
+              isDropped = true;
+              break;
 
-        case 2:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
-          icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
+            case 2:
+              NS_LOG_LOGIC ("Unknown Option. Drop!");
+              icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
+              m_dropTrace (packet);
+              optionLength = 0;
+              isDropped = true;
+              break;
 
-        case 3:
-          NS_LOG_LOGIC ("Unknown Option. Drop!");
+            case 3:
+              NS_LOG_LOGIC ("Unknown Option. Drop!");
 
-          if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
-          {
-            icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
-            m_dropTrace (packet);
-            optionLength = 0;
-            isDropped = true;
-            break;
-          }
+              if (!ipv6Header.GetDestinationAddress ().IsMulticast ())
+                {
+                  icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_UNKNOWN_OPTION, offset + processedSize);
+                  m_dropTrace (packet);
+                  optionLength = 0;
+                  isDropped = true;
+                  break;
+                }
 
-          m_dropTrace (packet);
-          optionLength = 0;
-          isDropped = true;
-          break;
+              m_dropTrace (packet);
+              optionLength = 0;
+              isDropped = true;
+              break;
 
-        default:
-          break;
-      }
+            default:
+              break;
+            }
 
-    }
-    else
-    {
-      optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
+        }
+      else
+        {
+          optionLength = ipv6Option->Process (packet, offset + processedSize, ipv6Header, isDropped);
+        }
+
+      processedSize += optionLength;
+      p->RemoveAtStart (optionLength);
     }
 
-    processedSize += optionLength;
-    p->RemoveAtStart (optionLength);
-  }
-
   return processedSize;
 }
 
@@ -203,9 +203,9 @@
   Ipv6ExtensionHopByHopHeader hopbyhopHeader;
   p->RemoveHeader (hopbyhopHeader);
   if (nextHeader)
-  {
-    *nextHeader = hopbyhopHeader.GetNextHeader ();
-  }
+    {
+      *nextHeader = hopbyhopHeader.GetNextHeader ();
+    }
 
   uint8_t processedSize = hopbyhopHeader.GetOptionsOffset ();
   offset += processedSize;
@@ -255,9 +255,9 @@
   Ipv6ExtensionDestinationHeader destinationHeader;
   p->RemoveHeader (destinationHeader);
   if (nextHeader)
-  {
-    *nextHeader = destinationHeader.GetNextHeader ();
-  }
+    {
+      *nextHeader = destinationHeader.GetNextHeader ();
+    }
 
   uint8_t processedSize = destinationHeader.GetOptionsOffset ();
   offset += processedSize;
@@ -295,9 +295,9 @@
   NS_LOG_FUNCTION_NOARGS ();
 
   for (MapFragments_t::iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
-  {
-    it->second = 0;
-  }
+    {
+      it->second = 0;
+    }
 
   m_fragments.clear ();
   Ipv6Extension::DoDispose ();
@@ -321,9 +321,9 @@
   p->RemoveHeader (fragmentHeader);
 
   if (nextHeader)
-  {
-    *nextHeader = fragmentHeader.GetNextHeader ();
-  }
+    {
+      *nextHeader = fragmentHeader.GetNextHeader ();
+    }
 
   bool moreFragment = fragmentHeader.GetMoreFragment ();
   uint16_t fragmentOffset = fragmentHeader.GetOffset ();
@@ -335,35 +335,35 @@
 
   MapFragments_t::iterator it = m_fragments.find (fragmentsId);
   if (it == m_fragments.end ())
-  {
-    fragments = Create<Fragments> ();
-    m_fragments.insert (std::make_pair (fragmentsId, fragments));
-  }
+    {
+      fragments = Create<Fragments> ();
+      m_fragments.insert (std::make_pair (fragmentsId, fragments));
+    }
   else
-  {
-    fragments = it->second;
-  }
+    {
+      fragments = it->second;
+    }
 
   if (fragmentOffset == 0)
-  {
-    Ptr<Packet> unfragmentablePart = packet->Copy ();
-    unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
-    fragments->SetUnfragmentablePart (unfragmentablePart);
-  }
+    {
+      Ptr<Packet> unfragmentablePart = packet->Copy ();
+      unfragmentablePart->RemoveAtEnd (packet->GetSize () - offset);
+      fragments->SetUnfragmentablePart (unfragmentablePart);
+    }
 
   fragments->AddFragment (p, fragmentOffset, moreFragment);
 
   if (fragments->IsEntire ())
-  {
-    packet = fragments->GetPacket ();
-    isDropped = false;
-  }
+    {
+      packet = fragments->GetPacket ();
+      isDropped = false;
+    }
   else 
-  {
-    NS_LOG_LOGIC ("Fragment. Drop!");
-    m_dropTrace (packet);
-    isDropped = true;
-  }
+    {
+      NS_LOG_LOGIC ("Fragment. Drop!");
+      m_dropTrace (packet);
+      isDropped = true;
+    }
 
   return 0;
 }
@@ -381,10 +381,10 @@
   bool moreHeader = true;
   if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
         || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
-  {
-    moreHeader = false;
-    ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
-  }
+    {
+      moreHeader = false;
+      ipv6Header.SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
+    }
 
   std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> > unfragmentablePart;
   uint32_t unfragmentablePartSize = 0;
@@ -394,64 +394,64 @@
   uint8_t extensionHeaderLength;
 
   while (moreHeader) 
-  {
-    if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP) 
     {
-      Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
-      p->RemoveHeader (*hopbyhopHeader);
+      if (nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP) 
+        {
+          Ipv6ExtensionHopByHopHeader *hopbyhopHeader = new Ipv6ExtensionHopByHopHeader ();
+          p->RemoveHeader (*hopbyhopHeader);
 
-      nextHeader = hopbyhopHeader->GetNextHeader ();
-      extensionHeaderLength = hopbyhopHeader->GetLength ();
+          nextHeader = hopbyhopHeader->GetNextHeader ();
+          extensionHeaderLength = hopbyhopHeader->GetLength ();
 
-      if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
-            || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
-      {
-        moreHeader = false;
-        hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
-      }
+          if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
+                || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
+            {
+              moreHeader = false;
+              hopbyhopHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
+            }
 
-      unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
-      unfragmentablePartSize += extensionHeaderLength;
-    }
-    else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING) 
-    {
-      uint8_t numberAddress = (*(p->PeekData () + 1)) / 2;
-      Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader ();
-      routingHeader->SetNumberAddress (numberAddress);
-      p->RemoveHeader (*routingHeader);
+          unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (hopbyhopHeader, Ipv6Header::IPV6_EXT_HOP_BY_HOP));
+          unfragmentablePartSize += extensionHeaderLength;
+        }
+      else if (nextHeader == Ipv6Header::IPV6_EXT_ROUTING) 
+        {
+          uint8_t numberAddress = (*(p->PeekData () + 1)) / 2;
+          Ipv6ExtensionLooseRoutingHeader *routingHeader = new Ipv6ExtensionLooseRoutingHeader ();
+          routingHeader->SetNumberAddress (numberAddress);
+          p->RemoveHeader (*routingHeader);
 
-      nextHeader = routingHeader->GetNextHeader ();
-      extensionHeaderLength = routingHeader->GetLength ();
+          nextHeader = routingHeader->GetNextHeader ();
+          extensionHeaderLength = routingHeader->GetLength ();
 
-      if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
-            || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
-      {
-        moreHeader = false;
-        routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
-      }
+          if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING
+                || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
+            {
+              moreHeader = false;
+              routingHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
+            }
 
-      unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
-      unfragmentablePartSize += extensionHeaderLength;
-    }
-    else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION) 
-    {
-      Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
-      p->RemoveHeader (*destinationHeader);
+          unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (routingHeader, Ipv6Header::IPV6_EXT_ROUTING));
+          unfragmentablePartSize += extensionHeaderLength;
+        }
+      else if (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION) 
+        {
+          Ipv6ExtensionDestinationHeader *destinationHeader = new Ipv6ExtensionDestinationHeader ();
+          p->RemoveHeader (*destinationHeader);
 
-      nextHeader = destinationHeader->GetNextHeader ();
-      extensionHeaderLength = destinationHeader->GetLength ();
+          nextHeader = destinationHeader->GetNextHeader ();
+          extensionHeaderLength = destinationHeader->GetLength ();
 
-      if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING 
-            || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
-      {
-        moreHeader = false;
-        destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
-      }
+          if (!(nextHeader == Ipv6Header::IPV6_EXT_HOP_BY_HOP || nextHeader == Ipv6Header::IPV6_EXT_ROUTING 
+                || (nextHeader == Ipv6Header::IPV6_EXT_DESTINATION && *p->PeekData () == Ipv6Header::IPV6_EXT_ROUTING)))
+            {
+              moreHeader = false;
+              destinationHeader->SetNextHeader (Ipv6Header::IPV6_EXT_FRAGMENTATION);
+            }
 
-      unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
-      unfragmentablePartSize += extensionHeaderLength;
+          unfragmentablePart.push_back (std::make_pair<Ipv6ExtensionHeader *, uint8_t> (destinationHeader, Ipv6Header::IPV6_EXT_DESTINATION));
+          unfragmentablePartSize += extensionHeaderLength;
+        }
     }
-  }
 
   Ipv6ExtensionFragmentHeader fragmentHeader;
   uint8_t fragmentHeaderSize = fragmentHeader.GetSerializedSize ();
@@ -465,65 +465,65 @@
   uint16_t offset = 0;
 
   do 
-  {
-    if (p->GetSize () > offset + maxFragmentablePartSize)
     {
-      moreFragment = true;
-      currentFragmentablePartSize = maxFragmentablePartSize;
-    }
-    else 
-    {
-      moreFragment = false;
-      currentFragmentablePartSize = p->GetSize () - offset;
-    }
+      if (p->GetSize () > offset + maxFragmentablePartSize)
+        {
+          moreFragment = true;
+          currentFragmentablePartSize = maxFragmentablePartSize;
+        }
+      else 
+        {
+          moreFragment = false;
+          currentFragmentablePartSize = p->GetSize () - offset;
+        }
 
-    currentFragmentablePartSize -= currentFragmentablePartSize % 8;
+      currentFragmentablePartSize -= currentFragmentablePartSize % 8;
 
-    fragmentHeader.SetNextHeader (nextHeader);
-    fragmentHeader.SetLength (currentFragmentablePartSize);
-    fragmentHeader.SetOffset (offset);
-    fragmentHeader.SetMoreFragment (moreFragment);
-    fragmentHeader.SetIdentification (identification);
+      fragmentHeader.SetNextHeader (nextHeader);
+      fragmentHeader.SetLength (currentFragmentablePartSize);
+      fragmentHeader.SetOffset (offset);
+      fragmentHeader.SetMoreFragment (moreFragment);
+      fragmentHeader.SetIdentification (identification);
 
-    Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
-    offset += currentFragmentablePartSize;
+      Ptr<Packet> fragment = p->CreateFragment (offset, currentFragmentablePartSize);
+      offset += currentFragmentablePartSize;
 
-    fragment->AddHeader (fragmentHeader);
+      fragment->AddHeader (fragmentHeader);
 
-    for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
-    {
-      if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
-      {
-        fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
-      }
-      else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
-      {
-        fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
-      }
-      else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
-      {
-        fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
-      }
-    }
+      for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
+        {
+          if (it->second == Ipv6Header::IPV6_EXT_HOP_BY_HOP)
+            {
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionHopByHopHeader *>(it->first));
+            }
+          else if (it->second == Ipv6Header::IPV6_EXT_ROUTING)
+            {
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionLooseRoutingHeader *>(it->first));
+            }
+          else if (it->second == Ipv6Header::IPV6_EXT_DESTINATION)
+            {
+              fragment->AddHeader (*dynamic_cast<Ipv6ExtensionDestinationHeader *>(it->first));
+            }
+        }
 
-    ipv6Header.SetPayloadLength (fragment->GetSize ());
-    fragment->AddHeader (ipv6Header);
+      ipv6Header.SetPayloadLength (fragment->GetSize ());
+      fragment->AddHeader (ipv6Header);
 
-    std::ostringstream oss;
-    fragment->Print (oss);
-    listFragments.push_back (fragment);
-  } while (moreFragment);
+      std::ostringstream oss;
+      fragment->Print (oss);
+      listFragments.push_back (fragment);
+    } while (moreFragment);
 
   for (std::list<std::pair<Ipv6ExtensionHeader *, uint8_t> >::iterator it = unfragmentablePart.begin (); it != unfragmentablePart.end (); it++)
-  {
-    delete it->first;
-  }
+    {
+      delete it->first;
+    }
 
   unfragmentablePart.clear ();
 }
 
 Ipv6ExtensionFragment::Fragments::Fragments ()
-  : m_moreFragment (0)
+: m_moreFragment (0)
 {
 }
 
@@ -536,17 +536,17 @@
   std::list<std::pair<Ptr<Packet>, uint16_t> >::iterator it;
 
   for (it = m_fragments.begin (); it != m_fragments.end (); it++)
-  {
-    if (it->second > fragmentOffset)
     {
-      break;
+      if (it->second > fragmentOffset)
+        {
+          break;
+        }
     }
-  }
 
   if (it == m_fragments.end ())
-  {
-    m_moreFragment = moreFragment;
-  }
+    {
+      m_moreFragment = moreFragment;
+    }
 
   m_fragments.insert (it, std::make_pair<Ptr<Packet>, uint16_t> (fragment, fragmentOffset));
 }
@@ -561,20 +561,20 @@
   bool ret = !m_moreFragment && m_fragments.size () > 0;
 
   if (ret)
-  {
-    uint16_t lastEndOffset = 0;
+    {
+      uint16_t lastEndOffset = 0;
 
-    for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
-    {
-      if (lastEndOffset != it->second)
-      {
-        ret = false;
-        break;
-      }
+      for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
+        {
+          if (lastEndOffset != it->second)
+            {
+              ret = false;
+              break;
+            }
 
-      lastEndOffset += it->first->GetSize ();				
+          lastEndOffset += it->first->GetSize ();				
+        }
     }
-  }
 
   return ret;
 }
@@ -584,9 +584,9 @@
   Ptr<Packet> p =  m_unfragmentable->Copy ();
 
   for (std::list<std::pair<Ptr<Packet>, uint16_t> >::const_iterator it = m_fragments.begin (); it != m_fragments.end (); it++)
-  {
-    p->AddAtEnd (it->first);
-  }
+    {
+      p->AddAtEnd (it->first);
+    }
 
   return p;
 }
@@ -640,14 +640,14 @@
   const uint8_t *buff = packet->PeekData ();
 
   uint8_t routingNextHeader = *buff;
-  uint8_t routingLength = *(buff+1);
-  uint8_t routingTypeRouting = *(buff+2);
-  uint8_t routingSegmentsLeft = *(buff+3);
+  uint8_t routingLength = *(buff + 1);
+  uint8_t routingTypeRouting = *(buff + 2);
+  uint8_t routingSegmentsLeft = *(buff + 3);
 
   if (nextHeader)
-  {
-    *nextHeader = routingNextHeader; 
-  }
+    {
+      *nextHeader = routingNextHeader; 
+    }
 
   Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
 
@@ -655,22 +655,22 @@
   Ptr<Ipv6ExtensionRouting> ipv6ExtensionRouting = ipv6ExtensionRoutingDemux->GetExtensionRouting (routingTypeRouting);
 
   if (ipv6ExtensionRouting == 0)
-  {
-    if (routingSegmentsLeft == 0)
     {
-      isDropped = false;
+      if (routingSegmentsLeft == 0)
+        {
+          isDropped = false;
+        }
+      else
+        {
+          NS_LOG_LOGIC ("Malformed header. Drop!");
+
+          icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
+          m_dropTrace (packet);
+          isDropped = true;
+        }
+
+      return routingLength;
     }
-    else
-    {
-      NS_LOG_LOGIC ("Malformed header. Drop!");
-
-      icmpv6->SendErrorParameterError (malformedPacket, ipv6Header.GetSourceAddress (), Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
-      m_dropTrace (packet);
-      isDropped = true;
-    }
-
-    return routingLength;
-  }
 
   return ipv6ExtensionRouting->Process (packet, offset, ipv6Header, dst, (uint8_t *)0, isDropped);
 }
@@ -683,9 +683,9 @@
   static TypeId tid = TypeId ("ns3::Ipv6ExtensionRoutingDemux")
     .SetParent<Object> ()
     .AddAttribute ("Routing Extensions", "The set of IPv6 Routing extensions registered with this demux.",
-        ObjectVectorValue (),
-        MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting),
-        MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&Ipv6ExtensionRoutingDemux::m_extensionsRouting),
+                   MakeObjectVectorChecker<Ipv6ExtensionRouting> ())
     ;
   return tid;
 }
@@ -701,10 +701,10 @@
 void Ipv6ExtensionRoutingDemux::DoDispose ()
 {
   for (Ipv6ExtensionRoutingList_t::iterator it = m_extensionsRouting.begin (); it != m_extensionsRouting.end (); it++)
-  {
-    (*it)->Dispose ();
-    *it = 0;
-  }
+    {
+      (*it)->Dispose ();
+      *it = 0;
+    }
   m_extensionsRouting.clear ();
   m_node = 0;
   Object::DoDispose ();
@@ -723,12 +723,12 @@
 Ptr<Ipv6ExtensionRouting> Ipv6ExtensionRoutingDemux::GetExtensionRouting (uint8_t typeRouting)
 {
   for (Ipv6ExtensionRoutingList_t::iterator i = m_extensionsRouting.begin (); i != m_extensionsRouting.end (); i++)
-  {
-    if ((*i)->GetTypeRouting () == typeRouting)
     {
-      return *i;
+      if ((*i)->GetTypeRouting () == typeRouting)
+        {
+          return *i;
+        }
     }
-  }
   return 0;
 }
 
@@ -792,9 +792,9 @@
   p->RemoveHeader (routingHeader);
 
   if (nextHeader)
-  {
-    *nextHeader = routingHeader.GetNextHeader ();
-  }
+    {
+      *nextHeader = routingHeader.GetNextHeader ();
+    }
 
   Ptr<Icmpv6L4Protocol> icmpv6 = GetNode ()->GetObject<Ipv6L3Protocol> ()->GetIcmpv6 ();
 
@@ -808,51 +808,51 @@
   Ipv6Address nextAddress;
 
   if (segmentsLeft == 0)
-  {
-    isDropped = false;
-    return routingHeader.GetSerializedSize ();
-  }
+    {
+      isDropped = false;
+      return routingHeader.GetSerializedSize ();
+    }
 
   if (length % 2 != 0)
-  {
-    NS_LOG_LOGIC ("Malformed header. Drop!");
-    icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
-    m_dropTrace (packet);
-    isDropped = true;
-    return routingHeader.GetSerializedSize ();
-  }
+    {
+      NS_LOG_LOGIC ("Malformed header. Drop!");
+      icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 1);
+      m_dropTrace (packet);
+      isDropped = true;
+      return routingHeader.GetSerializedSize ();
+    }
 
   if (segmentsLeft > nbAddress)
-  {
-    NS_LOG_LOGIC ("Malformed header. Drop!");
-    icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
-    m_dropTrace (packet);
-    isDropped = true;
-    return routingHeader.GetSerializedSize ();
-  }
+    {
+      NS_LOG_LOGIC ("Malformed header. Drop!");
+      icmpv6->SendErrorParameterError (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_MALFORMED_HEADER, offset + 3);
+      m_dropTrace (packet);
+      isDropped = true;
+      return routingHeader.GetSerializedSize ();
+    }
 
   routingHeader.SetSegmentsLeft (segmentsLeft - 1);
   nextAddressIndex = nbAddress - segmentsLeft;
   nextAddress = routingHeader.GetRouterAddress (nextAddressIndex);
 
   if (nextAddress.IsMulticast () || destAddress.IsMulticast ()) 
-  {
-    m_dropTrace (packet);
-    isDropped = true;
-    return routingHeader.GetSerializedSize ();
-  }
+    {
+      m_dropTrace (packet);
+      isDropped = true;
+      return routingHeader.GetSerializedSize ();
+    }
 
   routingHeader.SetRouterAddress (nextAddressIndex, destAddress);
   ipv6header.SetDestinationAddress (nextAddress);
 
   if (hopLimit <= 1)
-  {
-    NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
-    icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
-    m_dropTrace (packet);
-    isDropped = true;
-    return routingHeader.GetSerializedSize ();
-  }
+    {
+      NS_LOG_LOGIC ("Time Exceeded : Hop Limit <= 1. Drop!");
+      icmpv6->SendErrorTimeExceeded (malformedPacket, srcAddress, Icmpv6Header::ICMPV6_HOPLIMIT);
+      m_dropTrace (packet);
+      isDropped = true;
+      return routingHeader.GetSerializedSize ();
+    }
 
   routingHeader.SetLength (88);
   ipv6header.SetHopLimit (hopLimit - 1);
@@ -873,14 +873,14 @@
   Ptr<Ipv6Route> rtentry = ipv6rp->RouteOutput (p, ipv6header, 0, err);
 
   if (rtentry)
-  {
-    /* we know a route exists so send packet now */
-    ipv6->SendRealOut (rtentry, p, ipv6header);
-  }
+    {
+      /* we know a route exists so send packet now */
+      ipv6->SendRealOut (rtentry, p, ipv6header);
+    }
   else
-  {
-    NS_LOG_INFO ("No route for next router");
-  }
+    {
+      NS_LOG_INFO ("No route for next router");
+    }
 
   /* as we directly send packet, mark it as dropped */
   isDropped = true; 
--- a/src/internet-stack/ipv6-option-demux.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-option-demux.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -35,9 +35,9 @@
   static TypeId tid = TypeId ("ns3::Ipv6OptionDemux")
     .SetParent<Object> ()
     .AddAttribute ("Options", "The set of IPv6 options registered with this demux.",
-        ObjectVectorValue (),
-        MakeObjectVectorAccessor (&Ipv6OptionDemux::m_options),
-        MakeObjectVectorChecker<Ipv6Option> ())
+                   ObjectVectorValue (),
+                   MakeObjectVectorAccessor (&Ipv6OptionDemux::m_options),
+                   MakeObjectVectorChecker<Ipv6Option> ())
     ;
   return tid;
 }
@@ -53,10 +53,10 @@
 void Ipv6OptionDemux::DoDispose ()
 {
   for (Ipv6OptionList_t::iterator it = m_options.begin (); it != m_options.end (); it++)
-  {
-    (*it)->Dispose ();
-    *it = 0;
-  }
+    {
+      (*it)->Dispose ();
+      *it = 0;
+    }
   m_options.clear ();
   m_node = 0;
   Object::DoDispose ();
@@ -75,12 +75,12 @@
 Ptr<Ipv6Option> Ipv6OptionDemux::GetOption (int optionNumber)
 {
   for (Ipv6OptionList_t::iterator i = m_options.begin (); i != m_options.end (); ++i)
-  {
-    if ((*i)->GetOptionNumber () == optionNumber)
     {
-      return *i;
+      if ((*i)->GetOptionNumber () == optionNumber)
+        {
+          return *i;
+        }
     }
-  }
   return 0;
 }
 
--- a/src/internet-stack/ipv6-option-demux.h	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-option-demux.h	Tue Nov 24 20:38:21 2009 +0100
@@ -37,66 +37,66 @@
  */
 class Ipv6OptionDemux : public Object
 {
-  public:
-    /**
-     * \brief The interface ID.
-     * \return type ID
-     */
-    static TypeId GetTypeId (void);
+public:
+  /**
+   * \brief The interface ID.
+   * \return type ID
+   */
+  static TypeId GetTypeId (void);
 
-    /**
-     * \brief Constructor.
-     */
-    Ipv6OptionDemux ();
+  /**
+   * \brief Constructor.
+   */
+  Ipv6OptionDemux ();
 
-    /**
-     * \brief Destructor.
-     */
-    virtual ~Ipv6OptionDemux ();
+  /**
+   * \brief Destructor.
+   */
+  virtual ~Ipv6OptionDemux ();
 
-    /**
-     * \brief Set the node.
-     * \param node the node to set
-     */
-    void SetNode (Ptr<Node> node);
+  /**
+   * \brief Set the node.
+   * \param node the node to set
+   */
+  void SetNode (Ptr<Node> node);
 
-    /**
-     * \brief Insert a new IPv6 Option.
-     * \param option the option to insert
-     */
-    void Insert (Ptr<Ipv6Option> option);
+  /**
+   * \brief Insert a new IPv6 Option.
+   * \param option the option to insert
+   */
+  void Insert (Ptr<Ipv6Option> option);
 
-    /**
-     * \brief Get the option corresponding to optionNumber.
-     * \param optionNumber the option number of the option to retrieve
-     * \return a matching IPv6 option
-     */
-    Ptr<Ipv6Option> GetOption (int optionNumber);
+  /**
+   * \brief Get the option corresponding to optionNumber.
+   * \param optionNumber the option number of the option to retrieve
+   * \return a matching IPv6 option
+   */
+  Ptr<Ipv6Option> GetOption (int optionNumber);
 
-    /**
-     * \brief Remove an option from this demux.
-     * \param option pointer on the option to remove
-     */
-    void Remove (Ptr<Ipv6Option> option);
+  /**
+   * \brief Remove an option from this demux.
+   * \param option pointer on the option to remove
+   */
+  void Remove (Ptr<Ipv6Option> option);
 
-  protected:
-    /**
-     * \brief Dispose this object.
-     */
-    virtual void DoDispose();
+protected:
+  /**
+   * \brief Dispose this object.
+   */
+  virtual void DoDispose();
 
-  private:
-    typedef std::list<Ptr<Ipv6Option> > Ipv6OptionList_t;
+private:
+  typedef std::list<Ptr<Ipv6Option> > Ipv6OptionList_t;
 
-    /**
-     * \brief List of IPv6 Options supported.
-     */
-    Ipv6OptionList_t m_options;
+  /**
+   * \brief List of IPv6 Options supported.
+   */
+  Ipv6OptionList_t m_options;
 
-    /**
-     * \brief The node.
-     */
-    Ptr<Node> m_node;
+  /**
+   * \brief The node.
+   */
+  Ptr<Node> m_node;
 };
 
 } /* namespace ns3 */
--- a/src/internet-stack/ipv6-option-header.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-option-header.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -45,7 +45,7 @@
 }
 
 Ipv6OptionHeader::Ipv6OptionHeader ()
-  : m_type (0),
+: m_type (0),
   m_length (0)
 {
 }
@@ -212,9 +212,9 @@
   i.WriteU8 (GetLength ());
 
   for (int padding = 0; padding < GetLength (); padding++)
-  {
-    i.WriteU8 (0);
-  }
+    {
+      i.WriteU8 (0);
+    }
 }
 
 uint32_t Ipv6OptionPadnHeader::Deserialize (Buffer::Iterator start) 
@@ -315,7 +315,7 @@
 }
 
 Ipv6OptionRouterAlertHeader::Ipv6OptionRouterAlertHeader ()
-  : m_value (0)
+: m_value (0)
 {
   SetLength (2);
 }
--- a/src/internet-stack/ipv6-option.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/ipv6-option.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -36,9 +36,9 @@
   static TypeId tid = TypeId ("ns3::Ipv6Option")
     .SetParent<Object> ()
     .AddAttribute ("OptionNumber", "The IPv6 option number.",
-        UintegerValue (0),
-        MakeUintegerAccessor (&Ipv6Option::GetOptionNumber),
-        MakeUintegerChecker<uint8_t> ())
+                   UintegerValue (0),
+                   MakeUintegerAccessor (&Ipv6Option::GetOptionNumber),
+                   MakeUintegerChecker<uint8_t> ())
     ;
   return tid;
 }
--- a/src/internet-stack/tcp-l4-protocol.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/tcp-l4-protocol.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -576,6 +576,7 @@
       // should be cached.
       Ipv4Header header;
       header.SetDestination (daddr);
+      header.SetProtocol (PROT_NUMBER);
       Socket::SocketErrno errno_;
       Ptr<Ipv4Route> route;
       uint32_t oif = 0; //specify non-zero if bound to a source address
@@ -615,6 +616,7 @@
       // should be cached.
       Ipv4Header header;
       header.SetDestination (daddr);
+      header.SetProtocol (PROT_NUMBER);
       Socket::SocketErrno errno_;
       Ptr<Ipv4Route> route;
       uint32_t oif = 0; //specify non-zero if bound to a source address
--- a/src/internet-stack/udp-socket-impl.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/udp-socket-impl.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -373,6 +373,8 @@
           // Get the primary address
           Ipv4InterfaceAddress iaddr = ipv4->GetAddress (i, 0);
           Ipv4Address addri = iaddr.GetLocal ();
+          if (addri == Ipv4Address ("127.0.0.1"))
+            continue;
           Ipv4Mask maski = iaddr.GetMask ();
           if (maski == Ipv4Mask::GetOnes ())
             {
@@ -403,6 +405,7 @@
     {
       Ipv4Header header;
       header.SetDestination (dest);
+      header.SetProtocol (UdpL4Protocol::PROT_NUMBER);
       Socket::SocketErrno errno_;
       Ptr<Ipv4Route> route;
       uint32_t oif = 0; //specify non-zero if bound to a source address
--- a/src/internet-stack/wscript	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/internet-stack/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -128,6 +128,8 @@
         'sequence-number.h',
         'icmpv4.h',
         'icmpv6-header.h',
+        # used by routing
+        'ipv4-interface.h',
         'ipv4-l3-protocol.h',
         'ipv6-l3-protocol.h',
         'ipv6-extension-header.h',
--- a/src/node/socket.cc	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/node/socket.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -45,7 +45,9 @@
 Socket::CreateSocket (Ptr<Node> node, TypeId tid)
 {
   Ptr<Socket> s;
+  NS_ASSERT (node != 0);
   Ptr<SocketFactory> socketFactory = node->GetObject<SocketFactory> (tid);
+  NS_ASSERT (socketFactory != 0);
   s = socketFactory->CreateSocket ();
   NS_ASSERT (s != 0);
   return s;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-neighbor.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,173 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ *
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "aodv-neighbor.h"
+#include "ns3/log.h"
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("AodvNeighbors");
+
+namespace ns3
+{
+namespace aodv
+{
+Neighbors::Neighbors (Time delay) : 
+  m_ntimer (Timer::CANCEL_ON_DESTROY)
+{
+  m_ntimer.SetDelay(delay);
+  m_ntimer.SetFunction(&Neighbors::Purge, this);
+  m_txErrorCallback = MakeCallback (& Neighbors::ProcessTxError, this);
+}
+
+bool
+Neighbors::IsNeighbor (Ipv4Address addr)
+{
+  Purge ();
+  for (std::vector<Neighbor>::const_iterator i = m_nb.begin ();
+      i != m_nb.end (); ++i)
+    {
+      if (i->m_neighborAddress == addr)
+        return true;
+    }
+  return false;
+}
+
+Time
+Neighbors::GetExpireTime (Ipv4Address addr)
+{
+  Purge ();
+  for (std::vector<Neighbor>::const_iterator i = m_nb.begin (); i
+      != m_nb.end (); ++i)
+    {
+      if (i->m_neighborAddress == addr)
+        return (i->m_expireTime - Simulator::Now ());
+    }
+  return Seconds (0);
+}
+
+void
+Neighbors::Update (Ipv4Address addr, Time expire)
+{
+  for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
+    if (i->m_neighborAddress == addr)
+      {
+        i->m_expireTime
+            = std::max (expire + Simulator::Now (), i->m_expireTime);
+        if (i->m_hardwareAddress == Mac48Address ())
+          i->m_hardwareAddress = LookupMacAddress (i->m_neighborAddress);
+        return;
+      }
+
+  NS_LOG_LOGIC ("Open link to " << addr);
+  Neighbor neighbor (addr, LookupMacAddress (addr), expire + Simulator::Now ());
+  m_nb.push_back (neighbor);
+  Purge ();
+}
+
+struct CloseNeighbor
+{
+  bool operator() (const Neighbors::Neighbor & nb) const
+  {
+    return ((nb.m_expireTime < Simulator::Now ()) || nb.close);
+  }
+};
+
+void
+Neighbors::Purge ()
+{
+  if (m_nb.empty ())
+    return;
+
+  CloseNeighbor pred;
+  if (!m_handleLinkFailure.IsNull ())
+    {
+      for (std::vector<Neighbor>::iterator j = m_nb.begin (); j != m_nb.end (); ++j)
+        {
+          if (pred (*j))
+            {
+              NS_LOG_LOGIC ("Close link to " << j->m_neighborAddress);
+              m_handleLinkFailure (j->m_neighborAddress);
+            }
+        }
+    }
+  m_nb.erase (std::remove_if (m_nb.begin (), m_nb.end (), pred), m_nb.end ());
+  m_ntimer.Cancel ();
+  m_ntimer.Schedule ();
+}
+
+void
+Neighbors::ScheduleTimer ()
+{
+  m_ntimer.Cancel ();
+  m_ntimer.Schedule ();
+}
+
+void
+Neighbors::AddArpCache (Ptr<ArpCache> a)
+{
+  m_arp.push_back (a);
+}
+
+void
+Neighbors::DelArpCache (Ptr<ArpCache> a)
+{
+  m_arp.erase (std::remove (m_arp.begin (), m_arp.end (), a), m_arp.end ());
+}
+
+Mac48Address
+Neighbors::LookupMacAddress (Ipv4Address addr)
+{
+  Mac48Address hwaddr;
+  for (std::vector<Ptr<ArpCache> >::const_iterator i = m_arp.begin ();
+      i != m_arp.end (); ++i)
+    {
+      ArpCache::Entry * entry = (*i)->Lookup (addr);
+      if (entry != 0 && entry->IsAlive () && !entry->IsExpired ())
+        {
+          hwaddr = Mac48Address::ConvertFrom (entry->GetMacAddress ());
+          break;
+        }
+    }
+  return hwaddr;
+}
+
+void
+Neighbors::ProcessTxError (WifiMacHeader const & hdr)
+{
+  Mac48Address addr = hdr.GetAddr1 ();
+
+  for (std::vector<Neighbor>::iterator i = m_nb.begin (); i != m_nb.end (); ++i)
+    {
+      if (i->m_hardwareAddress == addr)
+        i->close = true;
+    }
+  Purge ();
+}
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-neighbor.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,114 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ *
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef AODVNEIGHBOR_H
+#define AODVNEIGHBOR_H
+
+#include "ns3/simulator.h"
+#include "ns3/timer.h"
+#include "ns3/ipv4-address.h"
+#include "ns3/callback.h"
+#include "ns3/wifi-mac-header.h"
+#include "ns3/arp-cache.h"
+#include <vector>
+
+namespace ns3
+{
+namespace aodv
+{
+class RoutingProtocol;
+/**
+ * \ingroup aodv
+ * \brief maintain list of active neighbors
+ */
+class Neighbors
+{
+public:
+  /// c-tor
+  Neighbors (Time delay);
+  /// Neighbor description
+  struct Neighbor
+  {
+    Ipv4Address m_neighborAddress;
+    Mac48Address m_hardwareAddress;
+    Time m_expireTime;
+    bool close;
+    
+    Neighbor (Ipv4Address ip, Mac48Address mac, Time t) :
+      m_neighborAddress (ip), m_hardwareAddress (mac), m_expireTime (t),
+      close (false)
+    {
+    }
+  };
+  /// Return expire time for neighbor node with address addr, if exists, else return 0.
+  Time GetExpireTime (Ipv4Address addr);
+  /// Check that node with address addr  is neighbor
+  bool IsNeighbor (Ipv4Address addr);
+  /// Update expire time for entry with address addr, if it exists, else add new entry
+  void Update (Ipv4Address addr, Time expire);
+  /// Remove all expired entries
+  void Purge ();
+  /// Schedule m_ntimer.
+  void ScheduleTimer ();
+  /// Remove all entries
+  void Clear () { m_nb.clear (); }
+  
+  /// Add ARP cache to be used to allow layer 2 notifications processing
+  void AddArpCache (Ptr<ArpCache>);
+  /// Don't use given ARP cache any more (interface is down)
+  void DelArpCache (Ptr<ArpCache>);
+  /// Get callback to ProcessTxError
+  Callback<void, WifiMacHeader const &> GetTxErrorCallback () const { return m_txErrorCallback; }
+ 
+  ///\name Handle link failure callback
+  //\{
+  void SetCallback (Callback<void, Ipv4Address> cb) { m_handleLinkFailure = cb;}
+  Callback<void, Ipv4Address> GetCallback () const { return m_handleLinkFailure; }
+  //\}
+private:
+  /// link failure callback
+  Callback<void, Ipv4Address> m_handleLinkFailure;
+  /// TX error callback
+  Callback<void, WifiMacHeader const &> m_txErrorCallback;
+  /// Timer for neighbor's list. Schedule Purge().
+  Timer m_ntimer;
+  /// vector of entries
+  std::vector<Neighbor> m_nb;
+  /// list of ARP cached to be used for layer 2 notifications processing
+  std::vector<Ptr<ArpCache> > m_arp;
+  
+  /// Find MAC address by IP using list of ARP caches
+  Mac48Address LookupMacAddress (Ipv4Address);
+  /// Process layer 2 TX error notification
+  void ProcessTxError (WifiMacHeader const &);
+};
+
+}
+}
+
+#endif /* AODVNEIGHBOR_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-packet.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,580 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#include "aodv-packet.h"
+#include "ns3/address-utils.h"
+#include "ns3/packet.h"
+
+namespace ns3
+{
+namespace aodv
+{
+
+TypeHeader::TypeHeader (MessageType t) :
+  m_type (t), m_valid (true)
+{
+}
+
+TypeId
+TypeHeader::GetInstanceTypeId () const
+{
+  return TypeId ();
+}
+
+uint32_t
+TypeHeader::GetSerializedSize () const
+{
+  return 1;
+}
+
+void
+TypeHeader::Serialize (Buffer::Iterator i) const
+{
+  i.WriteU8 ((uint8_t) m_type);
+}
+
+uint32_t
+TypeHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  uint8_t type = i.ReadU8 ();
+  m_valid = true;
+  switch (type)
+    {
+    case AODVTYPE_RREQ:
+    case AODVTYPE_RREP:
+    case AODVTYPE_RERR:
+    case AODVTYPE_RREP_ACK:
+      {
+        m_type = (MessageType) type;
+        break;
+      }
+    default:
+      m_valid = false;
+    }
+  uint32_t dist = i.GetDistanceFrom (start);
+  NS_ASSERT (dist == GetSerializedSize ());
+  return dist;
+}
+
+void
+TypeHeader::Print (std::ostream &os) const
+{
+  switch (m_type)
+    {
+    case AODVTYPE_RREQ:
+      {
+        os << "RREQ" << "\n";
+        break;
+      }
+    case AODVTYPE_RREP:
+      {
+        os << "RREP" << "\n";
+        break;
+      }
+    case AODVTYPE_RERR:
+      {
+        os << "RERR" << "\n";
+        break;
+      }
+    case AODVTYPE_RREP_ACK:
+      {
+        os << "RREP_ACK" << "\n";
+        break;
+      }
+    default:
+      os << "UNKNOWN_TYPE";
+    }
+}
+
+bool
+TypeHeader::operator== (TypeHeader const & o) const
+{
+  return (m_type == o.m_type && m_valid == o.m_valid);
+}
+
+std::ostream &
+operator<< (std::ostream & os, TypeHeader const & h)
+{
+  h.Print (os);
+  return os;
+}
+
+//-----------------------------------------------------------------------------
+// RREQ
+//-----------------------------------------------------------------------------
+RreqHeader::RreqHeader (uint8_t flags, uint8_t reserved, uint8_t hopCount, uint32_t requestID, Ipv4Address dst,
+                        uint32_t dstSeqNo, Ipv4Address origin, uint32_t originSeqNo) :
+                       m_flags (flags), m_reserved (reserved), m_hopCount (hopCount), m_requestID (requestID), m_dst(dst),
+                       m_dstSeqNo (dstSeqNo), m_origin(origin),  m_originSeqNo (originSeqNo)
+{
+}
+
+TypeId
+RreqHeader::GetInstanceTypeId () const
+{
+  return TypeId ();
+}
+
+uint32_t
+RreqHeader::GetSerializedSize () const
+{
+  return 23;
+}
+
+void
+RreqHeader::Serialize (Buffer::Iterator i) const
+{
+  i.WriteU8 (m_flags);
+  i.WriteU8 (m_reserved);
+  i.WriteU8 (m_hopCount);
+  i.WriteHtonU32 (m_requestID);
+  WriteTo (i, m_dst);
+  i.WriteHtonU32 (m_dstSeqNo);
+  WriteTo (i, m_origin);
+  i.WriteHtonU32 (m_originSeqNo);
+}
+
+uint32_t
+RreqHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+  m_flags = i.ReadU8 ();
+  m_reserved = i.ReadU8 ();
+  m_hopCount = i.ReadU8 ();
+  m_requestID = i.ReadNtohU32 ();
+  ReadFrom (i, m_dst);
+  m_dstSeqNo = i.ReadNtohU32 ();
+  ReadFrom (i, m_origin);
+  m_originSeqNo = i.ReadNtohU32 ();
+
+  uint32_t dist = i.GetDistanceFrom (start);
+  NS_ASSERT (dist == GetSerializedSize ());
+  return dist;
+}
+
+void
+RreqHeader::Print (std::ostream &os) const
+{
+  os << "RREQ ID " << m_requestID << "\n" << "destination: ipv4 " << m_dst
+      << " " << "sequence number " << m_dstSeqNo << "\n" << "source: ipv4 "
+      << m_origin << " " << "sequence number " << m_originSeqNo << "\n"
+      << "flags:\n" << "Gratuitous RREP " << (*this).GetGratiousRrep () << "\n"
+      << "Destination only " << (*this).GetDestinationOnly () << "\n"
+      << "Unknown sequence number " << (*this).GetUnknownSeqno () << "\n";
+}
+
+std::ostream &
+operator<< (std::ostream & os, RreqHeader const & h)
+{
+  h.Print (os);
+  return os;
+}
+
+void
+RreqHeader::SetGratiousRrep (bool f)
+{
+  if (f)
+    m_flags |= (1 << 5);
+  else
+    m_flags &= ~(1 << 5);
+}
+
+bool
+RreqHeader::GetGratiousRrep () const
+{
+  return (m_flags & (1 << 5));
+}
+
+void
+RreqHeader::SetDestinationOnly (bool f)
+{
+  if (f)
+    m_flags |= (1 << 4);
+  else
+    m_flags &= ~(1 << 4);
+}
+
+bool
+RreqHeader::GetDestinationOnly () const
+{
+  return (m_flags & (1 << 4));
+}
+
+void
+RreqHeader::SetUnknownSeqno (bool f)
+{
+  if (f)
+    m_flags |= (1 << 3);
+  else
+    m_flags &= ~(1 << 3);
+}
+
+bool
+RreqHeader::GetUnknownSeqno () const
+{
+  return (m_flags & (1 << 3));
+}
+
+bool
+RreqHeader::operator== (RreqHeader const & o) const
+{
+  return (m_flags == o.m_flags && m_reserved == o.m_reserved &&
+          m_hopCount == o.m_hopCount && m_requestID == o.m_requestID &&
+          m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo &&
+          m_origin == o.m_origin && m_originSeqNo == o.m_originSeqNo);
+}
+
+//-----------------------------------------------------------------------------
+// RREP
+//-----------------------------------------------------------------------------
+
+RrepHeader::RrepHeader (uint8_t prefixSize, uint8_t hopCount, Ipv4Address dst,
+                        uint32_t dstSeqNo, Ipv4Address origin, Time lifeTime) :
+                        m_flags (0), m_prefixSize (prefixSize), m_hopCount (hopCount),
+                        m_dst (dst), m_dstSeqNo (dstSeqNo), m_origin (origin)
+{
+  m_lifeTime = uint32_t (lifeTime.GetMilliSeconds ());
+}
+
+TypeId
+RrepHeader::GetInstanceTypeId () const
+{
+  return TypeId ();
+}
+
+uint32_t
+RrepHeader::GetSerializedSize () const
+{
+  return 19;
+}
+
+void
+RrepHeader::Serialize (Buffer::Iterator i) const
+{
+  i.WriteU8 (m_flags);
+  i.WriteU8 (m_prefixSize);
+  i.WriteU8 (m_hopCount);
+  WriteTo (i, m_dst);
+  i.WriteHtonU32 (m_dstSeqNo);
+  WriteTo (i, m_origin);
+  i.WriteHtonU32 (m_lifeTime);
+}
+
+uint32_t
+RrepHeader::Deserialize (Buffer::Iterator start)
+{
+  Buffer::Iterator i = start;
+
+  m_flags = i.ReadU8 ();
+  m_prefixSize = i.ReadU8 ();
+  m_hopCount = i.ReadU8 ();
+  ReadFrom (i, m_dst);
+  m_dstSeqNo = i.ReadNtohU32 ();
+  ReadFrom (i, m_origin);
+  m_lifeTime = i.ReadNtohU32 ();
+
+  uint32_t dist = i.GetDistanceFrom (start);
+  NS_ASSERT (dist == GetSerializedSize ());
+  return dist;
+}
+
+void
+RrepHeader::Print (std::ostream &os) const
+{
+  os << "destination: ipv4 " << m_dst << "sequence number " << m_dstSeqNo;
+  if (m_prefixSize != 0)
+    os << "prefix size " << m_prefixSize << "\n";
+  else
+    os << "\n";
+  os << "source ipv4 " << m_origin << "\n" << "life time " << m_lifeTime
+      << "\n" << "acknowledgment required flag " << (*this).GetAckRequired ()
+      << "\n";
+}
+
+void
+RrepHeader::SetLifeTime (Time t)
+{
+  m_lifeTime = t.GetMilliSeconds ();
+}
+
+Time
+RrepHeader::GetLifeTime () const
+{
+  Time t (MilliSeconds (m_lifeTime));
+  return t;
+}
+
+void
+RrepHeader::SetAckRequired (bool f)
+{
+  if (f)
+    m_flags |= (1 << 6);
+  else
+    m_flags &= ~(1 << 6);
+}
+
+bool
+RrepHeader::GetAckRequired () const
+{
+  return (m_flags & (1 << 6));
+}
+
+void
+RrepHeader::SetPrefixSize (uint8_t sz)
+{
+  m_prefixSize = sz;
+}
+
+uint8_t
+RrepHeader::GetPrefixSize () const
+{
+  return m_prefixSize;
+}
+
+bool
+RrepHeader::operator== (RrepHeader const & o) const
+{
+  return (m_flags == o.m_flags && m_prefixSize == o.m_prefixSize &&
+          m_hopCount == o.m_hopCount && m_dst == o.m_dst && m_dstSeqNo == o.m_dstSeqNo &&
+          m_origin == o.m_origin && m_lifeTime == o.m_lifeTime);
+}
+
+void
+RrepHeader::SetHello (Ipv4Address origin, uint32_t srcSeqNo, Time lifetime)
+{
+  m_flags = 0;
+  m_prefixSize = 0;
+  m_hopCount = 0;
+  m_dst = origin;
+  m_dstSeqNo = srcSeqNo;
+  m_origin = origin;
+  m_lifeTime = lifetime.GetMilliSeconds ();
+}
+
+std::ostream &
+operator<< (std::ostream & os, RrepHeader const & h)
+{
+  h.Print (os);
+  return os;
+}
+
+//-----------------------------------------------------------------------------
+// RREP-ACK
+//-----------------------------------------------------------------------------
+
+RrepAckHeader::RrepAckHeader () :
+  m_reserved (0)
+{
+}
+
+TypeId
+RrepAckHeader::GetInstanceTypeId () const
+{
+  return TypeId ();
+}
+
+uint32_t
+RrepAckHeader::GetSerializedSize () const
+{
+  return 1;
+}
+
+void
+RrepAckHeader::Serialize (Buffer::Iterator i ) const
+{
+  i.WriteU8 (m_reserved);
+}
+
+uint32_t
+RrepAckHeader::Deserialize (Buffer::Iterator start )
+{
+  Buffer::Iterator i = start;
+  m_reserved = i.ReadU8 ();
+  uint32_t dist = i.GetDistanceFrom (start);
+  NS_ASSERT (dist == GetSerializedSize ());
+  return dist;
+}
+
+void
+RrepAckHeader::Print (std::ostream &os ) const
+{
+}
+
+bool
+RrepAckHeader::operator== (RrepAckHeader const & o ) const
+{
+  return m_reserved == o.m_reserved;
+}
+
+std::ostream &
+operator<< (std::ostream & os, RrepAckHeader const & h )
+{
+  h.Print (os);
+  return os;
+}
+
+//-----------------------------------------------------------------------------
+// RERR
+//-----------------------------------------------------------------------------
+RerrHeader::RerrHeader () :
+  m_flag (0), m_reserved (0)
+{
+}
+
+TypeId
+RerrHeader::GetInstanceTypeId () const
+{
+  return TypeId ();
+}
+
+uint32_t
+RerrHeader::GetSerializedSize () const
+{
+  return (3 + 8 * GetDestCount ());
+}
+
+void
+RerrHeader::Serialize (Buffer::Iterator i ) const
+{
+  i.WriteU8 (m_flag);
+  i.WriteU8 (m_reserved);
+  i.WriteU8 (GetDestCount ());
+  std::map<Ipv4Address, uint32_t>::const_iterator j;
+  for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j)
+    {
+      WriteTo (i, (*j).first);
+      i.WriteHtonU32 ((*j).second);
+    }
+}
+
+uint32_t
+RerrHeader::Deserialize (Buffer::Iterator start )
+{
+  Buffer::Iterator i = start;
+  m_flag = i.ReadU8 ();
+  m_reserved = i.ReadU8 ();
+  uint8_t dest = i.ReadU8 ();
+  m_unreachableDstSeqNo.clear ();
+  Ipv4Address address;
+  uint32_t seqNo;
+  for (uint8_t k = 0; k < dest; ++k)
+    {
+      ReadFrom (i, address);
+      seqNo = i.ReadNtohU32 ();
+      m_unreachableDstSeqNo.insert (std::make_pair (address, seqNo));
+    }
+
+  uint32_t dist = i.GetDistanceFrom (start);
+  NS_ASSERT (dist == GetSerializedSize ());
+  return dist;
+}
+
+void
+RerrHeader::Print (std::ostream &os ) const
+{
+  os << "Unreachable destination (ipv4 address, seq. number):\n";
+  std::map<Ipv4Address, uint32_t>::const_iterator j;
+  for (j = m_unreachableDstSeqNo.begin (); j != m_unreachableDstSeqNo.end (); ++j)
+    {
+      os << (*j).first << ", " << (*j).second << "\n";
+    }
+  os << "No delete flag " << (*this).GetNoDelete () << "\n";
+}
+
+void
+RerrHeader::SetNoDelete (bool f )
+{
+  if (f)
+    m_flag |= (1 << 0);
+  else
+    m_flag &= ~(1 << 0);
+}
+
+bool
+RerrHeader::GetNoDelete () const
+{
+  return (m_flag & (1 << 0));
+}
+
+bool
+RerrHeader::AddUnDestination (Ipv4Address dst, uint32_t seqNo )
+{
+  if (m_unreachableDstSeqNo.find (dst) != m_unreachableDstSeqNo.end ())
+    return true;
+
+  NS_ASSERT (GetDestCount() < 255); // can't support more than 255 destinations in single RERR
+  m_unreachableDstSeqNo.insert (std::make_pair (dst, seqNo));
+  return true;
+}
+
+bool
+RerrHeader::RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un )
+{
+  if (m_unreachableDstSeqNo.empty ())
+    return false;
+  std::map<Ipv4Address, uint32_t>::iterator i = m_unreachableDstSeqNo.begin ();
+  un = *i;
+  m_unreachableDstSeqNo.erase (i);
+  return true;
+}
+
+void
+RerrHeader::Clear ()
+{
+  m_unreachableDstSeqNo.clear ();
+  m_flag = 0;
+  m_reserved = 0;
+}
+
+bool
+RerrHeader::operator== (RerrHeader const & o ) const
+{
+  if (m_flag != o.m_flag || m_reserved != o.m_reserved || GetDestCount () != o.GetDestCount ())
+    return false;
+
+  std::map<Ipv4Address, uint32_t>::const_iterator j = m_unreachableDstSeqNo.begin ();
+  std::map<Ipv4Address, uint32_t>::const_iterator k = o.m_unreachableDstSeqNo.begin ();
+  for (uint8_t i = 0; i < GetDestCount (); ++i)
+    {
+      if ((j->first != k->first) || (j->second != k->second))
+        return false;
+
+      j++;
+      k++;
+    }
+  return true;
+}
+
+std::ostream &
+operator<< (std::ostream & os, RerrHeader const & h )
+{
+  h.Print (os);
+  return os;
+}
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-packet.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,330 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#ifndef AODVPACKET_H
+#define AODVPACKET_H
+
+#include <iostream>
+#include "ns3/header.h"
+#include "ns3/enum.h"
+#include "ns3/ipv4-address.h"
+#include <map>
+#include "ns3/nstime.h"
+
+namespace ns3 {
+namespace aodv {
+
+enum MessageType
+{
+  AODVTYPE_RREQ  = 1,   //!< AODVTYPE_RREQ
+  AODVTYPE_RREP  = 2,   //!< AODVTYPE_RREP
+  AODVTYPE_RERR  = 3,   //!< AODVTYPE_RERR
+  AODVTYPE_RREP_ACK = 4 //!< AODVTYPE_RREP_ACK
+};
+
+/**
+* \ingroup aodv
+* \brief AODV types
+*/
+class TypeHeader : public Header
+{
+public:
+  /// c-tor
+  TypeHeader (MessageType t);
+
+  ///\name Header serialization/deserialization
+  //\{
+  TypeId GetInstanceTypeId () const;
+  uint32_t GetSerializedSize () const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  void Print (std::ostream &os) const;
+  //\}
+
+  /// Return type
+  MessageType Get () const { return m_type; }
+  /// Check that type if valid
+  bool IsValid () const { return m_valid; }
+  bool operator== (TypeHeader const & o) const;
+private:
+  MessageType m_type;
+  bool m_valid;
+};
+
+std::ostream & operator<< (std::ostream & os, TypeHeader const & h);
+
+/**
+* \ingroup aodv
+* \brief   Route Request (RREQ) Message Format
+  \verbatim
+  0                   1                   2                   3
+  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |     Type      |J|R|G|D|U|   Reserved          |   Hop Count   |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                            RREQ ID                            |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                    Destination IP Address                     |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                  Destination Sequence Number                  |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                    Originator IP Address                      |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                  Originator Sequence Number                   |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+class RreqHeader : public Header 
+{
+public:
+  /// c-tor
+  RreqHeader (uint8_t flags = 0, uint8_t reserved = 0, uint8_t hopCount = 0,
+      uint32_t requestID = 0, Ipv4Address dst = Ipv4Address (),
+      uint32_t dstSeqNo = 0, Ipv4Address origin = Ipv4Address (),
+      uint32_t originSeqNo = 0);
+
+  ///\name Header serialization/deserialization
+  //\{
+  TypeId GetInstanceTypeId () const;
+  uint32_t GetSerializedSize () const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  void Print (std::ostream &os) const;
+  //\}
+
+  ///\name Fields
+  //\{
+  void SetHopCount (uint8_t count) { m_hopCount = count; }
+  uint8_t GetHopCount () const { return m_hopCount; }
+  void SetId (uint32_t id) { m_requestID = id; }
+  uint8_t GetId () const { return m_requestID; }
+  void SetDst (Ipv4Address a) { m_dst = a; }
+  Ipv4Address GetDst () const { return m_dst; }
+  void SetDstSeqno (uint32_t s) { m_dstSeqNo = s; }
+  uint32_t GetDstSeqno () const { return m_dstSeqNo; }
+  void SetOrigin (Ipv4Address a) { m_origin = a; }
+  Ipv4Address GetOrigin () const { return m_origin; }
+  void SetOriginSeqno (uint32_t s) { m_originSeqNo = s; }
+  uint32_t GetOriginSeqno () const { return m_originSeqNo; }
+  //\}
+
+  ///\name Flags
+  //\{
+  void SetGratiousRrep (bool f);
+  bool GetGratiousRrep () const;
+  void SetDestinationOnly (bool f);
+  bool GetDestinationOnly () const;
+  void SetUnknownSeqno (bool f);
+  bool GetUnknownSeqno () const;
+  //\}
+
+  bool operator== (RreqHeader const & o) const;
+private:
+  uint8_t        m_flags;          ///< |J|R|G|D|U| bit flags, see RFC
+  uint8_t        m_reserved;       ///< Not used
+  uint8_t        m_hopCount;       ///< Hop Count
+  uint32_t       m_requestID;      ///< RREQ ID
+  Ipv4Address    m_dst;            ///< Destination IP Address
+  uint32_t       m_dstSeqNo;       ///< Destination Sequence Number
+  Ipv4Address    m_origin;         ///< Originator IP Address
+  uint32_t       m_originSeqNo;    ///< Source Sequence Number
+};
+
+std::ostream & operator<< (std::ostream & os, RreqHeader const &);
+
+/**
+* \ingroup aodv
+* \brief Route Reply (RREP) Message Format
+  \verbatim
+  0                   1                   2                   3
+  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |     Type      |R|A|    Reserved     |Prefix Sz|   Hop Count   |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                     Destination IP address                    |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                  Destination Sequence Number                  |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                    Originator IP address                      |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |                           Lifetime                            |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+class RrepHeader : public Header
+{
+public:
+  /// c-tor
+  RrepHeader (uint8_t prefixSize = 0, uint8_t hopCount = 0, Ipv4Address dst =
+      Ipv4Address (), uint32_t dstSeqNo = 0, Ipv4Address origin =
+      Ipv4Address (), Time lifetime = MilliSeconds (0));
+  ///\name Header serialization/deserialization
+  //\{
+  TypeId GetInstanceTypeId () const;
+  uint32_t GetSerializedSize () const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  void Print (std::ostream &os) const;
+  //\}
+
+  ///\name Fields
+  //\{
+  void SetHopCount (uint8_t count) { m_hopCount = count; }
+  uint8_t GetHopCount () const { return m_hopCount; }
+  void SetDst (Ipv4Address a) { m_dst = a; }
+  Ipv4Address GetDst () const { return m_dst; }
+  void SetDstSeqno (uint32_t s) { m_dstSeqNo = s; }
+  uint32_t GetDstSeqno () const { return m_dstSeqNo; }
+  void SetOrigin (Ipv4Address a) { m_origin = a; }
+  Ipv4Address GetOrigin () const { return m_origin; }
+  void SetLifeTime (Time t);
+  Time GetLifeTime () const;
+  //\}
+
+  ///\name Flags
+  //\{
+  void SetAckRequired (bool f);
+  bool GetAckRequired () const;
+  void SetPrefixSize (uint8_t sz);
+  uint8_t GetPrefixSize () const;
+  //\}
+
+  /// Configure RREP to be a Hello message
+  void SetHello (Ipv4Address src, uint32_t srcSeqNo, Time lifetime);
+
+  bool operator== (RrepHeader const & o) const;
+private:
+  uint8_t       m_flags;	          ///< A - acknowledgment required flag
+  uint8_t       m_prefixSize;	      ///< Prefix Size
+  uint8_t	      m_hopCount;         ///< Hop Count
+  Ipv4Address   m_dst;              ///< Destination IP Address
+  uint32_t      m_dstSeqNo;         ///< Destination Sequence Number
+  Ipv4Address	  m_origin;           ///< Source IP Address
+  uint32_t      m_lifeTime;         ///< Lifetime (in milliseconds)
+};
+
+std::ostream & operator<< (std::ostream & os, RrepHeader const &);
+
+/**
+* \ingroup aodv
+* \brief Route Reply Acknowledgment (RREP-ACK) Message Format
+  \verbatim
+  0                   1
+  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |     Type      |   Reserved    |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+class RrepAckHeader : public Header
+{
+public:
+  /// c-tor
+  RrepAckHeader ();
+
+  ///\name Header serialization/deserialization
+  //\{
+  TypeId GetInstanceTypeId () const;
+  uint32_t GetSerializedSize () const;
+  void Serialize (Buffer::Iterator start) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  void Print (std::ostream &os) const;
+  //\}
+
+  bool operator== (RrepAckHeader const & o) const;
+private:
+  uint8_t       m_reserved;
+};
+std::ostream & operator<< (std::ostream & os, RrepAckHeader const &);
+
+
+/**
+* \ingroup aodv
+* \brief Route Error (RERR) Message Format
+  \verbatim
+  0                   1                   2                   3
+  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |     Type      |N|          Reserved           |   DestCount   |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |            Unreachable Destination IP Address (1)             |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |         Unreachable Destination Sequence Number (1)           |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
+  |  Additional Unreachable Destination IP Addresses (if needed)  |
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  |Additional Unreachable Destination Sequence Numbers (if needed)|
+  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+  \endverbatim
+*/
+class RerrHeader : public Header
+{
+public:
+  /// c-tor
+  RerrHeader ();
+
+  ///\name Header serialization/deserialization
+  //\{
+  TypeId GetInstanceTypeId () const;
+  uint32_t GetSerializedSize () const;
+  void Serialize (Buffer::Iterator i) const;
+  uint32_t Deserialize (Buffer::Iterator start);
+  void Print (std::ostream &os) const;
+  //\}
+
+  ///\name No delete flag
+  //\{
+  void SetNoDelete (bool f);
+  bool GetNoDelete () const;
+  //\}
+
+  /**
+   * Add unreachable node address and its sequence number in RERR header
+   *\return false if we already added maximum possible number of unreachable destinations
+   */
+  bool AddUnDestination (Ipv4Address dst, uint32_t seqNo);
+  /** Delete pair (address + sequence number) from REER header, if the number of unreachable destinations > 0
+   * \return true on success
+   */
+  bool RemoveUnDestination (std::pair<Ipv4Address, uint32_t> & un);
+  /// Clear header
+  void Clear();
+  /// Return number of unreachable destinations in RERR message
+  uint8_t GetDestCount () const { return (uint8_t)m_unreachableDstSeqNo.size(); }
+  bool operator== (RerrHeader const & o) const;
+private:
+  uint8_t m_flag;            ///< No delete flag
+  uint8_t m_reserved;        ///< Not used
+
+  /// List of Unreachable destination: IP addresses and sequence numbers
+  std::map<Ipv4Address, uint32_t> m_unreachableDstSeqNo;
+};
+
+std::ostream & operator<< (std::ostream & os, RerrHeader const &);
+}
+}
+#endif /* AODVPACKET_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-routing-protocol.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,1498 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#include "aodv-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/adhoc-wifi-mac.h"
+#include <algorithm>
+
+NS_LOG_COMPONENT_DEFINE ("AodvRoutingProtocol");
+
+namespace ns3
+{
+namespace aodv
+{
+NS_OBJECT_ENSURE_REGISTERED (RoutingProtocol);
+
+/// UDP Port for AODV control traffic
+const uint32_t RoutingProtocol::AODV_PORT = 654;
+
+RoutingProtocol::RoutingProtocol () :
+  RreqRetries (2),
+  RreqRateLimit (10),
+  ActiveRouteTimeout (Seconds (3)),
+  NetDiameter (35),
+  NodeTraversalTime (MilliSeconds (40)),
+  NetTraversalTime (Scalar (2 * NetDiameter) * NodeTraversalTime),
+  PathDiscoveryTime ( Scalar (2) * NetTraversalTime),
+  MyRouteTimeout (Scalar (2) * std::max (PathDiscoveryTime, ActiveRouteTimeout)),
+  HelloInterval(Seconds (1)),
+  AllowedHelloLoss (2),
+  DeletePeriod (Scalar(5) * std::max(ActiveRouteTimeout, HelloInterval)),
+  NextHopWait (NodeTraversalTime + MilliSeconds (10)),
+  TimeoutBuffer (2),
+  BlackListTimeout(Scalar (RreqRetries) * NetTraversalTime),
+  MaxQueueLen (64),
+  MaxQueueTime (Seconds(30)),
+  DestinationOnly (false),
+  GratuitousReply (true),
+  EnableHello (true),
+  m_routingTable (DeletePeriod),
+  m_queue (MaxQueueLen, MaxQueueTime),
+  m_requestId (0),
+  m_seqNo (0),
+  m_rreqIdCache (PathDiscoveryTime),
+  m_dpd (PathDiscoveryTime),
+  m_nb(HelloInterval),
+  m_rreqCount (0),
+  m_htimer (Timer::CANCEL_ON_DESTROY),
+  m_rreqRateLimitTimer (Timer::CANCEL_ON_DESTROY)
+{
+  if (EnableHello)
+    {
+      m_nb.SetCallback (MakeCallback (&RoutingProtocol::SendRerrWhenBreaksLinkToNextHop, this));
+    }
+}
+
+TypeId
+RoutingProtocol::GetTypeId (void)
+{
+  static TypeId tid = TypeId ("ns3::aodv::RoutingProtocol")
+      .SetParent<Ipv4RoutingProtocol> ()
+      .AddConstructor<RoutingProtocol> ()
+      .AddAttribute ("HelloInterval", "HELLO messages emission interval.",
+                     TimeValue (Seconds (1)),
+                     MakeTimeAccessor (&RoutingProtocol::HelloInterval),
+                     MakeTimeChecker ())
+      .AddAttribute ("RreqRetries", "Maximum number of retransmissions of RREQ to discover a route",
+                     UintegerValue (2),
+                     MakeUintegerAccessor (&RoutingProtocol::RreqRetries),
+                     MakeUintegerChecker<uint32_t> ())
+      .AddAttribute ("RreqRateLimit", "Maximum number of RREQ per second.",
+                     UintegerValue (10),
+                     MakeUintegerAccessor (&RoutingProtocol::RreqRateLimit),
+                     MakeUintegerChecker<uint32_t> ())
+      .AddAttribute ("NodeTraversalTime", "Conservative estimate of the average one hop traversal time for packets and should include "
+                     "queuing delays, interrupt processing times and transfer times.",
+                     TimeValue (MilliSeconds (40)),
+                     MakeTimeAccessor (&RoutingProtocol::NodeTraversalTime),
+                     MakeTimeChecker ())
+      .AddAttribute ("NextHopWait", "Period of our waiting for the neighbour's RREP_ACK = 10 ms + NodeTraversalTime",
+                     TimeValue (MilliSeconds (50)),
+                     MakeTimeAccessor (&RoutingProtocol::NextHopWait),
+                     MakeTimeChecker ())
+      .AddAttribute ("ActiveRouteTimeout", "Period of time during which the route is considered to be valid",
+                     TimeValue (Seconds (3)),
+                     MakeTimeAccessor (&RoutingProtocol::ActiveRouteTimeout),
+                     MakeTimeChecker ())
+      .AddAttribute ("MyRouteTimeout", "Value of lifetime field in RREP generating by this node = 2 * max(ActiveRouteTimeout, PathDiscoveryTime)",
+                     TimeValue (Seconds (11.2)),
+                     MakeTimeAccessor (&RoutingProtocol::MyRouteTimeout),
+                     MakeTimeChecker ())
+      .AddAttribute ("BlackListTimeout", "Time for which the node is put into the blacklist = RreqRetries * NetTraversalTime",
+                     TimeValue (Seconds (5.6)),
+                     MakeTimeAccessor (&RoutingProtocol::BlackListTimeout),
+                     MakeTimeChecker ())
+      .AddAttribute ("DeletePeriod", "DeletePeriod is intended to provide an upper bound on the time for which an upstream node A "
+                     "can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D."
+                     " = 5 * max (HelloInterval, ActiveRouteTimeout)",
+                     TimeValue (Seconds (15)),
+                     MakeTimeAccessor (&RoutingProtocol::DeletePeriod),
+                     MakeTimeChecker ())
+      .AddAttribute ("TimeoutBuffer", "Its purpose is to provide a buffer for the timeout so that if the RREP is delayed"
+                     " due to congestion, a timeout is less likely to occur while the RREP is still en route back to the source.",
+                     UintegerValue (2),
+                     MakeUintegerAccessor (&RoutingProtocol::TimeoutBuffer),
+                     MakeUintegerChecker<uint16_t> ())
+      .AddAttribute ("NetDiameter", "Net diameter measures the maximum possible number of hops between two nodes in the network",
+                     UintegerValue (35),
+                     MakeUintegerAccessor (&RoutingProtocol::NetDiameter),
+                     MakeUintegerChecker<uint32_t> ())
+      .AddAttribute ("NetTraversalTime", "Estimate of the average net traversal time = 2 * NodeTraversalTime * NetDiameter",
+                     TimeValue (Seconds (2.8)),
+                     MakeTimeAccessor (&RoutingProtocol::NetTraversalTime),
+                     MakeTimeChecker ())
+      .AddAttribute ("PathDiscoveryTime", "Estimate of maximum time needed to find route in network = 2 * NetTraversalTime",
+                     TimeValue (Seconds (5.6)),
+                     MakeTimeAccessor (&RoutingProtocol::PathDiscoveryTime),
+                     MakeTimeChecker ())
+      .AddAttribute ("MaxQueueLen", "Maximum number of packets that we allow a routing protocol to buffer.",
+                     UintegerValue (64),
+                     MakeUintegerAccessor (&RoutingProtocol::MaxQueueLen),
+                     MakeUintegerChecker<uint32_t> ())
+      .AddAttribute ("MaxQueueTime", "Maximum time packets can be queued (in seconds)",
+                     TimeValue (Seconds (30)),
+                     MakeTimeAccessor (&RoutingProtocol::MaxQueueTime),
+                     MakeTimeChecker ())
+      .AddAttribute ("AllowedHelloLoss", "Number of hello messages which may be loss for valid link.",
+                     UintegerValue (2),
+                     MakeUintegerAccessor (&RoutingProtocol::AllowedHelloLoss),
+                     MakeUintegerChecker<uint16_t> ())
+      .AddAttribute ("GratuitousReply", "Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.",
+                     BooleanValue (true),
+                     MakeBooleanAccessor (&RoutingProtocol::SetGratuitousReplyFlag,
+                                          &RoutingProtocol::GetGratuitousReplyFlag),
+                     MakeBooleanChecker ())
+      .AddAttribute ("DestinationOnly", "Indicates only the destination may respond to this RREQ.",
+                     BooleanValue (false),
+                     MakeBooleanAccessor (&RoutingProtocol::SetDesinationOnlyFlag,
+                                          &RoutingProtocol::GetDesinationOnlyFlag),
+                     MakeBooleanChecker ())
+      .AddAttribute ("EnableHello", "Indicates whether a hello messages enable.",
+                     BooleanValue (true),
+                     MakeBooleanAccessor (&RoutingProtocol::SetHelloEnable,
+                                          &RoutingProtocol::GetHelloEnable),
+                     MakeBooleanChecker ())
+      .AddAttribute ("EnableBroadcast", "Indicates whether a broadcast data packets forwarding enable.",
+                     BooleanValue (true),
+                     MakeBooleanAccessor (&RoutingProtocol::SetBroadcastEnable,
+                                          &RoutingProtocol::GetBroadcastEnable),
+                     MakeBooleanChecker ())
+  ;
+  return tid;
+}
+
+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::Start ()
+{
+  m_scb = MakeCallback (&RoutingProtocol::Send, this);
+  m_ecb = MakeCallback (&RoutingProtocol::Drop, this);
+
+  if (EnableHello)
+    {
+      m_nb.ScheduleTimer ();
+    }
+  m_rreqRateLimitTimer.SetFunction (&RoutingProtocol::RreqRateLimitTimerExpire,
+      this);
+  m_rreqRateLimitTimer.Schedule (Seconds (1));
+}
+
+Ptr<Ipv4Route>
+RoutingProtocol::RouteOutput (Ptr<Packet> p, const Ipv4Header &header,
+    uint32_t oif, Socket::SocketErrno &sockerr)
+{
+  NS_LOG_FUNCTION (this << header.GetDestination ());
+  if (m_socketAddresses.empty ())
+    {
+      sockerr = Socket::ERROR_NOROUTETOHOST;
+      NS_LOG_LOGIC ("No aodv interfaces");
+      Ptr<Ipv4Route> route;
+      return route;
+    }
+  sockerr = Socket::ERROR_NOTERROR;
+  Ptr<Ipv4Route> route;
+  Ipv4Address dst = header.GetDestination ();
+  RoutingTableEntry rt;
+  if (m_routingTable.LookupRoute (dst, rt))
+    {
+      if (rt.GetFlag () == VALID)
+        {
+          route = rt.GetRoute ();
+          NS_ASSERT (route != 0);
+          NS_LOG_LOGIC("exist route to " << route->GetDestination() << " from interface " << route->GetSource());
+          UpdateRouteLifeTime (dst, ActiveRouteTimeout);
+          UpdateRouteLifeTime (route->GetGateway (), ActiveRouteTimeout);
+        }
+      else
+        {
+          bool result = true;
+          // May be null pointer (e.g. tcp-socket give null pointer)
+          if (p != Ptr<Packet> ())
+            {
+              QueueEntry newEntry (p, header, m_scb, m_ecb);
+              result = m_queue.Enqueue (newEntry);
+              if (result)
+                NS_LOG_LOGIC ("Add packet " << p->GetUid() << " to queue");
+
+            }
+          if ((rt.GetFlag () == INVALID) && result)
+            {
+              SendRequest (dst);
+            }
+        }
+    }
+  else
+    {
+      bool result = true;
+      if (p != Ptr<Packet> ())
+        {
+          QueueEntry newEntry (p, header, m_scb, m_ecb);
+          // Some protocols may ask route several times for a single packet.
+          result = m_queue.Enqueue (newEntry);
+          if (result)
+            NS_LOG_LOGIC ("Add packet " << p->GetUid() << " to queue. Protocol " << (uint16_t) header.GetProtocol ());
+        }
+      if (result)
+        SendRequest (dst);
+    }
+  return route;
+}
+
+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 (this << p->GetUid() << header.GetDestination() << idev->GetAddress());
+  if (m_socketAddresses.empty ())
+    {
+      NS_LOG_LOGIC ("No aodv 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 ();
+
+  if (IsMyOwnAddress (origin))
+    return true;
+
+  // Local delivery to AODV 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 ())
+          {
+            if (!EnableBroadcast)
+              {
+                return true;
+              }
+            if (m_dpd.IsDuplicate (p, header))
+              {
+                NS_LOG_DEBUG ("Duplicated packet " << p->GetUid () << " from " << origin << ". Drop.");
+                return true;
+              }
+            UpdateRouteLifeTime (origin, ActiveRouteTimeout);
+            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))
+                  {
+                    Ptr<Ipv4Route> route = toBroadcast.GetRoute ();
+                    ucb (route, packet, header);
+                  }
+                else
+                  {
+                    NS_LOG_DEBUG ("No route to forward broadcast. Drop packet " << p->GetUid ());
+                  }
+              }
+            else
+              {
+                NS_LOG_DEBUG ("TTL exceeded. Drop packet " << p->GetUid ());
+              }
+            return true;
+          }
+    }
+  for (std::map<Ptr<Socket> , Ipv4InterfaceAddress>::const_iterator j =
+      m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
+    {
+      Ipv4InterfaceAddress iface = j->second;
+      if (dst == iface.GetLocal ())
+        {
+          UpdateRouteLifeTime (origin, ActiveRouteTimeout);
+          RoutingTableEntry toOrigin;
+          if (m_routingTable.LookupRoute (origin, toOrigin))
+            {
+              UpdateRouteLifeTime (toOrigin.GetNextHop (), ActiveRouteTimeout);
+              m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
+            }
+          NS_LOG_LOGIC ("Unicast local delivery to " << iface.GetLocal ());
+          lcb (p, header, iif);
+          return true;
+        }
+    }
+
+  // Forwarding
+  return Forwarding (p, header, ucb, ecb);
+}
+
+bool
+RoutingProtocol::Forwarding (Ptr<const Packet> p, const Ipv4Header & header,
+    UnicastForwardCallback ucb, ErrorCallback ecb)
+{
+  Ipv4Address dst = header.GetDestination ();
+  Ipv4Address origin = header.GetSource ();
+  m_routingTable.Purge ();
+  RoutingTableEntry toDst;
+  if (m_routingTable.LookupRoute (dst, toDst))
+    {
+      if (toDst.GetFlag () == VALID)
+        {
+          Ptr<Ipv4Route> route = toDst.GetRoute ();
+          NS_LOG_LOGIC (route->GetSource()<<" forwarding to " << dst << " from " << origin << " packet " << p->GetUid ());
+
+          /*
+           *  Each time a route is used to forward a data packet, its Active Route
+           *  Lifetime field of the source, destination and the next hop on the
+           *  path to the destination is updated to be no less than the current
+           *  time plus ActiveRouteTimeout.
+           */
+          UpdateRouteLifeTime (origin, ActiveRouteTimeout);
+          UpdateRouteLifeTime (dst, ActiveRouteTimeout);
+          UpdateRouteLifeTime (route->GetGateway (), ActiveRouteTimeout);
+          /*
+           *  Since the route between each originator and destination pair is expected to be symmetric, the
+           *  Active Route Lifetime for the previous hop, along the reverse path back to the IP source, is also updated
+           *  to be no less than the current time plus ActiveRouteTimeout
+           */
+          RoutingTableEntry toOrigin;
+          m_routingTable.LookupRoute (origin, toOrigin);
+          UpdateRouteLifeTime (toOrigin.GetNextHop (), ActiveRouteTimeout);
+
+          m_nb.Update (route->GetGateway (), ActiveRouteTimeout);
+          m_nb.Update (toOrigin.GetNextHop (), ActiveRouteTimeout);
+
+          ucb (route, p, header);
+          return true;
+        }
+      else
+        {
+          if (toDst.GetValidSeqNo ())
+            {
+              SendRerrWhenNoRouteToForward (dst, toDst.GetSeqNo (), origin);
+              NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");
+              return false;
+            }
+        }
+    }
+  NS_LOG_LOGIC ("route not found to "<< dst << ". Send RERR message.");
+  NS_LOG_DEBUG ("Drop packet " << p->GetUid () << " because no route to forward it.");
+  SendRerrWhenNoRouteToForward (dst, 0, origin);
+  return false;
+}
+
+void
+RoutingProtocol::SetIpv4 (Ptr<Ipv4> ipv4)
+{
+  NS_ASSERT (ipv4 != 0);
+  NS_ASSERT (m_ipv4 == 0);
+
+  if (EnableHello)
+    {
+      m_htimer.SetFunction (&RoutingProtocol::HelloTimerExpire, this);
+      m_htimer.Schedule (MilliSeconds (UniformVariable ().GetInteger (0, 100)));
+    }
+
+  m_ipv4 = ipv4;
+  Simulator::ScheduleNow (&RoutingProtocol::Start, this);
+}
+
+void
+RoutingProtocol::NotifyInterfaceUp (uint32_t i)
+{
+  NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());
+  Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+  if (l3->GetNAddresses (i) > 1)
+    {
+      NS_LOG_WARN ("AODV does not work with more then one address per each interface.");
+    }
+  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::RecvAodv, this));
+  socket->Bind (InetSocketAddress (iface.GetLocal (), AODV_PORT));
+  socket->Connect (InetSocketAddress (iface.GetBroadcast (), AODV_PORT));
+  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 (), /*know seqno=*/true, /*seqno=*/0, /*iface=*/iface,
+                        /*hops=*/1, /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Simulator::GetMaximumSimulationTime ());
+  m_routingTable.AddRoute (rt);
+  
+  // Allow neighbor manager use this interface for layer 2 feedback if possible
+  Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
+  if (wifi == 0)
+    return;
+  Ptr<WifiMac> mac = wifi->GetMac ();
+  if (mac == 0)
+    return;
+  
+  mac->TraceConnectWithoutContext ("TxErrHeader", m_nb.GetTxErrorCallback ());
+  m_nb.AddArpCache (l3->GetInterface (i)->GetArpCache ());
+}
+
+void
+RoutingProtocol::NotifyInterfaceDown (uint32_t i)
+{
+  NS_LOG_FUNCTION (this << m_ipv4->GetAddress (i, 0).GetLocal ());
+
+  // Disable layer 2 link state monitoring (if possible)
+  Ptr<Ipv4L3Protocol> l3 = m_ipv4->GetObject<Ipv4L3Protocol> ();
+  Ptr<NetDevice> dev = l3->GetNetDevice (i);
+  Ptr<WifiNetDevice> wifi = dev->GetObject<WifiNetDevice> ();
+  if (wifi != 0)
+    {
+      Ptr<WifiMac> mac = wifi->GetMac ()->GetObject<AdhocWifiMac> ();
+      if (mac != 0)
+        {
+          mac->TraceDisconnectWithoutContext ("TxErrHeader",
+              m_nb.GetTxErrorCallback ());
+          m_nb.DelArpCache (l3->GetInterface (i)->GetArpCache ());
+        }
+    }
+  
+  // Close socket 
+  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 aodv interfaces");
+      m_htimer.Cancel ();
+      m_nb.Clear ();
+      m_routingTable.Clear ();
+      return;
+    }
+  m_routingTable.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;
+  if (l3->GetNAddresses (i) == 1)
+    {
+      Ipv4InterfaceAddress iface = l3->GetAddress (i, 0);
+      Ptr<Socket> socket = FindSocketWithInterfaceAddress (iface);
+      if (!socket)
+        {
+          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::RecvAodv,this));
+          socket->Bind (InetSocketAddress (iface.GetLocal (), AODV_PORT));
+          socket->Connect (InetSocketAddress (iface.GetBroadcast (), AODV_PORT));
+          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 (), /*know seqno=*/true,
+                                /*seqno=*/0, /*iface=*/iface, /*hops=*/1,
+                                /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Simulator::GetMaximumSimulationTime ());
+          m_routingTable.AddRoute (rt);
+        }
+    }
+  else
+    {
+      NS_LOG_LOGIC ("AODV does not work with more then one address per each interface. Ignore added address");
+    }
+}
+
+void
+RoutingProtocol::NotifyRemoveAddress (uint32_t i, Ipv4InterfaceAddress address)
+{
+  NS_LOG_FUNCTION (this);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress (address);
+  if (socket)
+    {
+      m_routingTable.DeleteAllRoutesFromInterface (address);
+      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::RecvAodv, this));
+          socket->Bind (InetSocketAddress (iface.GetLocal (), AODV_PORT));
+          socket->Connect (InetSocketAddress (iface.GetBroadcast (), AODV_PORT));
+          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 (), /*know seqno=*/true, /*seqno=*/0, /*iface=*/iface,
+                                /*hops=*/1, /*next hop=*/iface.GetBroadcast (), /*lifetime=*/Simulator::GetMaximumSimulationTime ());
+          m_routingTable.AddRoute (rt);
+        }
+      if (m_socketAddresses.empty ())
+        {
+          NS_LOG_LOGIC ("No aodv interfaces");
+          m_htimer.Cancel ();
+          m_nb.Clear ();
+          m_routingTable.Clear ();
+          return;
+        }
+    }
+  else
+    {
+      NS_LOG_LOGIC ("Remove address not participating in AODV operation");
+    }
+}
+
+bool
+RoutingProtocol::IsMyOwnAddress (Ipv4Address src)
+{
+  for (std::map<Ptr<Socket> , Ipv4InterfaceAddress>::const_iterator j =
+      m_socketAddresses.begin (); j != m_socketAddresses.end (); ++j)
+    {
+      Ipv4InterfaceAddress iface = j->second;
+      if (src == iface.GetLocal ())
+        {
+          return true;
+        }
+    }
+  return false;
+}
+
+void
+RoutingProtocol::SendRequest (Ipv4Address dst)
+{
+  NS_LOG_FUNCTION ( this << dst);
+  // A node SHOULD NOT originate more than RREQ_RATELIMIT RREQ messages per second.
+  if (m_rreqCount == RreqRateLimit)
+    {
+      Simulator::Schedule (m_rreqRateLimitTimer.GetDelayLeft () + MicroSeconds (100),
+          &RoutingProtocol::SendRequest, this, dst);
+      return;
+    }
+  else
+    m_rreqCount++;
+  // Create RREQ header
+  RreqHeader rreqHeader;
+  rreqHeader.SetDst (dst);
+
+  RoutingTableEntry rt;
+  if (m_routingTable.LookupRoute (dst, rt))
+    {
+      rreqHeader.SetHopCount (rt.GetHop ());
+      if (rt.GetValidSeqNo ())
+        rreqHeader.SetDstSeqno (rt.GetSeqNo ());
+      else
+        rreqHeader.SetUnknownSeqno (true);
+      rt.SetFlag (IN_SEARCH);
+      m_routingTable.AddRoute (rt);
+    }
+  else
+    {
+      rreqHeader.SetUnknownSeqno (true);
+      RoutingTableEntry newEntry;
+      newEntry.SetFlag (IN_SEARCH);
+      m_routingTable.AddRoute (newEntry);
+    }
+
+  if (GratuitousReply)
+    rreqHeader.SetGratiousRrep (true);
+  if (DestinationOnly)
+    rreqHeader.SetDestinationOnly (true);
+
+  m_seqNo++;
+  rreqHeader.SetOriginSeqno (m_seqNo);
+  m_requestId++;
+  rreqHeader.SetId (m_requestId);
+  rreqHeader.SetHopCount (0);
+
+  // Send RREQ as subnet directed broadcast from each interface used by aodv
+  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;
+
+      rreqHeader.SetOrigin (iface.GetLocal ());
+      m_rreqIdCache.IsDuplicate (iface.GetLocal (), m_requestId);
+
+      Ptr<Packet> packet = Create<Packet> ();
+      packet->AddHeader (rreqHeader);
+      TypeHeader tHeader (AODVTYPE_RREQ);
+      packet->AddHeader (tHeader);
+      socket->Send (packet);
+    }
+  ScheduleRreqRetry (dst);
+  if (EnableHello)
+    {
+      m_htimer.Cancel ();
+      m_htimer.Schedule (HelloInterval - Scalar (0.01) * MilliSeconds (UniformVariable ().GetInteger (0, 10)));
+    }
+}
+
+void
+RoutingProtocol::ScheduleRreqRetry (Ipv4Address dst)
+{
+  if (m_addressReqTimer.find (dst) == m_addressReqTimer.end ())
+    {
+      Timer timer (Timer::CANCEL_ON_DESTROY);
+      m_addressReqTimer[dst] = timer;
+    }
+  m_addressReqTimer[dst].SetFunction (&RoutingProtocol::RouteRequestTimerExpire, this);
+  m_addressReqTimer[dst].Remove ();
+  m_addressReqTimer[dst].SetArguments (dst);
+  RoutingTableEntry rt;
+  m_routingTable.LookupRoute (dst, rt);
+  rt.IncrementRreqCnt ();
+  m_routingTable.Update (rt);
+  m_addressReqTimer[dst].Schedule (Scalar (rt.GetRreqCnt ()) * NetTraversalTime);
+}
+
+void
+RoutingProtocol::RecvAodv (Ptr<Socket> socket)
+{
+  NS_LOG_FUNCTION (this);
+  Address sourceAddress;
+  Ptr<Packet> packet = socket->RecvFrom (sourceAddress);
+  InetSocketAddress inetSourceAddr = InetSocketAddress::ConvertFrom (sourceAddress);
+  Ipv4Address sender = inetSourceAddr.GetIpv4 ();
+  Ipv4Address receiver = m_socketAddresses[socket].GetLocal ();
+  NS_LOG_DEBUG ("AODV node " << this << " received a AODV packet from " << sender << " to " << receiver);
+
+  UpdateRouteToNeighbor (sender, receiver);
+  TypeHeader tHeader (AODVTYPE_RREQ);
+  packet->RemoveHeader (tHeader);
+  if (!tHeader.IsValid ())
+    {
+      NS_LOG_DEBUG ("AODV message " << packet->GetUid() << " with unknown type received: " << tHeader.Get() << ". Drop");
+      return; // drop
+    }
+  switch (tHeader.Get ())
+    {
+    case AODVTYPE_RREQ:
+      {
+        RecvRequest (packet, receiver, sender);
+        break;
+      }
+    case AODVTYPE_RREP:
+      {
+        RecvReply (packet, receiver, sender);
+        break;
+      }
+    case AODVTYPE_RERR:
+      {
+        RecvError (packet, sender);
+        break;
+      }
+    case AODVTYPE_RREP_ACK:
+      {
+        RecvReplyAck (sender);
+        break;
+      }
+    }
+}
+
+bool
+RoutingProtocol::UpdateRouteLifeTime (Ipv4Address addr, Time lifetime)
+{
+  RoutingTableEntry rt;
+  if (m_routingTable.LookupRoute (addr, rt))
+    {
+      rt.SetFlag (VALID);
+      rt.SetRreqCnt (0);
+      rt.SetLifeTime (std::max (lifetime, rt.GetLifeTime ()));
+      m_routingTable.Update (rt);
+      return true;
+    }
+  return false;
+}
+
+void
+RoutingProtocol::UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver)
+{
+  NS_LOG_FUNCTION (this << "sender " << sender << " receiver " << receiver);
+  RoutingTableEntry toNeighbor;
+  if (!m_routingTable.LookupRoute (sender, toNeighbor))
+    {
+      Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+      RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/sender, /*know seqno=*/false, /*seqno=*/0,
+                                  /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
+                                  /*hops=*/1, /*next hop=*/sender, /*lifetime=*/ActiveRouteTimeout);
+      m_routingTable.AddRoute (newEntry);
+    }
+  else
+    {
+      Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+      RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/sender, /*know seqno=*/false, /*seqno=*/0,
+                                  /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
+                                  /*hops=*/1, /*next hop=*/sender, /*lifetime=*/std::max (ActiveRouteTimeout, toNeighbor.GetLifeTime ()));
+      m_routingTable.Update (newEntry);
+    }
+}
+
+void
+RoutingProtocol::RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src)
+{
+  NS_LOG_FUNCTION (this);
+  RreqHeader rreqHeader;
+  p->RemoveHeader (rreqHeader);
+
+  // A node ignores all RREQs received from any node in its blacklist
+  RoutingTableEntry toPrev;
+  if (m_routingTable.LookupRoute (src, toPrev))
+    {
+      if (toPrev.IsUnidirectional ())
+        return;
+    }
+
+  uint32_t id = rreqHeader.GetId ();
+  Ipv4Address origin = rreqHeader.GetOrigin ();
+
+  /*
+   *  Node checks to determine whether it has received a RREQ with the same Originator IP Address and RREQ ID.
+   *  If such a RREQ has been received, the node silently discards the newly received RREQ.
+   */
+  if (m_rreqIdCache.IsDuplicate (origin, id))
+    {
+      return;
+    }
+
+  // Increment RREQ hop count
+  uint8_t hop = rreqHeader.GetHopCount () + 1;
+  rreqHeader.SetHopCount (hop);
+
+  /*
+   *  When the reverse route is created or updated, the following actions on the route are also carried out:
+   *  1. the Originator Sequence Number from the RREQ is compared to the corresponding destination sequence number
+   *     in the route table entry and copied if greater than the existing value there
+   *  2. the valid sequence number field is set to true;
+   *  3. the next hop in the routing table becomes the node from which the  RREQ was received
+   *  4. the hop count is copied from the Hop Count in the RREQ message;
+   *  5. the Lifetime is set to be the maximum of (ExistingLifetime, MinimalLifetime), where
+   *     MinimalLifetime = current time + 2*NetTraversalTime - 2*HopCount*NodeTraversalTime
+   */
+  RoutingTableEntry toOrigin;
+  if (!m_routingTable.LookupRoute (origin, toOrigin))
+    {
+      Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+      RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/origin, /*validSeno=*/true, /*seqNo=*/rreqHeader.GetOriginSeqno (),
+                                  /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0), /*hops=*/hop,
+                                  /*nextHop*/src, /*timeLife=*/Scalar (2) * NetTraversalTime - Scalar (2 * hop) * NodeTraversalTime);
+      m_routingTable.AddRoute (newEntry);
+    }
+  else
+    {
+      if (toOrigin.GetValidSeqNo ())
+        {
+          if (int32_t (rreqHeader.GetOriginSeqno ()) - int32_t (toOrigin.GetSeqNo ()) > 0)
+            toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ());
+        }
+      else
+        toOrigin.SetSeqNo (rreqHeader.GetOriginSeqno ());
+      toOrigin.SetValidSeqNo (true);
+      toOrigin.SetNextHop (src);
+      toOrigin.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
+      toOrigin.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
+      toOrigin.SetHop (hop);
+      toOrigin.SetLifeTime (std::max (Scalar (2) * NetTraversalTime - Scalar (2 * hop) * NodeTraversalTime, toOrigin.GetLifeTime ()));
+      m_routingTable.Update (toOrigin);
+    }
+  NS_LOG_LOGIC (receiver << " receive RREQ to destination " << rreqHeader.GetDst ());
+
+  //  A node generates a RREP if either:
+  //  (i)  it is itself the destination,
+  if (IsMyOwnAddress (rreqHeader.GetDst ()))
+    {
+      m_routingTable.LookupRoute (origin, toOrigin);
+      SendReply (rreqHeader, toOrigin);
+      return;
+    }
+  /*
+   * (ii) or it has an active route to the destination, the destination sequence number in the node's existing route table entry for the destination
+   *      is valid and greater than or equal to the Destination Sequence Number of the RREQ, and the "destination only" flag is NOT set.
+   */
+  RoutingTableEntry toDst;
+  Ipv4Address dst = rreqHeader.GetDst ();
+  if (m_routingTable.LookupRoute (dst, toDst))
+    {
+      /*
+       * The Destination Sequence number for the requested destination is set to the maximum of the corresponding value
+       * received in the RREQ message, and the destination sequence value currently maintained by the node for the requested destination.
+       * However, the forwarding node MUST NOT modify its maintained value for the destination sequence number, even if the value
+       * received in the incoming RREQ is larger than the value currently maintained by the forwarding node.
+       */
+      if (rreqHeader.GetUnknownSeqno () || ( (int32_t (toDst.GetSeqNo ()) - int32_t (rreqHeader.GetDstSeqno ()) > 0)
+          && toDst.GetValidSeqNo () ))
+        {
+          if (!rreqHeader.GetDestinationOnly () && toDst.GetFlag() == VALID)
+            {
+              m_routingTable.LookupRoute (origin, toOrigin);
+              SendReplyByIntermediateNode (toDst, toOrigin, rreqHeader.GetGratiousRrep ());
+              return;
+            }
+          rreqHeader.SetDstSeqno (toDst.GetSeqNo ());
+          rreqHeader.SetUnknownSeqno (false);
+        }
+    }
+
+  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> ();
+      packet->AddHeader (rreqHeader);
+      TypeHeader tHeader (AODVTYPE_RREQ);
+      packet->AddHeader (tHeader);
+      socket->Send (packet);
+    }
+
+  if (EnableHello)
+    {
+      m_htimer.Cancel ();
+      m_htimer.Schedule (HelloInterval - Scalar(0.1)*MilliSeconds(UniformVariable().GetInteger (0, 10)));
+    }
+}
+
+void
+RoutingProtocol::SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin)
+{
+  NS_LOG_FUNCTION (this << toOrigin.GetDestination ());
+  /*
+   * Destination node MUST increment its own sequence number by one if the sequence number in the RREQ packet is equal to that
+   * incremented value. Otherwise, the destination does not change its sequence number before generating the  RREP message.
+   */
+  if (!rreqHeader.GetUnknownSeqno () && (rreqHeader.GetDstSeqno () == m_seqNo + 1))
+    m_seqNo++;
+  RrepHeader rrepHeader ( /*prefixSize=*/0, /*hops=*/0, /*dst=*/rreqHeader.GetDst (),
+                          /*dstSeqNo=*/m_seqNo, /*origin=*/toOrigin.GetDestination (), /*lifeTime=*/MyRouteTimeout);
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (rrepHeader);
+  TypeHeader tHeader (AODVTYPE_RREP);
+  packet->AddHeader (tHeader);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ());
+  NS_ASSERT (socket);
+  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
+}
+
+void
+RoutingProtocol::SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep)
+{
+  NS_LOG_FUNCTION(this);
+  RrepHeader rrepHeader (/*prefix size=*/0, /*hops=*/toDst.GetHop (), /*dst=*/toDst.GetDestination (), /*dst seqno=*/toDst.GetSeqNo (),
+                         /*origin=*/toOrigin.GetDestination (), /*lifetime=*/toDst.GetLifeTime ());
+  /* If the node we received a RREQ for is a neighbor we are
+   * probably facing a unidirectional link... Better request a RREP-ack
+   */
+  if (toDst.GetHop () == 1)
+    {
+      rrepHeader.SetAckRequired (true);
+      RoutingTableEntry toNextHop;
+      m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHop);
+      toNextHop.m_ackTimer.SetFunction (&RoutingProtocol::AckTimerExpire, this);
+      toNextHop.m_ackTimer.SetArguments (toNextHop.GetDestination (), BlackListTimeout);
+      toNextHop.m_ackTimer.SetDelay (NextHopWait);
+    }
+  toDst.InsertPrecursor (toOrigin.GetNextHop ());
+  toOrigin.InsertPrecursor (toDst.GetNextHop ());
+  m_routingTable.Update (toDst);
+  m_routingTable.Update (toOrigin);
+
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (rrepHeader);
+  TypeHeader tHeader (AODVTYPE_RREP);
+  packet->AddHeader (tHeader);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ());
+  NS_ASSERT (socket);
+  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
+
+  // Generating gratuitous RREPs
+  if (gratRep)
+    {
+      RrepHeader gratRepHeader (/*prefix size=*/0, /*hops=*/toOrigin.GetHop (), /*dst=*/toOrigin.GetDestination (),
+                                /*dst seqno=*/toOrigin.GetSeqNo (), /*origin=*/toDst.GetDestination (),
+                                /*lifetime=*/toOrigin.GetLifeTime ());
+      Ptr<Packet> packetToDst = Create<Packet> ();
+      packetToDst->AddHeader (gratRepHeader);
+      TypeHeader type (AODVTYPE_RREP);
+      packetToDst->AddHeader (type);
+      Ptr<Socket> socket = FindSocketWithInterfaceAddress (toDst.GetInterface ());
+      NS_ASSERT (socket);
+      NS_LOG_LOGIC ("Send gratuitous RREP " << packet->GetUid());
+      socket->SendTo (packetToDst, 0, InetSocketAddress (toDst.GetNextHop (), AODV_PORT));
+    }
+}
+
+void
+RoutingProtocol::SendReplyAck (Ipv4Address neighbor)
+{
+  NS_LOG_FUNCTION (this << " to " << neighbor);
+  RrepAckHeader h;
+  TypeHeader typeHeader (AODVTYPE_RREP_ACK);
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (h);
+  packet->AddHeader (typeHeader);
+  RoutingTableEntry toNeighbor;
+  m_routingTable.LookupRoute (neighbor, toNeighbor);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toNeighbor.GetInterface ());
+  NS_ASSERT (socket);
+  socket->SendTo (packet, 0, InetSocketAddress (neighbor, AODV_PORT));
+}
+
+void
+RoutingProtocol::RecvReply (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address sender)
+{
+  NS_LOG_FUNCTION(this << " src " << sender);
+  RrepHeader rrepHeader;
+  p->RemoveHeader (rrepHeader);
+  Ipv4Address dst = rrepHeader.GetDst ();
+  NS_LOG_LOGIC("RREP destination " << dst << " RREP origin " << rrepHeader.GetOrigin());
+
+  uint8_t hop = rrepHeader.GetHopCount () + 1;
+  rrepHeader.SetHopCount (hop);
+
+  // If RREP is Hello message
+  if (dst == rrepHeader.GetOrigin ())
+    {
+      ProcessHello (rrepHeader, receiver);
+      return;
+    }
+
+  /*
+   * If the route table entry to the destination is created or updated, then the following actions occur:
+   * -  the route is marked as active,
+   * -  the destination sequence number is marked as valid,
+   * -  the next hop in the route entry is assigned to be the node from which the RREP is received,
+   *    which is indicated by the source IP address field in the IP header,
+   * -  the hop count is set to the value of the hop count from RREP message + 1
+   * -  the expiry time is set to the current time plus the value of the Lifetime in the RREP message,
+   * -  and the destination sequence number is the Destination Sequence Number in the RREP message.
+   */
+  Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+  RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/dst, /*validSeqNo=*/true, /*seqno=*/rrepHeader.GetDstSeqno (),
+                              /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),/*hop=*/hop,
+                              /*nextHop=*/sender, /*lifeTime=*/rrepHeader.GetLifeTime ());
+  RoutingTableEntry toDst;
+  if (m_routingTable.LookupRoute (dst, toDst))
+    {
+      /*
+       * The existing entry is updated only in the following circumstances:
+       * (i) the sequence number in the routing table is marked as invalid in route table entry.
+       */
+      if (!toDst.GetValidSeqNo ())
+        {
+          m_routingTable.Update (newEntry);
+        }
+      // (ii)the Destination Sequence Number in the RREP is greater than the node's copy of the destination sequence number and the known value is valid,
+      else if ((int32_t (rrepHeader.GetDstSeqno ()) - int32_t (toDst.GetSeqNo ())) > 0)
+        {
+          m_routingTable.Update (newEntry);
+        }
+      else
+        {
+          // (iii) the sequence numbers are the same, but the route is marked as inactive.
+          if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (toDst.GetFlag () != VALID))
+            {
+              m_routingTable.Update (newEntry);
+            }
+          // (iv)  the sequence numbers are the same, and the New Hop Count is smaller than the hop count in route table entry.
+          else if ((rrepHeader.GetDstSeqno () == toDst.GetSeqNo ()) && (hop < toDst.GetHop ()))
+            {
+              m_routingTable.Update (newEntry);
+            }
+        }
+    }
+  else
+    {
+      // The forward route for this destination is created if it does not already exist.
+      NS_LOG_LOGIC ("add new route");
+      m_routingTable.AddRoute (newEntry);
+    }
+  // Acknowledge receipt of the RREP by sending a RREP-ACK message back
+  if (rrepHeader.GetAckRequired ())
+    {
+      SendReplyAck (sender);
+      rrepHeader.SetAckRequired (false);
+    }
+  NS_LOG_LOGIC ("receiver " << receiver << " origin " << rrepHeader.GetOrigin ());
+  if (IsMyOwnAddress (rrepHeader.GetOrigin ()))
+    {
+      if (toDst.GetFlag () == IN_SEARCH)
+        {
+          m_routingTable.Update (newEntry);
+          m_addressReqTimer[dst].Remove ();
+          m_addressReqTimer.erase (dst);
+        }
+      SendPacketFromQueue (rrepHeader.GetDst (), newEntry.GetRoute ());
+      return;
+    }
+
+  RoutingTableEntry toOrigin;
+  if (!m_routingTable.LookupRoute (rrepHeader.GetOrigin (), toOrigin))
+    {
+      return; // Impossible! drop.
+    }
+  toOrigin.SetLifeTime (std::max (ActiveRouteTimeout, toOrigin.GetLifeTime ()));
+  m_routingTable.Update (toOrigin);
+
+  // Update information about precursors
+  m_routingTable.LookupRoute (rrepHeader.GetDst (), toDst);
+  toDst.InsertPrecursor (toOrigin.GetNextHop ());
+  m_routingTable.Update (toDst);
+
+  RoutingTableEntry toNextHopToDst;
+  m_routingTable.LookupRoute (toDst.GetNextHop (), toNextHopToDst);
+  toNextHopToDst.InsertPrecursor (toOrigin.GetNextHop ());
+  m_routingTable.Update (toNextHopToDst);
+
+  toOrigin.InsertPrecursor (toDst.GetNextHop ());
+  m_routingTable.Update (toOrigin);
+
+  RoutingTableEntry toNextHopToOrigin;
+  m_routingTable.LookupRoute (toOrigin.GetNextHop (), toNextHopToOrigin);
+  toNextHopToOrigin.InsertPrecursor (toDst.GetNextHop ());
+  m_routingTable.Update (toNextHopToOrigin);
+
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (rrepHeader);
+  TypeHeader tHeader (AODVTYPE_RREP);
+  packet->AddHeader (tHeader);
+  Ptr<Socket> socket = FindSocketWithInterfaceAddress (toOrigin.GetInterface ());
+  NS_ASSERT (socket);
+  socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
+}
+
+void
+RoutingProtocol::RecvReplyAck (Ipv4Address neighbor)
+{
+  NS_LOG_FUNCTION (this);
+  RoutingTableEntry rt;
+  if(m_routingTable.LookupRoute(neighbor, rt))
+    {
+      rt.m_ackTimer.Cancel ();
+      rt.SetFlag (VALID);
+      m_routingTable.Update(rt);
+    }
+}
+
+void
+RoutingProtocol::ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiver )
+{
+  NS_LOG_FUNCTION(this << "from " << rrepHeader.GetDst ());
+  /*
+   *  Whenever a node receives a Hello message from a neighbor, the node
+   * SHOULD make sure that it has an active route to the neighbor, and
+   * create one if necessary.
+   */
+  RoutingTableEntry toNeighbor;
+  if (!m_routingTable.LookupRoute (rrepHeader.GetDst (), toNeighbor))
+    {
+      Ptr<NetDevice> dev = m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver));
+      RoutingTableEntry newEntry (/*device=*/dev, /*dst=*/rrepHeader.GetDst (), /*validSeqNo=*/true, /*seqno=*/rrepHeader.GetDstSeqno (),
+                                  /*iface=*/m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0),
+                                  /*hop=*/1, /*nextHop=*/rrepHeader.GetDst (), /*lifeTime=*/rrepHeader.GetLifeTime ());
+      m_routingTable.AddRoute (newEntry);
+    }
+  else
+    {
+      toNeighbor.SetLifeTime (std::max (Scalar (AllowedHelloLoss) * HelloInterval, toNeighbor.GetLifeTime ()));
+      toNeighbor.SetSeqNo (rrepHeader.GetDstSeqno ());
+      toNeighbor.SetValidSeqNo (true);
+      toNeighbor.SetFlag (VALID);
+      toNeighbor.SetOutputDevice (m_ipv4->GetNetDevice (m_ipv4->GetInterfaceForAddress (receiver)));
+      toNeighbor.SetInterface (m_ipv4->GetAddress (m_ipv4->GetInterfaceForAddress (receiver), 0));
+      m_routingTable.Update (toNeighbor);
+    }
+  if (EnableHello)
+    {
+      m_nb.Update (rrepHeader.GetDst (), Scalar (AllowedHelloLoss) * HelloInterval);
+    }
+}
+
+void
+RoutingProtocol::RecvError (Ptr<Packet> p, Ipv4Address src )
+{
+  NS_LOG_FUNCTION (this << " from " << src);
+  RerrHeader rerrHeader;
+  p->RemoveHeader (rerrHeader);
+  std::map<Ipv4Address, uint32_t> dstWithNextHopSrc;
+  std::map<Ipv4Address, uint32_t> unreachable;
+  m_routingTable.GetListOfDestinationWithNextHop (src, dstWithNextHopSrc);
+  std::pair<Ipv4Address, uint32_t> un;
+  while (rerrHeader.RemoveUnDestination (un))
+    {
+      if (m_nb.IsNeighbor (un.first))
+        SendRerrWhenBreaksLinkToNextHop (un.first);
+      else
+        {
+          for (std::map<Ipv4Address, uint32_t>::const_iterator i =
+              dstWithNextHopSrc.begin (); i != dstWithNextHopSrc.end (); ++i)
+            {
+              if (i->first == un.first)
+                {
+                  Ipv4Address dst = un.first;
+                  unreachable.insert (un);
+                }
+            }
+        }
+    }
+
+  std::vector<Ipv4Address> precursors;
+  for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin ();
+      i != unreachable.end ();)
+    {
+      if (!rerrHeader.AddUnDestination (i->first, i->second))
+        {
+          TypeHeader typeHeader (AODVTYPE_RERR);
+          Ptr<Packet> packet = Create<Packet> ();
+          packet->AddHeader (rerrHeader);
+          packet->AddHeader (typeHeader);
+          SendRerrMessage (packet, precursors);
+          rerrHeader.Clear ();
+        }
+      else
+        {
+          RoutingTableEntry toDst;
+          m_routingTable.LookupRoute (i->first, toDst);
+          toDst.GetPrecursors (precursors);
+          ++i;
+        }
+    }
+  if (rerrHeader.GetDestCount () != 0)
+    {
+      TypeHeader typeHeader (AODVTYPE_RERR);
+      Ptr<Packet> packet = Create<Packet> ();
+      packet->AddHeader (rerrHeader);
+      packet->AddHeader (typeHeader);
+      SendRerrMessage (packet, precursors);
+    }
+  m_routingTable.InvalidateRoutesWithDst (unreachable);
+}
+
+void
+RoutingProtocol::RouteRequestTimerExpire (Ipv4Address dst)
+{
+  NS_LOG_LOGIC(this);
+  RoutingTableEntry toDst;
+  m_routingTable.LookupRoute (dst, toDst);
+  if (toDst.GetFlag () == VALID)
+    {
+      SendPacketFromQueue (dst, toDst.GetRoute ());
+      NS_LOG_LOGIC ("route to " << dst << " found");
+      return;
+    }
+  /*
+   *  If a route discovery has been attempted RreqRetries times at the maximum TTL without
+   *  receiving any RREP, all data packets destined for the corresponding destination SHOULD be
+   *  dropped from the buffer and a Destination Unreachable message SHOULD be delivered to the application.
+   */
+  if (toDst.GetRreqCnt () == RreqRetries)
+    {
+      NS_LOG_LOGIC("route discovery to " << dst << " has been attempted RreqRetries times");
+      m_addressReqTimer.erase (dst);
+      m_routingTable.DeleteRoute (dst);
+      NS_LOG_DEBUG ("Route not found. Drop packet with dst " << dst);
+      m_queue.DropPacketWithDst (dst);
+      return;
+    }
+
+  if (toDst.GetFlag () == IN_SEARCH)
+    {
+      NS_LOG_LOGIC ("Send new RREQ to " << dst << " ttl " << NetDiameter);
+      SendRequest (dst);
+    }
+  else
+    {
+      NS_LOG_DEBUG ("Route down. Stop search. Drop packet with destination " << dst);
+      m_addressReqTimer.erase(dst);
+      m_routingTable.DeleteRoute(dst);
+      m_queue.DropPacketWithDst(dst);
+    }
+}
+
+void
+RoutingProtocol::HelloTimerExpire ()
+{
+  NS_LOG_FUNCTION(this);
+  SendHello ();
+  m_htimer.Cancel ();
+  Time t = Scalar(0.01)*MilliSeconds(UniformVariable().GetInteger (0, 100));
+  m_htimer.Schedule (HelloInterval - t);
+}
+
+void
+RoutingProtocol::RreqRateLimitTimerExpire ()
+{
+  m_rreqCount = 0;
+  m_rreqRateLimitTimer.Schedule (Seconds (1));
+}
+
+void
+RoutingProtocol::AckTimerExpire (Ipv4Address neighbor, Time blacklistTimeout)
+{
+  NS_LOG_FUNCTION(this);
+  m_routingTable.MarkLinkAsUnidirectional (neighbor, blacklistTimeout);
+}
+
+void
+RoutingProtocol::SendHello ()
+{
+  NS_LOG_FUNCTION(this);
+  /* Broadcast a RREP with TTL = 1 with the RREP message fields set as follows:
+   *   Destination IP Address         The node's IP address.
+   *   Destination Sequence Number    The node's latest sequence number.
+   *   Hop Count                      0
+   *   Lifetime                       AllowedHelloLoss * HelloInterval
+   */
+  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;
+      RrepHeader helloHeader (/*prefix size=*/0, /*hops=*/0, /*dst=*/iface.GetLocal (), /*dst seqno=*/m_seqNo,
+                              /*origin=*/iface.GetLocal (),/*lifetime=*/Scalar (AllowedHelloLoss) * HelloInterval);
+      Ptr<Packet> packet = Create<Packet> ();
+      packet->AddHeader (helloHeader);
+      TypeHeader tHeader (AODVTYPE_RREP);
+      packet->AddHeader (tHeader);
+      socket->Send (packet);
+    }
+}
+
+void
+RoutingProtocol::SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route)
+{
+  NS_LOG_FUNCTION(this);
+  QueueEntry queueEntry;
+  while (m_queue.Dequeue (dst, queueEntry))
+    {
+      UnicastForwardCallback ucb = queueEntry.GetUnicastForwardCallback ();
+      ucb (route, queueEntry.GetPacket (), queueEntry.GetIpv4Header ());
+    }
+}
+
+void
+RoutingProtocol::Send (Ptr<Ipv4Route> route, Ptr<const Packet> packet,
+    const Ipv4Header & header)
+{
+  NS_LOG_FUNCTION (this << packet->GetUid() << (uint16_t) header.GetProtocol());
+  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::SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop)
+{
+  NS_LOG_FUNCTION (this << nextHop);
+  RerrHeader rerrHeader;
+  std::vector<Ipv4Address> precursors;
+  std::map<Ipv4Address, uint32_t> unreachable;
+
+  RoutingTableEntry toNextHop;
+  if (!m_routingTable.LookupRoute (nextHop, toNextHop))
+    return;
+  toNextHop.GetPrecursors (precursors);
+  rerrHeader.AddUnDestination (nextHop, toNextHop.GetSeqNo ());
+  m_routingTable.GetListOfDestinationWithNextHop (nextHop, unreachable);
+  for (std::map<Ipv4Address, uint32_t>::const_iterator i = unreachable.begin (); i
+      != unreachable.end ();)
+    {
+      if (!rerrHeader.AddUnDestination (i->first, i->second))
+        {
+          NS_LOG_LOGIC ("Send RERR message with maximum size.");
+          TypeHeader typeHeader (AODVTYPE_RERR);
+          Ptr<Packet> packet = Create<Packet> ();
+          packet->AddHeader (rerrHeader);
+          packet->AddHeader (typeHeader);
+          SendRerrMessage (packet, precursors);
+          rerrHeader.Clear ();
+        }
+      else
+        {
+          RoutingTableEntry toDst;
+          m_routingTable.LookupRoute (i->first, toDst);
+          toDst.GetPrecursors (precursors);
+          ++i;
+        }
+    }
+  if (rerrHeader.GetDestCount () != 0)
+    {
+      TypeHeader typeHeader (AODVTYPE_RERR);
+      Ptr<Packet> packet = Create<Packet> ();
+      packet->AddHeader (rerrHeader);
+      packet->AddHeader (typeHeader);
+      SendRerrMessage (packet, precursors);
+    }
+  unreachable.insert (std::make_pair (nextHop, toNextHop.GetSeqNo ()));
+  m_routingTable.InvalidateRoutesWithDst (unreachable);
+}
+
+void
+RoutingProtocol::SendRerrWhenNoRouteToForward (Ipv4Address dst,
+    uint32_t dstSeqNo, Ipv4Address origin)
+{
+  NS_LOG_FUNCTION (this);
+  RerrHeader rerrHeader;
+  rerrHeader.AddUnDestination (dst, dstSeqNo);
+  RoutingTableEntry toOrigin;
+  Ptr<Packet> packet = Create<Packet> ();
+  packet->AddHeader (rerrHeader);
+  packet->AddHeader (TypeHeader (AODVTYPE_RERR));
+  if (m_routingTable.LookupRoute (origin, toOrigin))
+    {
+      if (toOrigin.GetFlag () == VALID)
+        {
+          Ptr<Socket> socket = FindSocketWithInterfaceAddress (
+              toOrigin.GetInterface ());
+          NS_ASSERT (socket);
+          NS_LOG_LOGIC ("Unicast RERR to the source of the data transmission");
+          socket->SendTo (packet, 0, InetSocketAddress (toOrigin.GetNextHop (), AODV_PORT));
+        }
+
+    }
+  else
+    {
+      for (std::map<Ptr<Socket> , Ipv4InterfaceAddress>::const_iterator i =
+          m_socketAddresses.begin (); i != m_socketAddresses.end (); ++i)
+        {
+          Ptr<Socket> socket = i->first;
+          Ipv4InterfaceAddress iface = i->second;
+          NS_ASSERT (socket);
+          NS_LOG_LOGIC ("Broadcast RERR message from interface " << iface.GetLocal());
+          socket->Send (packet);
+        }
+    }
+}
+
+void
+RoutingProtocol::SendRerrMessage (Ptr<Packet> packet, std::vector<Ipv4Address> precursors)
+{
+  NS_LOG_FUNCTION(this);
+
+  if (precursors.empty ())
+    {
+      NS_LOG_LOGIC ("No precursors");
+      return;
+    }
+  // If there is only one precursor, RERR SHOULD be unicast toward that precursor
+  if (precursors.size () == 1)
+    {
+      RoutingTableEntry toPrecursor;
+      if (!m_routingTable.LookupRoute (precursors.front (), toPrecursor))
+        return;
+      Ptr<Socket> socket = FindSocketWithInterfaceAddress (toPrecursor.GetInterface ());
+      NS_ASSERT (socket);
+      if (toPrecursor.GetFlag () == VALID)
+        {
+          NS_LOG_LOGIC ("one precursor => unicast RERR to " << toPrecursor.GetDestination() << " from " << toPrecursor.GetInterface ().GetLocal ());
+          socket->SendTo (packet, 0, InetSocketAddress (precursors.front (), AODV_PORT));
+        }
+      else
+        NS_LOG_LOGIC ("One precursor, but no valid route to this precursor");
+      return;
+    }
+
+  //  Should only transmit RERR on those interfaces which have precursor nodes for the broken route
+  std::vector<Ipv4InterfaceAddress> ifaces;
+  RoutingTableEntry toPrecursor;
+  for (std::vector<Ipv4Address>::const_iterator i = precursors.begin (); i
+      != precursors.end (); ++i)
+    {
+      if (!m_routingTable.LookupRoute (*i, toPrecursor))
+        break;
+      bool result = true;
+      for (std::vector<Ipv4InterfaceAddress>::const_iterator i =
+          ifaces.begin (); i != ifaces.end (); ++i)
+        {
+          if (*i == toPrecursor.GetInterface ())
+            {
+              result = false;
+              break;
+            }
+        }
+      if (result)
+        ifaces.push_back (toPrecursor.GetInterface ());
+    }
+
+  for (std::vector<Ipv4InterfaceAddress>::const_iterator i = ifaces.begin (); i != ifaces.end (); ++i)
+    {
+      Ptr<Socket> socket = FindSocketWithInterfaceAddress (*i);
+      NS_ASSERT (socket);
+      NS_LOG_LOGIC ("Broadcast RERR message from interface " << i->GetLocal());
+      socket->Send (packet);
+    }
+
+}
+
+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::Drop(Ptr<const Packet> packet, const Ipv4Header & header, Socket::SocketErrno err)
+{
+  NS_LOG_DEBUG (this <<" drop own packet " << packet->GetUid() << " to " << header.GetDestination () << " from queue. Error " << err);
+}
+
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-routing-protocol.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,254 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#ifndef AODVROUTINGPROTOCOL_H
+#define AODVROUTINGPROTOCOL_H
+
+#include "aodv-rtable.h"
+#include "aodv-rqueue.h"
+#include "aodv-packet.h"
+#include "aodv-neighbor.h"
+
+#include "ns3/dpd.h"
+#include "ns3/node.h"
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/ipv4-interface.h"
+#include "ns3/ipv4-l3-protocol.h"
+#include <map>
+
+namespace ns3
+{
+namespace aodv
+{
+/**
+ * \ingroup aodv
+ * 
+ * \brief AODV routing protocol
+ */
+class RoutingProtocol : public Ipv4RoutingProtocol
+{
+public:
+  static TypeId GetTypeId (void);
+  static const uint32_t AODV_PORT;
+
+  /// c-tor
+  RoutingProtocol ();
+  virtual ~RoutingProtocol();
+  virtual void DoDispose ();
+  
+  ///\name From Ipv4RoutingProtocol
+  //\{
+  Ptr<Ipv4Route> RouteOutput (Ptr<Packet> p, const Ipv4Header &header, uint32_t oif, Socket::SocketErrno &sockerr);
+  bool RouteInput (Ptr<const Packet> p, const Ipv4Header &header, Ptr<const NetDevice> idev,
+                           UnicastForwardCallback ucb, MulticastForwardCallback mcb,
+                           LocalDeliverCallback lcb, ErrorCallback ecb);  
+  virtual void NotifyInterfaceUp (uint32_t interface);
+  virtual void NotifyInterfaceDown (uint32_t interface);
+  virtual void NotifyAddAddress (uint32_t interface, Ipv4InterfaceAddress address);
+  virtual void NotifyRemoveAddress (uint32_t interface, Ipv4InterfaceAddress address);
+  virtual void SetIpv4 (Ptr<Ipv4> ipv4);
+  //\}
+  
+  ///\name Handle protocol parameters
+  //\{
+  bool GetDesinationOnlyFlag () const { return DestinationOnly; }
+  void SetDesinationOnlyFlag (bool f) { DestinationOnly = f; }
+  bool GetGratuitousReplyFlag () const { return GratuitousReply; }
+  void SetGratuitousReplyFlag (bool f) { GratuitousReply = f; }
+  void SetHelloEnable (bool f) { EnableHello = f; }
+  bool GetHelloEnable () const { return EnableHello; }
+  void SetBroadcastEnable (bool f) { EnableBroadcast = f; }
+  bool GetBroadcastEnable () const { return EnableBroadcast; }
+  //\}
+private:
+  ///\name Protocol parameters.
+  //\{
+  uint32_t RreqRetries;             ///< Maximum number of retransmissions of RREQ with TTL = NetDiameter to discover a route
+  uint16_t RreqRateLimit;           ///< Maximum number of RREQ per second.
+  Time ActiveRouteTimeout;          ///< Period of time during which the route is considered to be valid.
+  uint32_t NetDiameter;             ///< Net diameter measures the maximum possible number of hops between two nodes in the network
+  /**
+   *  NodeTraversalTime is a conservative estimate of the average one hop traversal time for packets
+   *  and should include queuing delays, interrupt processing times and transfer times.
+   */
+  Time NodeTraversalTime;
+  Time NetTraversalTime;             ///< Estimate of the average net traversal time.
+  Time PathDiscoveryTime;            ///< Estimate of maximum time needed to find route in network.
+  Time MyRouteTimeout;               ///< Value of lifetime field in RREP generating by this node.
+  /**
+   * Every HelloInterval the node checks whether it has sent a broadcast  within the last HelloInterval.
+   * If it has not, it MAY broadcast a  Hello message
+   */
+  Time HelloInterval;
+  uint32_t AllowedHelloLoss;         ///< Number of hello messages which may be loss for valid link
+  /**
+   * DeletePeriod is intended to provide an upper bound on the time for which an upstream node A
+   * can have a neighbor B as an active next hop for destination D, while B has invalidated the route to D.
+   */
+  Time DeletePeriod;
+  Time NextHopWait;                  ///< Period of our waiting for the neighbour's RREP_ACK
+  /**
+   * The TimeoutBuffer is configurable.  Its purpose is to provide a buffer for the timeout so that if the RREP is delayed
+   * due to congestion, a timeout is less likely to occur while the RREP is still en route back to the source.
+   */
+  uint16_t TimeoutBuffer;
+  Time BlackListTimeout;             ///< Time for which the node is put into the blacklist
+  uint32_t MaxQueueLen;              ///< The maximum number of packets that we allow a routing protocol to buffer.
+  Time MaxQueueTime;                 ///< The maximum period of time that a routing protocol is allowed to buffer a packet for.
+  bool DestinationOnly;              ///< Indicates only the destination may respond to this RREQ.
+  bool GratuitousReply;              ///< Indicates whether a gratuitous RREP should be unicast to the node originated route discovery.
+  bool EnableHello;                  ///< Indicates whether a hello messages enable
+  bool EnableBroadcast;              ///< Indicates whether a a broadcast data packets forwarding enable
+  //\}
+
+  /// 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;
+
+  /// Routing table
+  RoutingTable m_routingTable;
+  /// A "drop-front" queue used by the routing layer to buffer packets to which it does not have a route.
+  RequestQueue m_queue;
+  /// Broadcast ID
+  uint32_t m_requestId;
+  /// Request sequence number
+  uint32_t m_seqNo;
+  /// Handle duplicated RREQ
+  dpd::IdCache m_rreqIdCache;
+  /// Handle duplicated broadcast/multicast packets
+  dpd::DuplicatePacketDetection m_dpd;
+  /// Handle neighbors
+  Neighbors m_nb;
+  /// Number of RREQs used for RREQ rate control
+  uint16_t m_rreqCount;
+
+  /// Unicast callback for own packets
+  UnicastForwardCallback m_scb;
+  /// Error callback for own packets
+  ErrorCallback m_ecb;
+
+private:
+  /// Start protocol operation
+  void Start ();
+  /// If route exists and valid, forward packet.
+  bool Forwarding (Ptr<const Packet> p, const Ipv4Header & header, UnicastForwardCallback ucb, ErrorCallback ecb);
+  /**
+  * To reduce congestion in a network, repeated attempts by a source node at route discovery
+  * for a single destination MUST utilize a binary exponential backoff.
+  */
+  void ScheduleRreqRetry (Ipv4Address dst);
+  /**
+   * Set lifetime field in routing table entry to the maximum of existing lifetime and lt, if the entry exists
+   * \param addr - destination address
+   * \param lt - proposed time for lifetime field in routing table entry for destination with address addr.
+   * \return true if route to destination address addr exist
+   */
+  bool UpdateRouteLifeTime (Ipv4Address addr, Time lt);
+  /**
+   * Update neighbor record.
+   * \param receiver is supposed to be my interface
+   * \param sender is supposed to be IP address of my neighbor.
+   */
+  void UpdateRouteToNeighbor (Ipv4Address sender, Ipv4Address receiver);
+  /// Check that packet is send from own interface
+  bool IsMyOwnAddress (Ipv4Address src);
+  /// Find socket with local interface address iface
+  Ptr<Socket> FindSocketWithInterfaceAddress (Ipv4InterfaceAddress iface) const;
+  /// Process hello message
+  void ProcessHello (RrepHeader const & rrepHeader, Ipv4Address receiverIfaceAddr);
+  
+  ///\name Receive control packets
+  //\{
+  /// Receive and process control packet
+  void RecvAodv (Ptr<Socket> socket);
+  /// Receive RREQ
+  void RecvRequest (Ptr<Packet> p, Ipv4Address receiver, Ipv4Address src);
+  /// Receive RREP
+  void RecvReply (Ptr<Packet> p, Ipv4Address my ,Ipv4Address src);
+  /// Receive RREP_ACK
+  void RecvReplyAck (Ipv4Address neighbor);
+  /// Receive RERR from node with address src
+  void RecvError (Ptr<Packet> p, Ipv4Address src);
+  //\}
+  
+  ///\name Send
+  //\{
+  /// Forward packet from route request queue
+  void SendPacketFromQueue (Ipv4Address dst, Ptr<Ipv4Route> route);
+  /// Aux. send helper
+  void Send (Ptr<Ipv4Route>, Ptr<const Packet>, const Ipv4Header &);
+  /// Send hello
+  void SendHello ();
+  /// Send RREQ
+  void SendRequest (Ipv4Address dst);
+  /// Send RREP
+  void SendReply (RreqHeader const & rreqHeader, RoutingTableEntry const & toOrigin);
+  /** Send RREP by intermediate node
+   * \param toDst routing table entry to destination
+   * \param toOrigin routing table entry to originator
+   * \param gratRep indicates whether a gratuitous RREP should be unicast to destination
+   */
+  void SendReplyByIntermediateNode (RoutingTableEntry & toDst, RoutingTableEntry & toOrigin, bool gratRep);
+  /// Send RREP_ACK
+  void SendReplyAck (Ipv4Address neighbor);
+  /// Initiate RERR
+  void SendRerrWhenBreaksLinkToNextHop (Ipv4Address nextHop);
+  /// Forward RERR
+  void SendRerrMessage(Ptr<Packet> packet,  std::vector<Ipv4Address> precursors);
+  /**
+   * Send RERR message when no route to forward input packet. Unicast if there is reverse route to originating node, broadcast otherwise.
+   * \param dst - destination node IP address
+   * \param dstSeqNo - destination node sequence number
+   * \param origin - originating node IP address
+   */
+  void SendRerrWhenNoRouteToForward (Ipv4Address dst, uint32_t dstSeqNo, Ipv4Address origin);
+  //\}
+  
+  /// Notify that packet is dropped for some reason 
+  void Drop(Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno);
+
+  /// Hello timer
+  Timer m_htimer;
+  /// Schedule next send of hello message
+  void HelloTimerExpire ();
+  /// RREQ rate limit timer
+  Timer m_rreqRateLimitTimer;
+  /// Reset RREQ count and schedule RREQ rate limit timer with delay 1 sec.
+  void RreqRateLimitTimerExpire ();
+  /// Map IP address + RREQ timer.
+  std::map<Ipv4Address, Timer> m_addressReqTimer;
+  /// Handle route discovery process
+  void RouteRequestTimerExpire (Ipv4Address dst);
+  /// Mark link to neighbor node as unidirectional for blacklistTimeout
+  void AckTimerExpire (Ipv4Address neighbor,  Time blacklistTimeout);
+
+};
+
+}
+}
+#endif /* AODVROUTINGPROTOCOL_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-rqueue.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,151 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#include "aodv-rqueue.h"
+#include <algorithm>
+#include <functional>
+#include "ns3/ipv4-route.h"
+#include "ns3/socket.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("AodvRequestQueue");
+
+namespace ns3
+{
+namespace aodv
+{
+uint32_t
+RequestQueue::GetSize ()
+{
+  Purge ();
+  return m_queue.size ();
+}
+
+bool
+RequestQueue::Enqueue (QueueEntry & entry)
+{
+  Purge ();
+  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;
+    }
+  entry.SetExpireTime (m_queueTimeout);
+  if (m_queue.size () == m_maxLen)
+    {
+      Drop (m_queue.front (), "Drop the most aged packet"); // Drop the most aged packet
+      m_queue.erase (m_queue.begin ());
+    }
+  m_queue.push_back (entry);
+  return true;
+}
+
+void
+RequestQueue::DropPacketWithDst (Ipv4Address dst)
+{
+  NS_LOG_FUNCTION (this << 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 (RequestQueue::IsEqual), dst)), m_queue.end ());
+}
+
+bool
+RequestQueue::Dequeue (Ipv4Address dst, QueueEntry & entry)
+{
+  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
+RequestQueue::Find (Ipv4Address dst)
+{
+  for (std::vector<QueueEntry>::const_iterator i = m_queue.begin (); i
+      != m_queue.end (); ++i)
+    {
+      if (i->GetIpv4Header ().GetDestination () == dst)
+        return true;
+    }
+  return false;
+}
+
+struct IsExpired
+{
+  bool
+  operator() (QueueEntry const & e) const
+  {
+    return (e.GetExpireTime () < Seconds (0));
+  }
+};
+
+void
+RequestQueue::Purge ()
+{
+  IsExpired pred;
+  for (std::vector<QueueEntry>::iterator i = m_queue.begin (); i
+      != m_queue.end (); ++i)
+    {
+      if (pred (*i))
+        {
+          Drop (*i, "Drop outdated packet ");
+        }
+    }
+  m_queue.erase (std::remove_if (m_queue.begin (), m_queue.end (), pred),
+      m_queue.end ());
+}
+
+void
+RequestQueue::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/manet/aodv/aodv-rqueue.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,137 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#ifndef AODV_RQUEUE_H
+#define AODV_RQUEUE_H
+
+#include <vector>
+#include "ns3/ipv4-routing-protocol.h"
+#include "ns3/simulator.h"
+
+
+namespace ns3 {
+namespace aodv {
+
+/**
+ * \ingroup aodv
+ * \brief AODV 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 (), Time exp = Simulator::Now ()) :
+              m_packet (pa), m_header (h), m_ucb (ucb), m_ecb (ecb),
+              m_expire (exp + Simulator::Now ())
+  {}
+
+  /**
+   * 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 aodv
+ * \brief AODV route request queue
+ * 
+ * Since AODV is an on demand routing we queue requests while looking for route.
+ */
+class RequestQueue
+{
+public:
+  /// Default c-tor
+  RequestQueue (uint32_t maxLen, Time routeToQueueTimeout) :
+    m_maxLen (maxLen), m_queueTimeout (routeToQueueTimeout)
+  {
+  }
+  /// 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);
+  /// Number of entries
+  uint32_t GetSize ();
+  ///\name Fields
+  //\{
+  uint32_t GetMaxQueueLen () const { return m_maxLen; }
+  void SetMaxQueueLen (uint32_t len) { m_maxLen = 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 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 /* AODV_RQUEUE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-rtable.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,344 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#include "aodv-rtable.h"
+#include <algorithm>
+#include "ns3/simulator.h"
+#include "ns3/log.h"
+
+NS_LOG_COMPONENT_DEFINE ("AodvRoutingTable");
+
+namespace ns3
+{
+namespace aodv
+{
+
+/*
+ The Routing Table
+ */
+
+RoutingTableEntry::RoutingTableEntry (Ptr<NetDevice> dev, Ipv4Address dst, bool vSeqNo, u_int32_t seqNo,
+                                      Ipv4InterfaceAddress iface, u_int16_t hops, Ipv4Address nextHop, Time lifetime) :
+                                      m_ackTimer (Timer::CANCEL_ON_DESTROY),
+                                      m_validSeqNo (vSeqNo), m_seqNo (seqNo), m_hops (hops),
+                                      m_lifeTime (lifetime + Simulator::Now ()), m_iface (iface), m_flag (VALID),
+                                      m_reqCount (0), m_blackListState (false), m_blackListTimeout (Simulator::Now ())
+{
+  m_ipv4Route = Create<Ipv4Route> ();
+  m_ipv4Route->SetDestination (dst);
+  m_ipv4Route->SetGateway (nextHop);
+  m_ipv4Route->SetSource (m_iface.GetLocal ());
+  m_ipv4Route->SetOutputDevice (dev);
+}
+
+RoutingTableEntry::~RoutingTableEntry ()
+{
+}
+
+bool
+RoutingTableEntry::InsertPrecursor (Ipv4Address id)
+{
+  if (!LookupPrecursor (id))
+    {
+      m_precursorList.push_back (id);
+      return true;
+    }
+  else
+    return false;
+}
+
+bool
+RoutingTableEntry::LookupPrecursor (Ipv4Address id)
+{
+  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
+      != m_precursorList.end (); ++i)
+    {
+      if (*i == id)
+        return true;
+    }
+  return false;
+}
+
+bool
+RoutingTableEntry::DeletePrecursor (Ipv4Address id)
+{
+  std::vector<Ipv4Address>::iterator i = std::remove (m_precursorList.begin (),
+      m_precursorList.end (), id);
+  if (i == m_precursorList.end ())
+    return false;
+  else
+    m_precursorList.erase (i, m_precursorList.end ());
+  return true;
+}
+
+void
+RoutingTableEntry::DeleteAllPrecursors ()
+{
+  m_precursorList.clear ();
+}
+
+bool
+RoutingTableEntry::IsPrecursorListEmpty () const
+{
+  return m_precursorList.empty ();
+}
+
+void
+RoutingTableEntry::GetPrecursors (std::vector<Ipv4Address> & prec) const
+{
+  if (IsPrecursorListEmpty ())
+    return;
+  for (std::vector<Ipv4Address>::const_iterator i = m_precursorList.begin (); i
+      != m_precursorList.end (); ++i)
+    {
+      bool result = true;
+      for (std::vector<Ipv4Address>::const_iterator j = prec.begin (); j
+          != prec.end (); ++j)
+        {
+          if (*j == *i)
+            result = false;
+        }
+      if (result)
+        prec.push_back (*i);
+    }
+}
+
+void
+RoutingTableEntry::Invalidate (Time badLinkLifetime)
+{
+  if (m_flag == INVALID)
+    return;
+  m_flag = INVALID;
+  m_reqCount = 0;
+  m_lifeTime = badLinkLifetime + Simulator::Now ();
+}
+
+void
+RoutingTableEntry::Print (std::ostream & os) const
+{
+  os << m_ipv4Route->GetDestination () << "\t" << m_ipv4Route->GetGateway ()
+      << "\t" << m_iface.GetLocal () << "\t";
+  switch (m_flag)
+    {
+    case VALID:
+      {
+        os << "UP";
+        break;
+      }
+    case INVALID:
+      {
+        os << "DOWN";
+        break;
+      }
+    case IN_SEARCH:
+      {
+        os << "IN_SEARCH";
+        break;
+      }
+    }
+  os << "\t" << (m_lifeTime - Simulator::Now ()).GetSeconds () << "\t"
+      << m_hops << "\n";
+}
+
+/*
+ The Routing Table
+ */
+
+RoutingTable::RoutingTable (Time t) : 
+  m_badLinkLifetime (t)
+{
+}
+
+bool
+RoutingTable::LookupRoute (Ipv4Address id, RoutingTableEntry & rt)
+{
+  Purge ();
+  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::DeleteRoute (Ipv4Address dst)
+{
+  Purge ();
+  if (m_ipv4AddressEntry.erase (dst) != 0)
+    return true;
+  return false;
+}
+
+bool
+RoutingTable::AddRoute (RoutingTableEntry & rt)
+{
+  if (rt.GetFlag () != IN_SEARCH)
+    rt.SetRreqCnt (0);
+  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;
+  if (i->second.GetFlag () != IN_SEARCH)
+    i->second.SetRreqCnt (0);
+  return true;
+}
+
+bool
+RoutingTable::SetEntryState (Ipv4Address id, RouteFlags state)
+{
+  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
+      m_ipv4AddressEntry.find (id);
+  if (i == m_ipv4AddressEntry.end ())
+    return false;
+  i->second.SetFlag (state);
+  i->second.SetRreqCnt (0);
+  return true;
+}
+
+void
+RoutingTable::GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable )
+{
+  Purge ();
+  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.GetSeqNo ()));
+        }
+    }
+}
+
+void
+RoutingTable::InvalidateRoutesWithDst (const std::map<Ipv4Address, uint32_t> & unreachable)
+{
+  Purge ();
+  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
+      m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
+    {
+      for (std::map<Ipv4Address, uint32_t>::const_iterator j =
+          unreachable.begin (); j != unreachable.end (); ++j)
+        {
+          if ((i->first == j->first) && (i->second.GetFlag () == VALID))
+            {
+              NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
+              i->second.Invalidate (m_badLinkLifetime);
+            }
+        }
+    }
+}
+
+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::Purge ()
+{
+  if (m_ipv4AddressEntry.empty ())
+    return;
+  for (std::map<Ipv4Address, RoutingTableEntry>::iterator i =
+      m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end ();)
+    {
+      if (i->second.GetLifeTime () < Seconds (0))
+        {
+          if (i->second.GetFlag () == INVALID)
+            {
+              std::map<Ipv4Address, RoutingTableEntry>::iterator tmp = i;
+              ++i;
+              m_ipv4AddressEntry.erase (tmp);
+            }
+          else if (i->second.GetFlag () == VALID)
+            {
+              NS_LOG_LOGIC ("Invalidate route with destination address " << i->first);
+              i->second.Invalidate (m_badLinkLifetime);
+              ++i;
+            }
+          else
+            ++i;
+        }
+      ++i;
+    }
+}
+
+bool
+RoutingTable::MarkLinkAsUnidirectional (Ipv4Address neighbor, Time blacklistTimeout)
+{
+  std::map<Ipv4Address, RoutingTableEntry>::iterator i =
+      m_ipv4AddressEntry.find (neighbor);
+  if (i == m_ipv4AddressEntry.end ())
+    return false;
+  i->second.SetUnidirectional (true);
+  i->second.SetBalcklistTimeout (blacklistTimeout);
+  i->second.SetRreqCnt (0);
+  return true;
+}
+
+void
+RoutingTable::Print (std::ostream &os)
+{
+  Purge ();
+  os << "\nAODV Routing table\n"
+      << "Destination\tGateway\t\tInterface\tFlag\tExpire\tHops\n";
+  for (std::map<Ipv4Address, RoutingTableEntry>::const_iterator i =
+      m_ipv4AddressEntry.begin (); i != m_ipv4AddressEntry.end (); ++i)
+    {
+      i->second.Print (os);
+    }
+  os << "\n";
+}
+
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-rtable.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,252 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#ifndef AODV_RTABLE_H
+#define AODV_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"
+
+namespace ns3 {
+namespace aodv {
+
+/**
+ * \ingroup aodv
+ * \brief Route record states
+ */
+enum RouteFlags
+{
+  VALID = 0,          //!< VALID
+  INVALID = 1,        //!< INVALID
+  IN_SEARCH = 2,      //!< IN_SEARCH
+};
+
+/**
+ * \ingroup aodv
+ * \brief Routing table entry
+ */
+class RoutingTableEntry
+{
+public:
+  /// c-to
+  RoutingTableEntry (Ptr<NetDevice> dev = 0,Ipv4Address dst = Ipv4Address(), bool vSeqNo = false, u_int32_t m_seqNo = 0,
+                    Ipv4InterfaceAddress iface = Ipv4InterfaceAddress(), u_int16_t  hops = 0,
+                    Ipv4Address nextHop = Ipv4Address(), Time lifetime = Simulator::Now());
+
+  ~RoutingTableEntry ();
+  
+  ///\name Precursors management
+  //\{
+  /**
+   * Insert precursor in precursor list if it doesn't yet exist in the list
+   * \param id precursor address
+   * \return true on success
+   */
+  bool InsertPrecursor (Ipv4Address id);
+  /**
+   * Lookup precursor by address
+   * \param id precursor address
+   * \return true on success
+   */
+  bool LookupPrecursor (Ipv4Address id);
+  /**
+   * \brief Delete precursor
+   * \param id precursor address
+   * \return true on success
+   */
+  bool DeletePrecursor (Ipv4Address id);
+  /// Delete all precursors
+  void DeleteAllPrecursors ();
+  /**
+   * Check that precursor list empty
+   * \return true if precursor list empty
+   */
+  bool IsPrecursorListEmpty () const;
+  /**
+   * Inserts precursors in vector prec if they does not yet exist in vector
+   */
+  void GetPrecursors (std::vector<Ipv4Address> & prec) const;
+  //\}
+
+  /// Mark entry as "down" (i.e. disable it)
+  void Invalidate (Time badLinkLifetime);
+  ///\name Fields
+  //\{
+  Ipv4Address GetDestination () const { return m_ipv4Route->GetDestination(); }
+  Ptr<Ipv4Route> GetRoute () const { return  m_ipv4Route; }
+  void SetRoute (Ptr<Ipv4Route> r) { m_ipv4Route = r; }
+  void SetNextHop (Ipv4Address nextHop) { m_ipv4Route->SetGateway(nextHop); }
+  Ipv4Address GetNextHop () const { return m_ipv4Route->GetGateway(); }
+  void SetOutputDevice (Ptr<NetDevice> dev) { m_ipv4Route->SetOutputDevice(dev); }
+  Ptr<NetDevice> GetOutputDevice () const { return m_ipv4Route->GetOutputDevice(); }
+  Ipv4InterfaceAddress GetInterface () const { return m_iface;}
+  void SetInterface (Ipv4InterfaceAddress iface) { m_iface = iface; }
+  void SetValidSeqNo (bool s) { m_validSeqNo = s; }
+  bool GetValidSeqNo () const { return m_validSeqNo; }
+  void SetSeqNo (uint32_t sn) { m_seqNo = sn; }
+  uint32_t GetSeqNo () const { return m_seqNo; }
+  void SetHop (uint16_t hop) { m_hops = hop; }
+  uint16_t GetHop () const {return m_hops; }
+  void SetLifeTime (Time lt) { m_lifeTime = lt + Simulator::Now(); }
+  Time GetLifeTime () const { return m_lifeTime - Simulator::Now(); }
+  void SetFlag (RouteFlags flag) { m_flag = flag; }
+  RouteFlags GetFlag () const { return m_flag; }
+  void SetRreqCnt (uint8_t n) { m_reqCount = n; }
+  uint8_t GetRreqCnt () const { return m_reqCount; }
+  void IncrementRreqCnt () { m_reqCount++; }
+  void SetUnidirectional (bool u) { m_blackListState = u; }
+  bool IsUnidirectional () const { return m_blackListState; }
+  void SetBalcklistTimeout (Time t) { m_blackListTimeout = t; }
+  Time GetBlacklistTimeout () const { return m_blackListTimeout; }
+  /// RREP_ACK timer
+  Timer m_ackTimer;
+  //\}
+
+  /**
+   * \brief Compare destination address
+   * \return true if equal
+   */
+  bool operator== (Ipv4Address const  dst) const
+  {
+    return (m_ipv4Route->GetDestination () == dst);
+  }
+  void Print(std::ostream & os) const;
+
+private:
+  /// Valid Destination Sequence Number flag
+  bool m_validSeqNo;
+  /// Destination Sequence Number, if m_validSeqNo = true
+  uint32_t m_seqNo;
+  /// Hop Count (number of hops needed to reach destination)
+  uint16_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;
+
+  /// List of precursors
+  std::vector<Ipv4Address> m_precursorList;
+  /// When I can send another request
+  Time m_routeRequestTimout;
+  /// Number of route requests
+  uint8_t m_reqCount;
+  /// Indicate if this entry is in "blacklist"
+  bool m_blackListState;
+  /// Time for which the node is put into the blacklist
+  Time m_blackListTimeout;
+};
+
+/**
+ * \ingroup aodv
+ * \brief The Routing table used by AODV protocol
+ */
+class RoutingTable
+{
+public:
+  /// c-tor
+  RoutingTable (Time t);
+  ///\name Handle life time of invalid route
+  //\{
+  Time GetBadLinkLifetime () const { return m_badLinkLifetime; }
+  void SetBadLinkLifetime (Time t) { m_badLinkLifetime = t; }
+  //\}
+  /**
+   * 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);
+  /// Update routing table
+  bool Update (RoutingTableEntry & rt);
+  /// Set routing table entry flags
+  bool SetEntryState (Ipv4Address dst, RouteFlags state);
+  /// Lookup routing entries with next hop Address dst and not empty list of precursors.
+  void GetListOfDestinationWithNextHop (Ipv4Address nextHop, std::map<Ipv4Address, uint32_t> & unreachable);
+  /**
+   *   Update routing entries with this destinations as follows:
+   *  1. The destination sequence number of this routing entry, if it
+   *     exists and is valid, is incremented.
+   *  2. The entry is invalidated by marking the route entry as invalid
+   *  3. The Lifetime field is updated to current time plus DELETE_PERIOD.
+   */
+  void InvalidateRoutesWithDst (std::map<Ipv4Address, uint32_t> const & unreachable);
+  /// 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 and invalidate valid entry if Lifetime is expired
+  void Purge ();
+  /** Mark entry as unidirectional (e.g. add this neighbor to "blacklist" for blacklistTimeout period)
+   * \param neighbor - neighbor address link to which assumed to be unidirectional
+   * \param blacklistTimeout - time for which the neighboring node is put into the blacklist
+   * \return true on success
+   */
+  bool MarkLinkAsUnidirectional(Ipv4Address neighbor, Time blacklistTimeout);
+  /// Print routing table
+  void Print(std::ostream &os);
+
+private:
+  std::map<Ipv4Address, RoutingTableEntry> m_ipv4AddressEntry;
+  /// Deletion time for invalid routes
+  Time m_badLinkLifetime;
+};
+
+}}
+
+#endif /* AODV_RTABLE_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv-test-suite.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,554 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+#include "ns3/test.h"
+#include "aodv-neighbor.h"
+#include "aodv-packet.h"
+#include "aodv-rqueue.h"
+#include "aodv-rtable.h"
+#include "ns3/ipv4-route.h"
+
+namespace ns3
+{
+namespace aodv
+{
+
+/// Unit test for neighbors
+struct NeighborTest : public TestCase
+{
+  NeighborTest () : TestCase ("Neighbor"), neighbor (0) { }
+  virtual bool DoRun ();
+  void Handler (Ipv4Address addr);
+  void CheckTimeout1 ();
+  void CheckTimeout2 ();
+  void CheckTimeout3 ();
+  Neighbors * neighbor;
+};
+
+void
+NeighborTest::Handler (Ipv4Address addr)
+{
+}
+
+void
+NeighborTest::CheckTimeout1 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), true, "Neighbor exists");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), true, "Neighbor exists");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists");
+}
+void
+NeighborTest::CheckTimeout2 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), true, "Neighbor exists");
+}
+void
+NeighborTest::CheckTimeout3 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.1.1.1")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("2.2.2.2")), false, "Neighbor doesn't exist");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("3.3.3.3")), false, "Neighbor doesn't exist");
+}
+
+bool
+NeighborTest::DoRun ()
+{
+  Neighbors nb (Seconds (1));
+  neighbor = &nb;
+  neighbor->SetCallback (MakeCallback (&NeighborTest::Handler, this));
+  neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (1));
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("4.3.2.1")), false, "Neighbor doesn't exist");
+  neighbor->Update (Ipv4Address ("1.2.3.4"), Seconds (10));
+  NS_TEST_EXPECT_MSG_EQ (neighbor->IsNeighbor (Ipv4Address ("1.2.3.4")), true, "Neighbor exists");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("1.2.3.4")), Seconds (10), "Known expire time");
+  NS_TEST_EXPECT_MSG_EQ (neighbor->GetExpireTime (Ipv4Address ("4.3.2.1")), Seconds (0), "Known expire time");
+  neighbor->Update (Ipv4Address ("1.1.1.1"), Seconds (5));
+  neighbor->Update (Ipv4Address ("2.2.2.2"), Seconds (10));
+  neighbor->Update (Ipv4Address ("3.3.3.3"), Seconds (20));
+
+  Simulator::Schedule (Seconds (2), &NeighborTest::CheckTimeout1, this);
+  Simulator::Schedule (Seconds (15), &NeighborTest::CheckTimeout2, this);
+  Simulator::Schedule (Seconds (30), &NeighborTest::CheckTimeout3, this);
+  Simulator::Run ();
+  Simulator::Destroy ();
+  
+  return GetErrorStatus ();
+}
+//-----------------------------------------------------------------------------
+struct TypeHeaderTest : public TestCase
+{
+  TypeHeaderTest () : TestCase ("AODV TypeHeader") 
+  {
+  }
+  virtual bool DoRun ()
+  {
+    TypeHeader h (AODVTYPE_RREQ);
+    NS_TEST_EXPECT_MSG_EQ (h.IsValid (), true, "Default header is valid");
+    NS_TEST_EXPECT_MSG_EQ (h.Get (), AODVTYPE_RREQ, "Default header is RREQ");
+
+    Ptr<Packet> p = Create<Packet> ();
+    p->AddHeader (h);
+    TypeHeader h2 (AODVTYPE_RREP);
+    uint32_t bytes = p->RemoveHeader (h2);
+    NS_TEST_EXPECT_MSG_EQ (bytes, 1, "Type header is 1 byte long");
+    NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for RREQ
+struct RreqHeaderTest : public TestCase
+{
+  RreqHeaderTest () : TestCase ("AODV RREQ") 
+  {
+  }
+  virtual bool DoRun ()
+  {
+    RreqHeader h (/*flags*/0, /*reserved*/0, /*hopCount*/6, /*requestID*/1, /*dst*/Ipv4Address ("1.2.3.4"),
+                  /*dstSeqNo*/40, /*origin*/Ipv4Address ("4.3.2.1"), /*originSeqNo*/10);
+    NS_TEST_EXPECT_MSG_EQ (h.GetGratiousRrep (), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 6, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetId (), 1, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 40, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 10, "trivial");
+
+    h.SetGratiousRrep (true);
+    NS_TEST_EXPECT_MSG_EQ (h.GetGratiousRrep (), true, "trivial");
+    h.SetDestinationOnly (true);
+    NS_TEST_EXPECT_MSG_EQ (h.GetDestinationOnly (), true, "trivial");
+    h.SetUnknownSeqno (true);
+    NS_TEST_EXPECT_MSG_EQ (h.GetUnknownSeqno (), true, "trivial");
+    h.SetDst (Ipv4Address ("1.1.1.1"));
+    NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial");
+    h.SetDstSeqno (5);
+    NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 5, "trivial");
+    h.SetHopCount (7);
+    NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 7, "trivial");
+    h.SetId (55);
+    NS_TEST_EXPECT_MSG_EQ (h.GetId (), 55, "trivial");
+    h.SetOrigin (Ipv4Address ("4.4.4.4"));
+    NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial");
+    h.SetOriginSeqno (23);
+    NS_TEST_EXPECT_MSG_EQ (h.GetOriginSeqno (), 23, "trivial");
+
+    Ptr<Packet> p = Create<Packet> ();
+    p->AddHeader (h);
+    RreqHeader h2;
+    uint32_t bytes = p->RemoveHeader (h2);
+    NS_TEST_EXPECT_MSG_EQ (bytes, 23, "RREP is 23 bytes long");
+    NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
+    
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for RREP
+struct RrepHeaderTest : public TestCase
+{
+  RrepHeaderTest () : TestCase ("AODV RREP") {}
+  virtual bool DoRun ()
+  {
+    RrepHeader h (/*prefixSize*/0, /*hopCount*/12, /*dst*/Ipv4Address ("1.2.3.4"), /*dstSeqNo*/2,
+                  /*origin*/Ipv4Address ("4.3.2.1"), /*lifetime*/Seconds (3));
+    NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 0, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 12, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.2.3.4"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 2, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.3.2.1"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (3), "trivial");
+    h.SetDst (Ipv4Address ("1.1.1.1"));
+    NS_TEST_EXPECT_MSG_EQ (h.GetDst (), Ipv4Address ("1.1.1.1"), "trivial");
+    h.SetDstSeqno (123);
+    NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 123, "trivial");
+    h.SetOrigin (Ipv4Address ("4.4.4.4"));
+    NS_TEST_EXPECT_MSG_EQ (h.GetOrigin (), Ipv4Address ("4.4.4.4"), "trivial");
+    h.SetLifeTime (MilliSeconds (1200));
+    NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), MilliSeconds (1200), "trivial");
+    h.SetAckRequired (true);
+    NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), true, "trivial");
+    h.SetAckRequired (false);
+    NS_TEST_EXPECT_MSG_EQ (h.GetAckRequired (), false, "trivial");
+    h.SetPrefixSize (2);
+    NS_TEST_EXPECT_MSG_EQ (h.GetPrefixSize (), 2, "trivial");
+    h.SetHopCount (15);
+    NS_TEST_EXPECT_MSG_EQ (h.GetHopCount (), 15, "trivial");
+
+    h.SetHello (Ipv4Address ("10.0.0.2"), 9, Seconds (15));
+    NS_TEST_EXPECT_MSG_EQ (h.GetDst (), h.GetOrigin (), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetDstSeqno (), 9, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetLifeTime (), Seconds (15), "trivial");
+
+    Ptr<Packet> p = Create<Packet> ();
+    p->AddHeader (h);
+    RrepHeader h2;
+    uint32_t bytes = p->RemoveHeader (h2);
+    NS_TEST_EXPECT_MSG_EQ (bytes, 19, "RREP is 19 bytes long");
+    NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for RREP-ACK
+struct RrepAckHeaderTest : public TestCase
+{
+  RrepAckHeaderTest () : TestCase ("AODV RREP-ACK")
+  {
+  }
+  virtual bool DoRun()
+  {
+    RrepAckHeader h;
+    Ptr<Packet> p = Create<Packet> ();
+    p->AddHeader (h);
+    RrepAckHeader h2;
+    uint32_t bytes = p->RemoveHeader(h2);
+    NS_TEST_EXPECT_MSG_EQ (bytes, 1, "ACK is 1 byte long");
+    NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for RERR
+struct RerrHeaderTest : public TestCase
+{
+  RerrHeaderTest () : TestCase ("AODV RERR")
+  {
+  }
+  virtual bool DoRun()
+  {
+    RerrHeader h;
+    h.SetNoDelete(true);
+    NS_TEST_EXPECT_MSG_EQ(h.GetNoDelete(), true, "trivial");
+    Ipv4Address dst = Ipv4Address("1.2.3.4");
+    NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst, 12), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ(h.GetDestCount(), 1, "trivial");
+    NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst, 13), true, "trivial");
+    Ipv4Address dst2 = Ipv4Address("4.3.2.1");
+    NS_TEST_EXPECT_MSG_EQ(h.AddUnDestination(dst2, 12), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ(h.GetDestCount(), 2, "trivial");
+
+    Ptr<Packet> p = Create<Packet> ();
+    p->AddHeader (h);
+    RerrHeader h2;
+    uint32_t bytes = p->RemoveHeader(h2);
+    NS_TEST_EXPECT_MSG_EQ (bytes, h.GetSerializedSize(), "(De)Serialized size match");
+    NS_TEST_EXPECT_MSG_EQ (h, h2, "Round trip serialization works");
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for AODV routing table entry
+struct QueueEntryTest : public TestCase
+{
+  QueueEntryTest () : TestCase ("QueueEntry") {}
+  void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
+  void Error (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
+  void Unicast2 (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
+  void Error2 (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
+  virtual bool DoRun()
+  {
+    Ptr<const Packet> packet = Create<Packet> ();
+    Ipv4Header h;
+    h.SetDestination (Ipv4Address ("1.2.3.4"));
+    h.SetSource (Ipv4Address ("4.3.2.1"));
+    Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&QueueEntryTest::Unicast, this);
+    Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&QueueEntryTest::Error, this);
+    QueueEntry entry (packet, h, ucb, ecb, Seconds (1));
+    NS_TEST_EXPECT_MSG_EQ (h.GetDestination (),  entry.GetIpv4Header ().GetDestination (), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (h.GetSource (),  entry.GetIpv4Header ().GetSource (), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (ucb.IsEqual(entry.GetUnicastForwardCallback ()), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (ecb.IsEqual(entry.GetErrorCallback ()), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (1), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (entry.GetPacket (), packet, "trivial");
+    entry.SetExpireTime (Seconds (3));
+    NS_TEST_EXPECT_MSG_EQ (entry.GetExpireTime (), Seconds (3), "trivial");
+    Ipv4Header h2;
+    h2.SetDestination(Ipv4Address ("1.1.1.1"));
+    entry.SetIpv4Header (h2);
+    NS_TEST_EXPECT_MSG_EQ (entry.GetIpv4Header ().GetDestination (), Ipv4Address ("1.1.1.1"), "trivial");
+    Ipv4RoutingProtocol::UnicastForwardCallback ucb2 = MakeCallback (&QueueEntryTest::Unicast2, this);
+    Ipv4RoutingProtocol::ErrorCallback ecb2 = MakeCallback (&QueueEntryTest::Error2, this);
+    entry.SetErrorCallback (ecb2);
+    NS_TEST_EXPECT_MSG_EQ (ecb2.IsEqual (entry.GetErrorCallback ()), true, "trivial");
+    entry.SetUnicastForwardCallback (ucb2);
+    NS_TEST_EXPECT_MSG_EQ (ucb2.IsEqual (entry.GetUnicastForwardCallback ()), true, "trivial");
+
+    return GetErrorStatus();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for RequestQueue
+struct AodvRqueueTest : public TestCase
+{
+  AodvRqueueTest () : TestCase ("Rqueue"), q (64, Seconds (30)) {}
+  virtual bool DoRun ();
+  void Unicast (Ptr<Ipv4Route> route, Ptr<const Packet> packet, const Ipv4Header & header) {}
+  void Error (Ptr<const Packet>, const Ipv4Header &, Socket::SocketErrno) {}
+  void CheckSizeLimit ();
+  void CheckTimeout ();
+
+  RequestQueue q;
+};
+
+bool
+AodvRqueueTest::DoRun ()
+{
+  NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 64, "trivial");
+  q.SetMaxQueueLen (32);
+  NS_TEST_EXPECT_MSG_EQ (q.GetMaxQueueLen (), 32, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (30), "trivial");
+  q.SetQueueTimeout (Seconds(10));
+  NS_TEST_EXPECT_MSG_EQ (q.GetQueueTimeout (), Seconds (10), "trivial");
+
+  Ptr<const Packet> packet = Create<Packet> ();
+  Ipv4Header h;
+  h.SetDestination (Ipv4Address ("1.2.3.4"));
+  h.SetSource (Ipv4Address ("4.3.2.1"));
+  Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&AodvRqueueTest::Unicast, this);
+  Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&AodvRqueueTest::Error, this);
+  QueueEntry e1 (packet, h, ucb, ecb, Seconds (1));
+  q.Enqueue (e1);
+  q.Enqueue (e1);
+  q.Enqueue (e1);
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.1.1.1")), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 1, "trivial");
+  q.DropPacketWithDst (Ipv4Address ("1.2.3.4"));
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("1.2.3.4")), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "trivial");
+
+  h.SetDestination (Ipv4Address ("2.2.2.2"));
+  QueueEntry e2 (packet, h, ucb, ecb, Seconds (1));
+  q.Enqueue (e1);
+  q.Enqueue (e2);
+  Ptr<Packet> packet2 = Create<Packet> ();
+  QueueEntry e3 (packet2, h, ucb, ecb, Seconds (1));
+  NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address("3.3.3.3"), e3), false, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Dequeue (Ipv4Address ("2.2.2.2"), e3), true, "trivial");
+  NS_TEST_EXPECT_MSG_EQ (q.Find (Ipv4Address ("2.2.2.2")), false, "trivial");
+  q.Enqueue (e2);
+  q.Enqueue (e3);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
+  Ptr<Packet> packet4 = Create<Packet> ();
+  h.SetDestination (Ipv4Address ("1.2.3.4"));
+  QueueEntry e4 (packet4, h, ucb, ecb, Seconds (20));
+  q.Enqueue (e4);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 3, "trivial");
+  q.DropPacketWithDst (Ipv4Address ("1.2.3.4"));
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize(), 1, "trivial");
+
+  CheckSizeLimit ();
+
+  Ipv4Header header2;
+  Ipv4Address dst2 ("1.2.3.4");
+  header2.SetDestination (dst2);
+
+  Simulator::Schedule (q.GetQueueTimeout () + Seconds (1), &AodvRqueueTest::CheckTimeout, this);
+
+  Simulator::Run ();
+  Simulator::Destroy ();
+
+  return GetErrorStatus ();
+}
+
+void
+AodvRqueueTest::CheckSizeLimit ()
+{
+  Ptr<Packet> packet = Create<Packet> ();
+  Ipv4Header header;
+  Ipv4RoutingProtocol::UnicastForwardCallback ucb = MakeCallback (&AodvRqueueTest::Unicast, this);
+  Ipv4RoutingProtocol::ErrorCallback ecb = MakeCallback (&AodvRqueueTest::Error, this);
+  QueueEntry e1 (packet, header, ucb, ecb, Seconds (1));
+
+  for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
+    q.Enqueue (e1);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
+
+  for (uint32_t i = 0; i < q.GetMaxQueueLen (); ++i)
+    q.Enqueue (e1);
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 2, "trivial");
+}
+
+void
+AodvRqueueTest::CheckTimeout ()
+{
+  NS_TEST_EXPECT_MSG_EQ (q.GetSize (), 0, "Must be empty now");
+}
+//-----------------------------------------------------------------------------
+/// Unit test for AODV routing table entry
+struct AodvRtableEntryTest : public TestCase
+{
+  AodvRtableEntryTest () : TestCase ("RtableEntry") {}
+  virtual bool DoRun()
+  {
+    Ptr<NetDevice> dev;
+    Ipv4InterfaceAddress iface;
+    RoutingTableEntry rt (/*output device*/dev, /*dst*/Ipv4Address("1.2.3.4"), /*validSeqNo*/true, /*seqNo*/10,
+                          /*interface*/iface, /*hop*/5, /*next hop*/Ipv4Address("3.3.3.3"), /*lifetime*/Seconds(10));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetDestination (), Ipv4Address ("1.2.3.4"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetSeqNo (), 10, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 5, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("3.3.3.3"), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (10), "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), VALID, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 0, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial");
+
+    Ptr<NetDevice> dev2;
+    Ipv4InterfaceAddress iface2;
+    rt.SetOutputDevice (dev2);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetOutputDevice (), dev2, "trivial");
+    rt.SetInterface (iface2);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetInterface (), iface2, "trivial");
+    rt.SetValidSeqNo (false);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetValidSeqNo (), false, "trivial");
+    rt.SetFlag (INVALID);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
+    rt.SetFlag (IN_SEARCH);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), IN_SEARCH, "trivial");
+    rt.SetHop (12);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetHop (), 12, "trivial");
+    rt.SetLifeTime (Seconds (1));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (1), "trivial");
+    rt.SetNextHop (Ipv4Address ("1.1.1.1"));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetNextHop (), Ipv4Address ("1.1.1.1"), "trivial");
+    rt.SetUnidirectional (true);
+    NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial");
+    rt.SetBalcklistTimeout (Seconds (7));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetBlacklistTimeout (), Seconds (7), "trivial");
+    rt.SetRreqCnt (2);
+    NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 2, "trivial");
+    rt.IncrementRreqCnt ();
+    NS_TEST_EXPECT_MSG_EQ (rt.GetRreqCnt (), 3, "trivial");
+    rt.Invalidate (Seconds (13));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (13), "trivial");
+    rt.SetLifeTime (Seconds (0.1));
+    NS_TEST_EXPECT_MSG_EQ (rt.GetLifeTime (), Seconds (0.1), "trivial");
+    Ptr<Ipv4Route> route = rt.GetRoute ();
+    NS_TEST_EXPECT_MSG_EQ (route->GetDestination (), Ipv4Address ("1.2.3.4"), "trivial");
+
+    NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.3")), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.1")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.2")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.LookupPrecursor (Ipv4Address ("10.0.0.2")), false, "trivial");
+    std::vector<Ipv4Address> prec;
+    rt.GetPrecursors (prec);
+    NS_TEST_EXPECT_MSG_EQ (prec.size (), 1, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.InsertPrecursor (Ipv4Address ("10.0.0.4")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.DeletePrecursor (Ipv4Address ("10.0.0.5")), false, "trivial");
+    rt.GetPrecursors (prec);
+    NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial");
+    rt.DeleteAllPrecursors ();
+    NS_TEST_EXPECT_MSG_EQ (rt.IsPrecursorListEmpty (), true, "trivial");
+    rt.GetPrecursors (prec);
+    NS_TEST_EXPECT_MSG_EQ (prec.size (), 2, "trivial");
+
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+/// Unit test for AODV routing table
+struct AodvRtableTest : public TestCase
+{
+  AodvRtableTest () : TestCase ("Rtable") {}
+  virtual bool DoRun()
+  {
+    RoutingTable rtable (Seconds (2));
+    NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (2), "trivial");
+    rtable.SetBadLinkLifetime (Seconds (1));
+    NS_TEST_EXPECT_MSG_EQ (rtable.GetBadLinkLifetime (), Seconds (1), "trivial");
+    Ptr<NetDevice> dev;
+    Ipv4InterfaceAddress iface;
+    RoutingTableEntry rt (/*output device*/dev, /*dst*/Ipv4Address("1.2.3.4"), /*validSeqNo*/true, /*seqNo*/10,
+                          /*interface*/iface, /*hop*/5, /*next hop*/Ipv4Address("1.1.1.1"), /*lifetime*/Seconds(10));
+    NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt), false, "trivial");
+    RoutingTableEntry rt2 (/*output device*/dev, /*dst*/Ipv4Address("4.3.2.1"), /*validSeqNo*/false, /*seqNo*/0,
+                           /*interface*/iface, /*hop*/15, /*next hop*/Ipv4Address("1.1.1.1"), /*lifetime*/Seconds(1));
+    NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt2), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (rt2.GetDestination (), rt), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt2.GetDestination (), rt.GetDestination (), "trivial");
+    rt.SetHop (20);
+    rt.InsertPrecursor (Ipv4Address ("10.0.0.3"));
+    NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial");
+    RoutingTableEntry rt3;
+    NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("10.0.0.1"), rt), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt3), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("10.0.0.1"), INVALID), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("1.2.3.4"), IN_SEARCH), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("5.5.5.5")), false, "trivial");
+    RoutingTableEntry rt4 (/*output device*/dev, /*dst*/Ipv4Address ("5.5.5.5"), /*validSeqNo*/false, /*seqNo*/0,
+                           /*interface*/iface, /*hop*/15, /*next hop*/Ipv4Address ("1.1.1.1"), /*lifetime*/Seconds (-10));
+    NS_TEST_EXPECT_MSG_EQ (rtable.AddRoute (rt4), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.SetEntryState (Ipv4Address ("5.5.5.5"), INVALID), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("5.5.5.5"), rt), false, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.MarkLinkAsUnidirectional (Ipv4Address ("1.2.3.4"), Seconds (2)), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("1.2.3.4"), rt), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.IsUnidirectional (), true, "trivial");
+    rt.SetLifeTime (Seconds (-5));
+    NS_TEST_EXPECT_MSG_EQ (rtable.Update (rt), true, "trivial");
+    std::map<Ipv4Address, uint32_t> unreachable;
+    rtable.GetListOfDestinationWithNextHop (Ipv4Address ("1.1.1.1"), unreachable);
+    NS_TEST_EXPECT_MSG_EQ (unreachable.size (), 2, "trivial");
+    unreachable.insert (std::make_pair (Ipv4Address ("4.3.2.1"), 3));
+    rtable.InvalidateRoutesWithDst (unreachable);
+    NS_TEST_EXPECT_MSG_EQ (rtable.LookupRoute (Ipv4Address ("4.3.2.1"), rt), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rt.GetFlag (), INVALID, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), true, "trivial");
+    NS_TEST_EXPECT_MSG_EQ (rtable.DeleteRoute (Ipv4Address ("1.2.3.4")), false, "trivial");
+
+    return GetErrorStatus ();
+  }
+};
+//-----------------------------------------------------------------------------
+class AodvTestSuite : public TestSuite
+{
+public:
+  AodvTestSuite () : TestSuite ("routing-aodv", UNIT)
+  {
+    AddTestCase (new NeighborTest);
+    AddTestCase (new TypeHeaderTest);
+    AddTestCase (new RreqHeaderTest);
+    AddTestCase (new RrepHeaderTest);
+    AddTestCase (new RrepAckHeaderTest);
+    AddTestCase (new RerrHeaderTest);
+    AddTestCase (new QueueEntryTest);
+    AddTestCase (new AodvRqueueTest);
+    AddTestCase (new AodvRtableEntryTest);
+    AddTestCase (new AodvRtableTest);
+  }
+} g_aodvTestSuite;
+
+}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/aodv.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on 
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ * 
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef AODV_H
+#define AODV_H
+
+/**
+ * \ingroup routing
+ * \defgroup aodv AODV
+ * 
+ * This model implements the base specification of the Ad hoc on demand distance vector (AODV)
+ * protocol. Implementation is based on RFC3561.
+ *
+ * Class aodv::RoutingProtocol implements all functionality of service packet exchange and inherits Ipv4RoutingProtocol. 
+ * Base class defines two virtual functions for packet routing and forwarding.  The first one,
+ * RouteOutput(), is used for locally originated packets, and the second one, RouteInput(), is used for forwarding
+ * and/or delivering received packets.
+ *
+ * Protocol operation depends on the many adjustable parameters. Parameters for this functionality are attributes of
+ * aodv::RoutingProtocol. We support parameters, with their default values, from RFC and parameters that enable/disable
+ * protocol features, such as broadcasting HELLO messages, broadcasting data packets and so on.
+ *
+ * AODV discovers routes on demand. Therefore, our AODV model  buffer all packets, while a route request packet (RREQ)
+ * is disseminated. We implement a packet queue in aodv-rqueue.cc. Smart pointer to packet, Ipv4RoutingProtocol::ErrorCallback,
+ * Ipv4RoutingProtocol::UnicastForwardCallback and IP header are stored in this queue. The packet queue implements garbage collection of old
+ * packets and a queue size limit.
+ *
+ * Routing table implementation support garbage collection of old entries and state machine, defined in standard.
+ * It implements as a STL map container. The key is a destination IP address.
+ *
+ * Some moments of protocol operation aren't described in RFC. This moments generally concern cooperation of different OSI model layers.
+ * We use following heuristics:
+ * 
+ * 1) This AODV implementation can detect the presence of unidirectional links and avoid them if necessary.
+ *    If the node we received a RREQ for is a neighbor we are probably facing a unidirectional link... 
+ *    This heuristic is taken from AODV-UU implementation and can be disabled.
+ *    
+ * 2) Protocol operation strongly depends on broken link detection mechanism. We implements two such heuristics.
+ *    First, this implementation support  HELLO messages. However HELLO messages are not a good way to do neighbor sensing
+ *    in a wireless environment (at least not over 802.11). Therefore, you may experience bad performance when running over wireless.
+ *    There are several reasons for this:
+ *      -# HELLO messages are broadcasted. In 802.11, broadcasting is done at a lower bit rate than unicasting,
+ *         thus HELLO messages travel further than data.
+ *      -# HELLO messages are small, thus less prone to bit errors than data transmissions.
+ *      -# Broadcast transmissions are not guaranteed to be bidirectional, unlike unicast transmissions.
+ *    Second, we use layer 2 feedback when possible. Link considered to be broken, if frame transmission results in a transmission 
+ *    failure for all retries. This mechanism meant for active links and work much more faster, than first method.
+ *    Layer 2 feedback implementation relies on TxErrHeader trace source, currently it is supported in AdhocWifiMac only.
+ *    
+ * 3) Duplicate packet detection. We use special class dpd::DuplicatePacketDetection for this purpose.
+ *
+ * Following optional protocol optimizations aren't implemented:
+ *  - Expanding ring search.
+ *  - Local link repair.
+ *  - RREP, RREQ and HELLO message extensions.
+ * This techniques require direct access to IP header, which contradict assertion from AODV RFC that AODV works over UDP. Our model use UDP
+ * for simplicity, but this disable us to implement protocol optimizations. We don't use low layer raw socket, because they are not portable.
+ *
+ */
+
+#endif /* AODV_H */
Binary file src/routing/manet/aodv/test/aodv-chain-regression-test-0-0.pcap has changed
Binary file src/routing/manet/aodv/test/aodv-chain-regression-test-1-0.pcap has changed
Binary file src/routing/manet/aodv/test/aodv-chain-regression-test-2-0.pcap has changed
Binary file src/routing/manet/aodv/test/aodv-chain-regression-test-3-0.pcap has changed
Binary file src/routing/manet/aodv/test/aodv-chain-regression-test-4-0.pcap has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/test/aodv-regression.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,171 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "aodv-regression.h"
+
+#include "ns3/mesh-helper.h"
+#include "ns3/simulator.h"
+#include "ns3/random-variable.h"
+#include "ns3/mobility-helper.h"
+#include "ns3/double.h"
+#include "ns3/uinteger.h"
+#include "ns3/string.h"
+#include "ns3/boolean.h"
+#include "ns3/yans-wifi-helper.h"
+#include "ns3/internet-stack-helper.h"
+#include "ns3/ipv4-address-helper.h"
+#include "ns3/abort.h"
+#include "ns3/udp-echo-helper.h"
+#include "ns3/mobility-model.h"
+#include "ns3/pcap-file.h"
+#include "ns3/aodv-helper.h"
+#include "ns3/v4ping-helper.h"
+#include "ns3/nqos-wifi-mac-helper.h"
+#include <sstream>
+
+/// Set to true to rewrite reference traces, leave false to run regression tests
+const bool WRITE_VECTORS = false;
+
+namespace ns3 {
+namespace aodv {
+//-----------------------------------------------------------------------------
+// Test suite
+//-----------------------------------------------------------------------------
+class AodvRegressionTestSuite : public TestSuite
+{
+public:
+  AodvRegressionTestSuite () : TestSuite ("routing-aodv-regression", SYSTEM) 
+  {
+    AddTestCase (new ChainRegressionTest);
+  }
+} g_aodvRegressionTestSuite;
+ 
+
+//-----------------------------------------------------------------------------
+// ChainRegressionTest
+//-----------------------------------------------------------------------------
+/// Unique PCAP files prefix for this test
+const char * const ChainRegressionTest::PREFIX = "aodv-chain-regression-test";
+
+ChainRegressionTest::ChainRegressionTest () : TestCase ("AODV chain regression test"),
+  m_nodes (0),
+  m_time (Seconds (10)),
+  m_size (5),
+  m_step (120)
+{
+}
+
+ChainRegressionTest::~ChainRegressionTest ()
+{
+  delete m_nodes;
+}
+
+bool
+ChainRegressionTest::DoRun ()
+{
+  SeedManager::SetSeed(12345);
+  CreateNodes ();
+  CreateDevices ();
+  
+  // At m_time / 3 move central node away and see what will happen
+  Ptr<Node> node = m_nodes->Get (m_size / 2);
+  Ptr<MobilityModel> mob = node->GetObject<MobilityModel> ();
+  Simulator::Schedule (m_time / Scalar(3.0), &MobilityModel::SetPosition, mob, Vector (1e5, 1e5, 1e5));
+
+  Simulator::Stop (m_time);
+  Simulator::Run ();
+  Simulator::Destroy ();
+  
+  if (!WRITE_VECTORS) CheckResults ();
+  
+  delete m_nodes, m_nodes = 0;
+  return GetErrorStatus ();
+}
+
+void
+ChainRegressionTest::CreateNodes ()
+{
+  m_nodes = new NodeContainer;
+  m_nodes->Create (m_size);
+  MobilityHelper mobility;
+  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
+                                "MinX", DoubleValue (0.0),
+                                "MinY", DoubleValue (0.0),
+                                "DeltaX", DoubleValue (m_step),
+                                "DeltaY", DoubleValue (0),
+                                "GridWidth", UintegerValue (m_size),
+                                "LayoutType", StringValue ("RowFirst"));
+  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
+  mobility.Install (*m_nodes);
+}
+
+void
+ChainRegressionTest::CreateDevices ()
+{
+  // 1. Setup WiFi
+  NqosWifiMacHelper wifiMac = NqosWifiMacHelper::Default ();
+  wifiMac.SetType ("ns3::AdhocWifiMac");
+  YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
+  YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
+  wifiPhy.SetChannel (wifiChannel.Create ());
+  WifiHelper wifi = WifiHelper::Default ();
+  wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager", "DataMode", StringValue ("wifia-6mbs"), "RtsCtsThreshold", StringValue ("2200"));
+  NetDeviceContainer devices = wifi.Install (wifiPhy, wifiMac, *m_nodes); 
+  
+  // 2. Setup TCP/IP & AODV
+  AodvHelper aodv; // Use default parameters here
+  InternetStackHelper internetStack;
+  internetStack.SetRoutingHelper (aodv);
+  internetStack.Install (*m_nodes);
+  Ipv4AddressHelper address;
+  address.SetBase ("10.1.1.0", "255.255.255.0");
+  Ipv4InterfaceContainer interfaces = address.Assign (devices);
+  
+  // 3. Setup ping
+  V4PingHelper ping (interfaces.GetAddress (m_size - 1));
+  ping.SetAttribute ("Verbose", BooleanValue (false)); // don't need verbose ping in regression test
+  ApplicationContainer p = ping.Install (m_nodes->Get (0));
+  p.Start (Seconds (0));
+  p.Stop (m_time);
+  
+  // 4. write PCAP
+  std::string prefix = (WRITE_VECTORS ? NS_TEST_SOURCEDIR : GetTempDir ()) + PREFIX;
+  wifiPhy.EnablePcapAll (prefix);
+}
+
+void
+ChainRegressionTest::CheckResults ()
+{
+  for (uint32_t i = 0; i < m_size; ++i)
+    {
+      std::ostringstream os1, os2;
+      // File naming conventions are hard-coded here.
+      os1 << NS_TEST_SOURCEDIR << PREFIX << "-" << i << "-0.pcap";
+      os2 << GetTempDir () << PREFIX << "-" << i << "-0.pcap";
+      
+      uint32_t sec(0), usec(0);
+      bool diff = PcapFile::Diff (os1.str(), os2.str(), sec, usec);
+      NS_TEST_EXPECT_MSG_EQ (diff, false, "PCAP traces " << os1.str() << " and " << os2.str() 
+                                       << " differ starting from " << sec << " s " << usec << " us");
+    }
+}
+
+}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/test/aodv-regression.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,184 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef AODVREGRESSION_H_
+#define AODVREGRESSION_H_
+
+#include "ns3/test.h"
+#include "ns3/nstime.h"
+#include "ns3/node-container.h"
+
+namespace ns3 {
+namespace aodv {
+
+/**
+ * \ingroup aodv
+ * 
+ * \brief AODV chain regression test
+ *
+ * This script creates 1-dimensional grid topology and then ping last node from the first one:
+ *
+ * [10.1.1.1] <-- step --> [10.1.1.2] <-- step --> [10.1.1.3] <-- step --> [10.1.1.4] <-- step --> [10.1.1.5]
+ *
+ * Each node can hear only his right and his left neighbor, if they exist. When one third of total time expired,
+ * central node moves away. After this, node 3 doesn't hear any packets from other nodes and nobody hears his packets.
+ * We want to demonstrate in this script
+ * 1) route establishing
+ * 2) broken link detection both from layer 2 information and hello messages.
+ * 
+ * \verbatim
+ Expected packets time diagram.
+           1       2       3       4       5
+    <------|------>|       |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=0, ID=1, org_seqno=1) src = 10.1.1.1
+           |<------|------>|       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=1, ID=1, org_seqno=1) src = 10.1.1.2
+           |       |<------|------>|       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=2, ID=1, org_seqno=1) src = 10.1.1.3
+           |       |       |<------|------>|        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, U=1, hop=3, ID=1, org_seqno=1) src = 10.1.1.4
+           |       |       |       |<------|------> ARP request. Who has 10.1.1.4? Tell 10.1.1.5
+           |       |       |       |======>|        ARP reply
+           |       |       |       |<======|        RREP (orig 10.1.1.1, dst 10.1.1.5, hop=0, dst_seqno=0) src=10.1.1.5
+           |       |       |<------|------>|        ARP request. Who has 10.1.1.3? Tell 10.1.1.4
+           |       |       |======>|       |        ARP reply
+           |       |       |<======|       |        RREP (orig 10.1.1.1, dst 10.1.1.5, hop=1, dst_seqno=0) src=10.1.1.4
+           |       |<------|------>|       |        ARP request. Who has 10.1.1.2? Tell 10.1.1.3
+           |       |======>|       |       |        ARP reply
+           |       |<======|       |       |        RREP (orig 10.1.1.1, dst 10.1.1.5, hop=2, dst_seqno=0) src=10.1.1.3
+           |<------|------>|       |       |        ARP request. Who has 10.1.1.1? Tell 10.1.1.2
+           |======>|       |       |       |        ARP reply
+           |<======|       |       |       |        RREP (orig 10.1.1.1, dst 10.1.1.5, hop=3, dst_seqno=0) src=10.1.1.2
+   <-------|------>|       |       |       |        ARP request. Who has 10.1.1.2? Tell 10.1.1.1
+           |<======|       |       |       |
+           |======>|       |       |       |        ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.1 next_hop=10.1.1.2
+           |<------|------>|       |       |        ARP request. Who has 10.1.1.3? Tell 10.1.1.2
+           |       |<======|       |       |        ARP reply
+           |       |======>|       |       |        ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.2 next_hop=10.1.1.3
+           |       |<------|------>|       |        ARP request. Who has 10.1.1.4? Tell 10.1.1.3
+           |       |       |<======|       |        ARP reply
+           |       |       |======>|       |        ICMP (ping) request 0 from 10.1.1.1 to 10.1.1.5; src=10.1.1.3 next_hop=10.1.1.4
+           |       |       |<------|------>|        ARP request. Who has 10.1.1.5? Tell 10.1.1.4
+           |       |       |       |<======|        ARP reply
+           |       |       |       |======>|        ICMP (ping) request 0; src=10.1.1.4 next_hop=10.1.1.5
+           |       |       |       |<======|        ICMP (ping) reply 0; src=10.1.1.5 next_hop=10.1.1.4
+           |       |       |<======|       |        ICMP (ping) reply 0; src=10.1.1.4 next_hop=10.1.1.3
+           |       |<======|       |       |        ICMP (ping) reply 0; src=10.1.1.3 next_hop=10.1.1.2
+           |<======|       |       |       |        ICMP (ping) reply 0; src=10.1.1.2 next_hop=10.1.1.1
+           |       |       |       |<------|------> Hello
+           |<------|------>|       |       |        Hello
+    <------|------>|       |       |       |        Hello
+           |       |<------|------>|       |        Hello
+           |======>|       |       |       |        ICMP (ping) request 1; src=10.1.1.1 next_hop=10.1.1.2
+           |       |       |<------|------>|        Hello
+           |       |======>|       |       |        ICMP (ping) request 1; src=10.1.1.2 next_hop=10.1.1.3
+           |       |       |======>|       |        ICMP (ping) request 1; src=10.1.1.3 next_hop=10.1.1.4
+           |       |       |       |======>|        ICMP (ping) request 1; src=10.1.1.4 next_hop=10.1.1.5
+           |       |       |       |<======|        ICMP (ping) reply 1; src=10.1.1.5 next_hop=10.1.1.4
+           |       |       |<======|       |        ICMP (ping) reply 1; src=10.1.1.4 next_hop=10.1.1.3
+           |       |<======|       |       |        ICMP (ping) reply 11; src=10.1.1.3 next_hop=10.1.1.2
+           |<======|       |       |       |        ICMP (ping) reply 1; src=10.1.1.2 next_hop=10.1.1.1
+           |       |       |       |<------|------> Hello
+           |<------|------>|       |       |        Hello
+    <------|------>|       |       |       |        Hello
+           |       |       |<------|------>|        Hello
+           |       |<------|------>|       |        Hello
+           |======>|       |       |       |        ICMP (ping) request 2; src=10.1.1.1 next_hop=10.1.1.2
+           |       |======>|       |       |        ICMP (ping) request 2; src=10.1.1.2 next_hop=10.1.1.3
+           |       |       |======>|       |        ICMP (ping) request 2; src=10.1.1.3 next_hop=10.1.1.4
+           |       |       |       |======>|        ICMP (ping) request 2; src=10.1.1.4 next_hop=10.1.1.5
+           |       |       |       |<======|        ICMP (ping) reply 2; src=10.1.1.5 next_hop=10.1.1.4
+           |       |       |<======|       |        ICMP (ping) reply 2; src=10.1.1.4 next_hop=10.1.1.3
+           |       |<======|       |       |        ICMP (ping) reply 2; src=10.1.1.3 next_hop=10.1.1.2
+           |<======|       |       |       |        ICMP (ping) reply 2; src=10.1.1.2 next_hop=10.1.1.1
+           |       |       |       |<------|------> Hello
+    <------|------>|       |       |       |        Hello
+           |       |<------|------>|       |        Hello
+           |<------|------>|       |       |        Hello
+           |       |       |<------|------>|        Hello
+           |======>|       |       |       |        ICMP (ping) request 3; src=10.1.1.1 next_hop=10.1.1.2
+           |       |======>|       |       |        ICMP (ping) request 3; src=10.1.1.2 next_hop=10.1.1.3
+           |       |       |======>|       |        ICMP (ping) request 3; src=10.1.1.3 next_hop=10.1.1.4
+           |       |       |       |======>|        ICMP (ping) request 3; src=10.1.1.4 next_hop=10.1.1.5
+           |       |       |       |<======|        ICMP (ping) reply 3; src=10.1.1.5 next_hop=10.1.1.4
+           |       |       |<======|       |        ICMP (ping) reply 3; src=10.1.1.4 next_hop=10.1.1.3
+           |       |<======|       |       |        ICMP (ping) reply 3; src=10.1.1.3 next_hop=10.1.1.2
+           |<======|       |       |       |        ICMP (ping) reply 3; src=10.1.1.2 next_hop=10.1.1.1
+           |       |       |       |<------|------> Hello
+    <------|------>|       |       |       |        Hello
+           |<------|-->    |       |       |        Hello   |
+           |       |    <--|-->    |       |        Hello   |Node 3 move away => nobody hear his packets and node 3 doesn't hear anything !
+           |       |       |    <--|------>|        Hello   |
+           |======>|       |       |       |        ICMP (ping) request 4; src=10.1.1.1 next_hop=10.1.1.2
+           |       |==>    |       |       |        ICMP (ping) request 4; src=10.1.1.2 next_hop=10.1.1.3.   7 retries.
+           |<======|       |       |       |        RERR (unreachable dst 10.1.1.3 & 10.1.1.5) src=10.1.1.2
+           |       |       |       |<------|------> Hello
+    <------|------>|       |       |       |        Hello
+           |<------|-->    |       |       |        Hello
+           |       |    <--|-->    |       |        Hello
+           |       |       |    <--|------>|        Hello
+    <------|------>|       |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=2, org_seqno=2) src = 10.1.1.1
+           |<------|-->    |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=2, org_seqno=1) src = 10.1.1.2
+           |       |       |       |<------|------> Hello
+           |       |       |    <--|------>|        Hello
+           |       |    <--|-->    |       |        Hello
+    <------|------>|       |       |       |        Hello
+    <------|------>|       |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=3, org_seqno=3) src = 10.1.1.1
+           |<------|-->    |       |       |        Hello
+           |<------|-->    |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=3, org_seqno=3) src = 10.1.1.2
+           |       |       |       |======>|        RERR (unreachable dst 10.1.1.1 & 10.1.1.3) src=10.1.1.4
+           |       |       |       |<------|------> Hello
+           |       |       |    <--|------>|        Hello
+           |       |    <--|-->    |       |        Hello
+           |<------|-->    |       |       |        Hello
+    <------|------>|       |       |       |        Hello
+    <------|------>|       |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=0, ID=4, org_seqno=4) src = 10.1.1.1
+           |<------|-->    |       |       |        RREQ (orig 10.1.1.1, dst 10.1.1.5, G=1, hop=1, ID=4, org_seqno=4) src = 10.1.1.2
+
+..................................................................
+ * \endverbatim
+ */
+class ChainRegressionTest : public TestCase
+{
+public:
+  ChainRegressionTest ();
+  ~ChainRegressionTest ();  
+private:
+  /// Unique PCAP files prefix for this test
+  static const char * const PREFIX;
+  /// XXX It is important to have pointers here
+  NodeContainer * m_nodes;
+  
+  /// Total simulation time
+  const Time m_time;
+  /// Chain size
+  const uint32_t m_size;
+  /// Chain step, meters
+  const double m_step;
+  
+  /// Create test topology
+  void CreateNodes ();
+  /// Create devices, install TCP/IP stack and applications
+  void CreateDevices ();
+  /// Compare traces with reference ones
+  void CheckResults ();
+  /// Go
+  bool DoRun ();
+};
+
+}
+}
+#endif /* AODVREGRESSION_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/waf	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/aodv/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -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('aodv', ['internet-stack', 'contrib'])
+    module.includes = '.'
+    module.source = [
+        'aodv-rtable.cc',
+        'aodv-rqueue.cc',
+        'aodv-packet.cc',
+        'aodv-neighbor.cc',
+        'aodv-routing-protocol.cc',
+        'aodv-test-suite.cc',
+        'test/aodv-regression.cc',
+        ]
+
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'aodv'
+    headers.source = [
+        'aodv-rtable.h',
+        'aodv-rqueue.h',
+        'aodv-packet.h',
+        'aodv-neighbor.h',
+        'aodv-routing-protocol.h',
+        ]
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/dpd.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,50 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#include "dpd.h"
+
+namespace ns3
+{
+namespace dpd
+{
+
+bool
+DuplicatePacketDetection::IsDuplicate  (Ptr<const Packet> p, const Ipv4Header & header)
+{
+  return m_idCache.IsDuplicate (header.GetSource (), p->GetUid() );
+}
+void
+DuplicatePacketDetection::SetLifetime (Time lifetime)
+{
+  m_idCache.SetLifetime(lifetime);
+}
+
+Time
+DuplicatePacketDetection::GetLifetime () const
+{
+  return m_idCache.GetLifeTime();
+}
+
+
+}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/dpd.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,59 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef DUPLICATEPACKETDETECTION_H_
+#define DUPLICATEPACKETDETECTION_H_
+
+#include "id-cache.h"
+#include "ns3/nstime.h"
+#include "ns3/packet.h"
+#include "ns3/ipv4-header.h"
+
+namespace ns3
+{
+namespace dpd
+{
+/**
+ * \ingroup dpd
+ * 
+ * \brief Helper class used to remember already seen packets and detect duplicates.
+ */
+class DuplicatePacketDetection
+{
+public:
+  /// C-tor
+  DuplicatePacketDetection (Time lifetime) : m_idCache(lifetime) {}
+  /// Check that the packet is duplicated. If not, save information about this packet.
+  bool IsDuplicate (Ptr<const Packet> p, const Ipv4Header & header);
+  /// Set duplicate records lifetimes
+  void SetLifetime (Time lifetime);
+  /// Get duplicate records lifetimes
+  Time GetLifetime () const;
+private:
+  /// Impl
+  IdCache m_idCache;
+};
+
+}
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/id-cache.cc	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,131 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ *
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+#include "id-cache.h"
+#include "ns3/test.h"
+#include <algorithm>
+
+namespace ns3
+{
+namespace dpd
+{
+bool
+IdCache::IsDuplicate (Ipv4Address addr, uint32_t id)
+{
+  Purge ();
+  for (std::vector<UniqueId>::const_iterator i = m_idCache.begin ();
+      i != m_idCache.end (); ++i)
+    if (i->m_context == addr && i->m_id == id)
+      return true;
+  struct UniqueId uniqueId =
+   { addr, id, m_lifetime + Simulator::Now () };
+   m_idCache.push_back (uniqueId);
+  return false;
+}
+void
+IdCache::Purge ()
+{
+  m_idCache.erase (remove_if (m_idCache.begin (), m_idCache.end (),
+      IsExpired ()), m_idCache.end ());
+}
+
+uint32_t
+IdCache::GetSize ()
+{
+  Purge ();
+  return m_idCache.size ();
+}
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+/// Unit test for id cache
+struct IdCacheTest : public TestCase
+{
+  IdCacheTest () : TestCase ("Id Cache"), cache (Seconds(10))
+  {}
+  virtual bool DoRun();
+  void CheckTimeout1 ();
+  void CheckTimeout2 ();
+  void CheckTimeout3 ();
+
+  IdCache cache;
+};
+
+bool
+IdCacheTest::DoRun ()
+{
+  NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime(), Seconds(10), "Lifetime");
+  NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), false, "Unknown ID & address");
+  NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 4), false, "Unknown ID");
+  NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("4.3.2.1"), 3), false, "Unknown address");
+  NS_TEST_EXPECT_MSG_EQ (cache.IsDuplicate (Ipv4Address ("1.2.3.4"), 3), true, "Known address & ID");
+  cache.SetLifetime(Seconds(15));
+  NS_TEST_EXPECT_MSG_EQ (cache.GetLifeTime(), Seconds(15), "New lifetime");
+  cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4);
+  cache.IsDuplicate (Ipv4Address ("1.1.1.1"), 4);
+  cache.IsDuplicate (Ipv4Address ("2.2.2.2"), 5);
+  cache.IsDuplicate (Ipv4Address ("3.3.3.3"), 6);
+  NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "trivial");
+
+  Simulator::Schedule (Seconds(5), &IdCacheTest::CheckTimeout1, this);
+  Simulator::Schedule (Seconds(11), &IdCacheTest::CheckTimeout2, this);
+  Simulator::Schedule (Seconds(30), &IdCacheTest::CheckTimeout3, this);
+  Simulator::Run ();
+  Simulator::Destroy ();
+  
+  return GetErrorStatus ();
+}
+
+void
+IdCacheTest::CheckTimeout1 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 6, "Nothing expire");
+}
+
+void
+IdCacheTest::CheckTimeout2 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 3, "3 records left");
+}
+
+void
+IdCacheTest::CheckTimeout3 ()
+{
+  NS_TEST_EXPECT_MSG_EQ (cache.GetSize (), 0, "All records expire");
+}
+//-----------------------------------------------------------------------------
+class IdCacheTestSuite : public TestSuite
+{
+public:
+  IdCacheTestSuite () : TestSuite ("routing-id-cache", UNIT)
+  {
+    AddTestCase (new IdCacheTest);
+  }
+} g_idCacheTestSuite;
+
+}}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/id-cache.h	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,86 @@
+/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
+/*
+ * Copyright (c) 2009 IITP RAS
+ *
+ * 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
+ *
+ * Based on
+ *      NS-2 AODV model developed by the CMU/MONARCH group and optimized and
+ *      tuned by Samir Das and Mahesh Marina, University of Cincinnati;
+ *
+ *      AODV-UU implementation by Erik Nordström of Uppsala University
+ *      http://core.it.uu.se/core/index.php/AODV-UU
+ *
+ * Authors: Elena Buchatskaia <borovkovaes@iitp.ru>
+ *          Pavel Boyko <boyko@iitp.ru>
+ */
+
+#ifndef IDCACHE_H_
+#define IDCACHE_H_
+
+#include "ns3/ipv4-address.h"
+#include "ns3/simulator.h"
+#include <vector>
+
+namespace ns3
+{
+namespace dpd
+{
+/**
+ * \ingroup dpd
+ * 
+ * \brief Unique packets identification cache used for simple duplicate detection.
+ */
+class IdCache
+{
+public:
+  /// c-tor
+  IdCache (Time lifetime): m_lifetime (lifetime) {}
+  /// Check that entry (addr, id) exists in cache. Add entry, if it doesn't exist.
+  bool IsDuplicate (Ipv4Address addr, uint32_t id);
+  /// Remove all expired entries
+  void Purge ();
+  /// Return number of entries in cache
+  uint32_t GetSize ();
+  /// Set lifetime for future added entries.
+  void SetLifetime (Time lifetime) { m_lifetime = lifetime; }
+  /// Return lifetime for existing entries in cache
+  Time GetLifeTime () const { return m_lifetime; }
+private:
+  /// Unique packet ID
+  struct UniqueId
+  {
+    /// ID is supposed to be unique in single address context (e.g. sender address)
+    Ipv4Address m_context;
+    /// The id
+    uint32_t m_id;
+    /// When record will expire
+    Time m_expire;
+  };
+  struct IsExpired
+  {
+    bool operator() (const struct UniqueId & u) const
+    {
+      return (u.m_expire < Simulator::Now ());
+    }
+  };
+  /// Already seen IDs
+  std::vector<UniqueId> m_idCache;
+  /// Default lifetime for ID records
+  Time m_lifetime;
+};
+
+}
+}
+#endif /* IDCACHE_H_ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/waf	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,1 @@
+exec "`dirname "$0"`"/../../../../waf "$@"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/routing/manet/dpd/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -0,0 +1,17 @@
+## -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
+
+def build(bld):
+    module = bld.create_ns3_module('dpd', ['contrib'])
+    module.includes = '.'
+    module.source = [
+        'id-cache.cc',
+		'dpd.cc'
+        ]
+
+    headers = bld.new_task_gen('ns3header')
+    headers.module = 'dpd'
+    headers.source = [
+        'dpd.h',
+        'id-cache.h',
+        ]
+
--- a/src/wscript	Tue Nov 24 20:37:29 2009 +0100
+++ b/src/wscript	Tue Nov 24 20:38:21 2009 +0100
@@ -32,6 +32,8 @@
     'routing/global-routing',
     'routing/static-routing',
     'routing/list-routing',
+    'routing/manet/aodv',
+    'routing/manet/dpd',
     'mobility',
     'devices/wifi',
     'helper',
--- a/test.py	Tue Nov 24 20:37:29 2009 +0100
+++ b/test.py	Tue Nov 24 20:38:21 2009 +0100
@@ -114,6 +114,7 @@
     ("routing/simple-point-to-point-olsr", "True", "True"),
     ("routing/simple-routing-ping6", "True", "True"),
     ("routing/static-routing-slash32", "True", "True"),
+    ("routing/aodv", "True", "True"),
 
     ("stats/wifi-example-sim", "True", "True"),